IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

XMLRAD Discussion :

Délai d'expiration des cookies


Sujet :

XMLRAD

  1. #21
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    encore une autre trouvaille si je met 0 dans XMLC_LoginTimeOut, il faut que je mette dans la fonction LoginBeforeXMLGRAM la modif suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      Expiration := Now+(StrToIntDef(XMLApplication.InitParams.GetValue('XMLC_LoginTimeOut'), 720) / (24 * 60)) + 0.00001;
    Et là cela fonctionne. Est ce correct ? ou toujours pareil un truc bizarre qui fais que je cache un autre problème ?

    Merci pour vos commentaires
    Michel

  2. #22
    RDM
    RDM est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 424
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 424
    Points : 2 927
    Points
    2 927
    Par défaut
    c'est une erreur de ma part, je suis allé trop vite.
    d'ailleurs si on regarde le code conprend tout de suite:

    l'expiration est calculé avec Now + quelquechose
    Or pour faire un cookie de session comme je l'indique dans la FAQ il faut que l'expiration soit à 0.
    don cpour le XMLC_LoginTimeOut ca ne fonctionne pas.
    je met a jour la FAQ
    RDM
    Tout Est Relatif
    Rubrique XMLRAD: http://xmlrad.developpez.com
    FAQ XMLRAD: http://xmlrad.developpez.com/faq/

  3. #23
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    Oui je viens de m'en rendre compte que cela fonctionne pas. En lisant ta faq j'essaye de l'adapter au process de sécurité que tu as poster dans les news et je me retrouve coincer car je ne sais pas (question de débutant certe) :
    1) Où placer le AddCookie ? (je l'ai mis lorsque l'utilisateur ce connecte avec comme ligne de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    XMLRequest.AddCookie('XMLC_UsrID', Context.GetValue('USR_ID'), Context.GetValue('XMLC_Host'), XMLApplication.InitParams.GetValue('XMLC_CookiesPath'), 0);
    2) Quand je fais le test de couper IE et de relancer mon URL je suis toujours loggé....

    Merci pour ton aide
    Michel

  4. #24
    RDM
    RDM est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 424
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 424
    Points : 2 927
    Points
    2 927
    Par défaut
    c'est surtout la session (XMLC_Session) qu'il faut stocker dans le cookie car c'est la dessus qu'est testé l'authentification.
    RDM
    Tout Est Relatif
    Rubrique XMLRAD: http://xmlrad.developpez.com
    FAQ XMLRAD: http://xmlrad.developpez.com/faq/

  5. #25
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    Ok je viens de faire la modification.

    Mais quand je suis dans la fonction "Authenticate" détournée pour aller chercher les informations dans la base de données et que fais le test avec XMLC_SESSION(cookie) et USR_SESSION (stockée en base) : ils sont identiques apres avoir couper et relancer IE.

    Peut être que je fais le mauvais test ?

    Merci encore de ton aide.

    Michel

  6. #26
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    A l'aide au secours

    En faite je viens de m'apercevoir que XMLC_Cookiespath est vide alors j'ai mis
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /ProjectsBin/{$XMLC_InstanceName}/Bin/monappli.dll/
    et j'ai retesté mais toujours le même résultat : je reste loggé apres voir couper IE

    Michel

  7. #27
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    En faite c'est bon j'ai trouvé le souci, en regardant le code dans XMLRAD fichier XMLSecurityWM.pas la fonction SetLoginCookies qui en faite fais le boulot de la mise en place du cookie donc pas besoin de s'embêter d'ajouter un AddCookie.

    Il faut juste de ne pas faire comme moi de ne pas oublier de mettre la variable XMLC_LoginTimeOut à 0 dans le fichier initparams.xml.

    Et pour être complet, d'enlever le test sur l'expiration (là je fais référence au tutorial de RDM) car sinon à chaque lien cela part dans le formulaire de login.

    Dites moi si je ne dis pas de bêtises car ils me font tourner en bourrique ses cookies !!! 8)

    Michel

  8. #28
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    Fausse joie je me suis encore fais avoir avec le path ... donc j'ai toujours le même problème.

    Michel

  9. #29
    RDM
    RDM est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 424
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 424
    Points : 2 927
    Points
    2 927
    Par défaut
    il ne faut pas utiliser SetLoginCookies du SecurityWM.pas
    il faut qu'il soit courcircuité.
    c'est à toi de mettre le cookie de session avec une expiration à 0.
    RDM
    Tout Est Relatif
    Rubrique XMLRAD: http://xmlrad.developpez.com
    FAQ XMLRAD: http://xmlrad.developpez.com/faq/

  10. #30
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    Citation Envoyé par RDM
    il ne faut pas utiliser SetLoginCookies du SecurityWM.pas
    il faut qu'il soit courcircuité.
    c'est à toi de mettre le cookie de session avec une expiration à 0.
    Bein justement le code est en dehors du courcircuitage des hooks ... je vais essayer de mettre le code en commentaire et je vous donne le résultat

    Michel

  11. #31
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    Juste ce message pour vous dire que je viens d'essayer et que c'est toujours pareille rien n'y fais j'ai même mis en commentaire le SetLoginCookies du module SecurityWM.pas car cette ligne de code n'est pas courcicuité par le XMLC_SkipLoginAuthentication mais uniquement par XMLC_SkipLogin.

    Là je suis dans le noir le plus complet...

    Michel

  12. #32
    RDM
    RDM est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 424
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 424
    Points : 2 927
    Points
    2 927
    Par défaut
    peux tu donner le code que tu as fait dans le "MyLogin" cad le hook ?
    RDM
    Tout Est Relatif
    Rubrique XMLRAD: http://xmlrad.developpez.com
    FAQ XMLRAD: http://xmlrad.developpez.com/faq/

  13. #33
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    C'est super inspiré de ton tutorial et je pense que mon collègue a posté le même bout de code dans un autre poste mais bon le voici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    procedure TSecurity.SLELoginBeforeXMLGram(XMLGram: IXMLGram; InputDoc,
      OutputDoc: IXMLCursor; var Skip: Boolean);
    var
      Session: WideString;
      Expiration: TDateTime;
    begin
      if Context.Values['UserName'] = '' then
      begin
        raise Exception.Create('ERR_EMAIL_NULL');
      end;
      Context.Values['USR_NAME'] := Context.Values['UserName'];
      Context.Values['USR_PASSWORD'] := Context.Values['Password'];
      XMLCollection.DBExtract('qryUSRPwd');
      if Context.Values['USR_ID'] = '' then
      begin
        raise Exception.Create('ERR_LOGIN_FAILED');
      end;
      XMLCollection.DBExtract('qryUSRAuthorized');
      if Context.Values['USR_AUTHORIZED'] = '0' then
      begin
        raise Exception.Create('ERR_LOGIN_NOT_AUTHORIZED');
      end;
     
      Session := WideUpperCase(MD5(FloatToStr(Now)));
      // Prepare for Cookies
      Context.Values['XMLC_UserID'] := Context.Values['USR_ID'];
      Context.Values['XMLC_UserName'] := Context.Values['USR_NAME'];
      Context.Values['XMLC_Session'] := Session;
      // Prepare for update DB Session + Expiration
      Context.Values['USR_SESSION'] := Session;
      Expiration := Now+StrToIntDef(XMLApplication.InitParams.GetValue('XMLC_LoginTimeOut'), 720) / (24 * 60) + 0.00001;
      Context.Values['USR_EXPIRATION'] := FloatToStr(Expiration);
      XMLCollection.DBBatch('qryUpdateUSRSession');
      XMLRequest.AddCookie('XMLC_Session', Session, '', Context.GetValue('XMLC_CookiesPath'), 0);
      Context.Values['XMLC_SkipLoginAuthentication'] := '1';
    end;
    Et pour le check:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
     
    procedure TSecurity.SAECollectionEventsAuthenticate(
      XMLCollection: IXMLCollection; e: TAuthenticateEventArgs);
    var
      Database: TDacDatabase;
      Session: WideString;
      SAVEUSR_NAME: WideString;
      SAVEUSR_ID: WideString;
      USR_NAME: WideString;
      Expiration: TDateTime;
    begin
      if XMLApplication.InitParams.Values['XMLC_Design'] <> '1' then
      begin
        SAVEUSR_ID   := Context.Values['USR_ID'];
        SAVEUSR_NAME := Context.Values['USR_NAME'];
        Database := (XMLCollection as IXMLCollection2).GetDatabaseComponent('SAE');
        if not Database.Connected then
        begin
          Database.Connected := True;
        end;
        Database.StartTransaction;
        try
          try
            e.Handled := True;
            USR_NAME := Context.Values['XMLC_UserName'];
            Session := Context.Values['XMLC_Session'];
            Context.Values['USR_NAME'] := USR_NAME;
            Context.Values['USR_SESSION'] := Session;
            XMLCollection.DBExtract('qryUSRSession');
            if Context.Values['USR_ID'] =  '' then
            begin
              Context.Values['XMLC_Authenticated'] := '0';
              XMLRequest.RaiseError('XMLC_AUTHENTICATION_REQUIRED', 'TSecurity.SAECollectionEventsAuthenticate');
            end;
            (*
            Expiration := StrToFloatDef(Context.Values['USR_EXPIRATION'], 0);
            if Expiration < Now then
            begin
              Context.Values['XMLC_Authenticated'] := '0';
              XMLRequest.RaiseError('XMLC_AUTHENTICATION_REQUIRED', 'TSecurity.SAECollectionEventsAuthenticate');
            end;
            *)
            Context.Values['XMLC_Authenticated'] := '1';
            Context.Values['USR_ID'] := SAVEUSR_ID;
            Context.Values['USR_NAME'] := SAVEUSR_NAME;
          except
            Database.Rollback;
            raise;
          end;
        finally
          Database.Commit;
        end;
      end
      else
      begin
        e.Handled := True;
        Context.Values['XMLC_Authenticated'] := '1';
      end;
    end;
    Voila peut être que fais une grosse boulette et que je ne la voie pas !!!

    Merci d'avance,

    Michel

  14. #34
    RDM
    RDM est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 424
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 424
    Points : 2 927
    Points
    2 927
    Par défaut
    il faut pas faire le
    Context.Values['XMLC_SkipLoginAuthentication'] := '1';

    mais Context.Values['XMLC_SkipLogin'] := '1';
    car sinon tu fais le SetLoginCookies qu'il ne faut pas faire car tu veux une expiration à 0

    donc il te faut reprendre le code de SetLoginCookies et tout ce qu'il y a après soit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      XMLRequest.AddCookie('XMLC_Session', Session, '', Context.GetValue('XMLC_CookiesPath'), 0); 
      XMLRequest.SetCookie('XMLC_UserID', Context.GetValue('XMLC_UserID')); 
      XMLRequest.SetCookie('XMLC_UserName', Context.GetValue('XMLC_UserName'));
     
      XMLApplication.LoadProfile(XMLRequest); 
      Context.SetValue('NextAction', 'XMLC_InnerRedirect');
    RDM
    Tout Est Relatif
    Rubrique XMLRAD: http://xmlrad.developpez.com
    FAQ XMLRAD: http://xmlrad.developpez.com/faq/

  15. #35
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    Je viens de réessayer avec le code que tu m'a donné comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
     
      Session := WideUpperCase(MD5(FloatToStr(Now)));
      // Prepare for Cookies
      Context.Values['XMLC_UserID'] := Context.Values['USR_ID'];
      Context.Values['XMLC_UserName'] := Context.Values['USR_NAME'];
      Context.Values['XMLC_Session'] := Session;
      // Prepare for update DB Session + Expiration
      Context.Values['USR_SESSION'] := Session;
      Expiration := Now+StrToIntDef(XMLApplication.InitParams.GetValue('XMLC_LoginTimeOut'), 720) / (24 * 60) + 0.00001;
      Context.Values['USR_EXPIRATION'] := FloatToStr(Expiration);
      XMLCollection.DBBatch('qryUpdateUSRSession');
      XMLRequest.AddCookie('XMLC_Session', Session, '', Context.GetValue('XMLC_CookiesPath'), 0);
      XMLRequest.SetCookie('XMLC_UserID', Context.GetValue('XMLC_UserID'));
      XMLRequest.SetCookie('XMLC_UserName', Context.GetValue('XMLC_UserName'));
      XMLApplication.LoadProfile(XMLRequest);
      Context.SetValue('NextAction', 'XMLC_InnerRedirect');
      Context.Values['XMLC_SkipLogin'] := '1';
    et malheureusement toujours le même symptome : je reste connecté sur mon appli malgré la coupure du navigateur.

    Michel

  16. #36
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    pas d'idée RDM a mon souci .. je sais cela date

    michel

  17. #37
    RDM
    RDM est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 424
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 424
    Points : 2 927
    Points
    2 927
    Par défaut
    non rien de plus, vérifie juste que le cookie XMLC_Session a bien une valeur de 0 avec par exemple le Web Developer de firefox
    RDM
    Tout Est Relatif
    Rubrique XMLRAD: http://xmlrad.developpez.com
    FAQ XMLRAD: http://xmlrad.developpez.com/faq/

  18. #38
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    Voila j'ai fais un AddCookie de XMLC_Session avec la valeur 0.
    Voici avec le web developer ce que je vois dans mon cookie:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    Name	Max-Age
    Value	0
    Host	localhost
    Path	/ProjectsBin/SAE/Bin/SAE.dll/
    Secure	No
    Expires	At End Of Session
     
    Name	XMLC_Session
    Value	1B65F3065CEC2704264BB5C9DC48CEFE
    Host	localhost
    Path	/ProjectsBin/SAE/Bin/SAE.dll/
    Secure	No
    Expires	mardi 21 mars 2006 13:40:18
     
    Name	XMLC_UserID
    Value	1
    Host	localhost
    Path	/ProjectsBin/SAE/Bin/SAE.dll/
    Secure	No
    Expires	lundi 15 décembre 2008 01:40:18
     
    Name	XMLC_UserName
    Value	dba
    Host	localhost
    Path	/ProjectsBin/SAE/Bin/SAE.dll/
    Secure	No
    Expires	lundi 15 décembre 2008 01:40:18
    Value n'est pas à 0 et l'expires non plus ... je fais le test à 00:53

    le code mis dans le LoginBeforeXmlgram est le suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
      if Context.Values['UserName'] = '' then
      begin
        raise Exception.Create('ERR_EMAIL_NULL');
      end;
      Context.Values['USR_NAME'] := Context.Values['UserName'];
      Context.Values['USR_PASSWORD'] := Context.Values['Password'];
      XMLCollection.DBExtract('qryUSRPwd');
      if Context.Values['USR_ID'] = '' then
      begin
        raise Exception.Create('ERR_LOGIN_FAILED');
      end;
      XMLCollection.DBExtract('qryUSRAuthorized');
      if Context.Values['USR_AUTHORIZED'] = '0' then
      begin
        raise Exception.Create('ERR_LOGIN_NOT_AUTHORIZED');
      end;
      Session := WideUpperCase(MD5(FloatToStr(Now)));
      // Prepare for Cookies
      Context.Values['XMLC_UserID'] := Context.Values['USR_ID'];
      Context.Values['XMLC_UserName'] := Context.Values['USR_NAME'];
      Context.Values['XMLC_Session'] := Session;
      // Prepare for update DB Session + Expiration
      Context.Values['USR_SESSION'] := Session;
      XMLRequest.AddCookie('XMLC_Session', Session, '', Context.GetValue('XMLC_CookiesPath'), 0);
      Context.Values['XMLC_SkipLoginAuthentication'] := '1';
    une idée car là je sèche ?

    Merci
    Michel

  19. #39
    RDM
    RDM est déconnecté
    Membre émérite

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 424
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 424
    Points : 2 927
    Points
    2 927
    Par défaut
    il faut que tu fasses
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Context.Values['XMLC_SkipLogin'] := '1';
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Context.Values['XMLC_SkipLoginAuthentication'] := '1';
    car sinon ton cookie est réécrasé par la méthode AfterXMLGRam dans XMLC_Login
    RDM
    Tout Est Relatif
    Rubrique XMLRAD: http://xmlrad.developpez.com
    FAQ XMLRAD: http://xmlrad.developpez.com/faq/

  20. #40
    Membre régulier
    Inscrit en
    Février 2005
    Messages
    154
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 154
    Points : 114
    Points
    114
    Par défaut
    Quand dans le loginBeforeXmlgram je passe XMLC_SkipLogin à 1 au lieu du XMLC_SkipLoginAuthentication à 1 je me retrouve après la saisie de l'utilisateur et du mot de passe sur le service XMLC_Login donc l'utilisateur obtient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
      <?xml version="1.0" encoding="ISO-8859-15" ?> 
    - <document>
      <Params /> 
    - <Aliases>
      <SAEDLL>/ProjectsBin/SAE/Bin/SAE.dll/</SAEDLL> 
      <XMLRADDLL>/XMLRADBin/XMLRAD.dll/</XMLRADDLL> 
      </Aliases>
      </document>
    Peut être qu'il manque une redirection mais je ne vois pas où j'ai fais la boulette

    Michel

Discussions similaires

  1. Expiration des cookies instantanée?
    Par starkson dans le forum ASP.NET
    Réponses: 1
    Dernier message: 18/12/2007, 09h52
  2. Expiration des cookies
    Par Crypt dans le forum ASP.NET
    Réponses: 1
    Dernier message: 30/07/2007, 13h51
  3. date d'expiration des cookies
    Par agrotic dans le forum ASP
    Réponses: 1
    Dernier message: 01/12/2006, 16h22
  4. [JSP SERVLET]Moment d'expiration des objets du scope Request
    Par Little_Goldo dans le forum Servlets/JSP
    Réponses: 6
    Dernier message: 25/08/2005, 13h18
  5. [VB.NET] Expiration de cookie
    Par NicoNGRI dans le forum ASP.NET
    Réponses: 7
    Dernier message: 26/10/2004, 15h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo