Les cookies

Ce qu'il faut savoir
Maintenant que vous avez vaguement acquis quelques bases de programmation, retournons à nos moutons, c'est-à-dire au javascript.

C'est quoi un "cookie" ? C'est juste une possibilité de stocker une ou plusieurs informations chez votre visiteur. L'exemple le plus éculé consiste à lui demander son prénom à sa premième visite, puis de le saluer avec "une page personnalisée" à son retour (un bête "Bonjour machin, c'est votre n-ème visite" impressionne déjà les gogos). Mais il y a des limites à ce mécanisme (pas à celui de la bêtise):

  • Un navigateur peut refuser les cookies ou ne pas savoir quoi en faire.
  • Le nombre de cookies acceptés n'excédera pas les 300, dans tous les cas.
  • Chaque cookie ne peut dépasser la taille de 4000 caractères.
  • Un navigateur n'accepte normalement que 20 cookies par adresse (par exemple, 20 cookies différents pour l'ensemble des gens de chez "chez.com").
  • Un navigateur peut se "purger" de vos cookie même si la date d'expiration n'est pas encore dépassée.
  • Le format correct d'un cookie est: nom=valeur;[expires=date;]
  • Si on ne donne pas une date d'expiration, le cookie n'est valable que pour la session courante.
  • Si ont veut utiliser des caratères "spéciaux" ou des espaces, il faut passer par des routines de codage/décodage: escape() et unescape().
  • Internet explorer 6 n'accepte plus les cookies sauf s'ils sont garantits "Respect de la vie privée" au moyen d'un mécanisme et d'une charte supplémentaire (voir: P3P chez http://www.w3.org/P3P/usep3p.html ou sur un moteur de recherche).
Bref, ne comptez pas trop là dessus, sauf si vous fournissez des prestations qui nécéssitent vraiment l'utilisation de ce mécanisme et que vos visiteurs apprécient suffisement ce "plus" pour valider ou ne pas purger leur fichier de cookies.

La démarche
La bonne marche à suivre, si l'on voulait écrire un programme correct, serait de tester si le navigateur accepte les cookies, puis s'il n'a pas déjà celui que vous projetez de lui envoyer, et enfin de lui envoyer s'il ne l'a pas et qu'il les accepte, ou d'utiliser une autre solution dans le cas contraire.

Comme actuellement (janvier 2000) à peu prêt 50 % de vos visiteurs viendront sur votre site avec msie et environ 30 % avec netscape et le tout sous windows, vous pouvez éventuellement choisir de vous passer de la première partie des opérations, les gens de ces plateformes étants des habitués de longue date de programmes mal écrits, de toutes sortes d'incohérences, et de "votre machin ne possède pas le bidule version x.xxx, vous devez absolument dépenser votre fric pour une mise à jour" ou autres "le disque dur est plein, changez de pentium".

Quant à moi, je vais comme d'habitude essayer de faire les choses le plus correctement possible, car heureusement il n'est pas question de "bizness" ici, mais d'informatique.


La pratique
J'avais espéré trouver une propriété qui me dit éventuellement si le navigateur accepte les cookies, genre "navigator.enabledPlugin" ou autre "navigator.properties", mais bon, pour le moment je n'ai rien trouvé, alors il va falloir s'en passer et travailler comme un cochon.

Ensuite pour essayer de lire le cookie il faut utiliser l'objet.propriété "document.cookie" qui malheureusement pointe sur une liste de cookies et pas sur un simple élément, il va encore falloir parcourir cette liste à la recherche du bon.

Pour ça on va créer une routine du genre:


function donnecookie(nom)
{
  var recherche=nom+'=';                    // pour recherche nom dans la liste
  if (document.cookie.length>0)             // si il existe des cookies
  {
    position=document.cookie.indexOf(recherche);   // donne la position du nom
    if (position!=-1)                              // si une position existe
      {
        position=position+recherche.length;        // on passe après nom=
        fin=document.cookie.indexOf(';',position); // on cherche la fin (";")
        if (fin==-1)                               // si le ";" n'existe pas
        {
          fin=document.cookie.length;       // alors le cookie va jusqu'au bout
        }
        return unescape(document.cookie.substring(position,fin));// donne texte
      }
      else {return '';}                     // retourne du 'vide'
  }
  else {return '';}                         // retourne du 'vide'
}

Cette routine fournit juste le texte du cookie de nom donné (et pas sa date d'expiration) ou rien du tout si il n'est pas trouvé. Notez l'utilisation de la fonction unescape() qui vous permet entre autre d'utiliser le point virgule, les espaces et tous les autres caractères spéciaux dans vos cookies sans vous casser la tête (pour une fois).

Notez aussi que le test de position se fait avec -1, vu que la position 0 est parfaitement valide et correspond à la première position dans la chaîne de caractères, car comme pour les tableaux, la numérotation de position part de zéro.

Attention ! La routine donnecookie() n'est pas assez intelligente telle-quelle pour faire la différence entre "texte=" et "contexte=" si vous cherchez le mot "texte" le premier cookie entré contenant cette fin de chaîne de caractères sera fournit en retour, prenez donc garde au nom de vos cookies ou perfectionnez vous-même cette routine.

Bon, on à lu le cookie, ou on ne l'a pas lu et il va falloir l'écrire (éventuellement après avoir demandé quelques infos au visiteur dans un bête formulaire, avec ou sans validation, c'est vos oignons), pour faire ça, je me suis encore retroussé les manches et il ne vous reste plus qu'à utiliser cette autre belle fonction, fournie gratuitement par votre serviteur:


function ecritcookie(nom,texte,jours)       // les beaux paramètres
{
  var datecourante=new Date();              // lit la date
  var expires=new Date();
  expires.setTime(datecourante.getTime()+1000*60*60*24*jours);
  document.cookie=nom+'='+escape(texte)+'; expires='+expires.toGMTString();
}

Plusieurs remarques me semblent indispensables avant les explications que vous êtes en droit d'attendre pour cette routine.

  • On peut facilement mettre le foutoir dans le fichier cookie en ajoutant ou pas un ou plusieurs ";" sans encoder.
  • Personne n'est là pour vous obliger à respecter le format ci-dessus, mais heureusement, si l'on veut que le navigateur enregistre le cookie, il faut une date d'expiration correcte et bien délimitée selon les règles ci-dessus.
  • Si vous vous plantez en écrivant un cookie et en faisant vos tests, vous pouvez le réécrire avec une date dépassée, arrêter et relancer le navigateur, voire dans les cas extrêmes effacer le fichier cookie.txt.
  • Si le nom de votre cookie est "toto", pas de problème, il n'y aura pas de conflit avec un toto à une autre adresse, ou même dans une autre page, ce sont les cookies du document que vous lisez et écrivez, pas ceux de l'ensemble des pages visitées par le navigateur, l'avantage c'est que vous n'êtes pas limité à un cookie par page, mais toutes les autres limitations restent valables, et l'inconvénient grâve, c'est que vous ne pourrez pas vous servir des cookies pour passer des valeurs d'une page à l'autre (c'est pas moi qui fait les règles, désolé).
  • Ce qui est réellement rajouté au fichier cookie c'est "toto=ce_que_vous_avez_mis_dans_le_texte", les informations de provenance et de date sont encodées et illisibles.

Et maintenant la routine:

  • On lit la date courante que l'on met dans datecourante (original non ?).
  • On crée une autre variable qui contiendra la date d'expiration.
  • On change ensuite la valeur de la date d'expiration (expire.setTime()) en lui ajoutant la valeur de la date courante (datecourante.getTime()) plus un nombre de jours de validité, le format de la date étant en millisecondes (millièmes de seconde), on le multiplie par 1000 pour avoir des secondes, puis par 60 pour avoir des minutes, puis par 60 pour avoir des heures, puis par 24 pour avoir des jours, puis par 365 pour avoir des années, heu non, les jours ça suffit (vous pouvez directement utiliser *86400000 maintenant que vous avez compris), et enfin par le nombre de jours de validité désirés. Si vous ne souhaitez pas que votre cookie soit enregistré, donnez-lui une date de validité expirée avec "-1" jours en paramètre.
  • Et on écrit le cookie au format correct et en le "codant" avec escape() pour éviter les ennuis.

Pour utiliser les deux routines:


var taille='';
taille=donnecookie('tailledelafenetrepage1');
if (taille=='') {ecritcookie('tailledelafenetrepage1','640x480',365);}

Attention au nom du cookie qui n'est pas codé et qui ne peut pas contenir de point virgule, d'espace ni d'autres symboles bizzaroïdes, le "texte" lui, peut bien sur contenir des tas de chose (puisqu'il est codé dans ce cas précis), comme des listes séparées par des virgules ou des réglages comme "bgcolor='#000000',color='#FFFFFF',sound='coincoin.mid', etc...", faites en bon usage.

Si vous avez besoin des 4000 caractères disponibles et que vous ne mettez que des chiffres et des lettres sans espace, n'encodez (et ne décodez) pas le cookie, en effet cette fonction utilise 3 caractères pour le prix d'un.

Voilà, vous savez tout sur les cookies...


Encore un exemple ?
Bandes de petits canailloux, je vous ai habitué à être bien trop gâté, il va falloir que ça change, bon alors rien qu'un petit exemple et totalement inutile en plus, ça vous forcera à réfléchir par vous-même pour l'adapter.

Au besoin rechargez la page après avoir entré votre pseudo, ce rechargement est automatique avec un navigateur récent (netscape ou msie 4 et plus).


Et vous voulez encore des explications ?
Vous êtes plutôt gourmand, mais comme je ne souhaite pas recevoir une avalanche d'insultes, je cède à la violence, mais ne venez pas pleurer après parce que vous aurez perdu l'habitude d'utiliser votre cerveau.

<SCRIPT LANGUAGE="Javascript">            // Quelque part dans la page web
<!-- ;
var data='';
var data=donnecookie('donneesvisiteur');  // Essaye de lire le cookie
if (data=='')                             // Si pas trouvé ou vide
{
  ecritcookie('test','test',1);           // Ecrit un cookie de test
  if (donnecookie('test')!='test')        // Si on ne peut pas relire
  {
    document.writeln('<P><CENTER><H2>Vous n\'acceptez
    pas les cookies, l\'exemple ne peut pas fonctionner.</H2><
    /CENTER>');
  }
  else                                    // Si on peut le relire
  {
    ecritcookie('test','test',-1);        // On efface le cookie test
    document.writeln('
    <FORM>Tapez votre pseudo:             // On demande le pseudo
    <INPUT TYPE=\"TEXT\" NAME=\"nom\" onChange=\"testenom(this)\">
    </FORM>');                            // Et on va en routine testenon
  }
}
else                                      // Si le cookie existait déjà
{
  document.writeln('                      // (suite dessous, pas de ";")
  OUELCOME '+data+' in ze...');           // On utilise le contenu du cookie
  document.writeln('                      // On permet aussi de l'effacer
  <FORM onSubmit=\"kill()\">              // en cas d'erreur avec la routine
  <INPUT TYPE=\"SUBMIT\" VALUE=\" kill \">// kill()
  </FORM>');                              // depuis un simple bouton submit
}
// -->
</SCRIPT>                                 // Et si javascript n'est pas actif
<NOSCRIPT><P><CENTER>
<H2>Désolé vous n'avez pas Javascript 1.2 ou celui-ci n'est pas activé
dans vos préférences, vous ne pouvez donc pas voir l'exemple.</H2>
</CENTER></NOSCRIPT>

Reste encore deux routines, "testenom()" et "kill()", qu'il faudra placer entre <HEAD> et </HEAD>, sans oublier "donnecookie()" et "ecritcookie()".


function testenom(pseudo)                 // Recupère le nom de l'objet
{
  ecritcookie('donneesvisiteur',pseudo.value,20);  // contenu pour 20 jours
}
function kill()
{
  ecritcookie('donneesvisiteur','',-1);            // contenu='' date-1 jour
}
function init()                           // Pour la propreté/compatibilité
{
  nom='';                                 // Initialisation de toutes les
  texte='';                               // variables du programmes
  jours=1;                                // ne pas oublier de rajouter
  pseudo='';                              // dans <BODY>
  data='';                                // le onload="init();"
}

Il n'était pas vraiment nécessaire d'écrire toute une routine pour testenom(), mais bon, ça permet de rajouter des tests pour valider le pseudo ou autres bricoles, on aurait pu aussi passer le nombre de jours de validité en paramètre mais bref, quand à kill() c'était encore moins nécessaire, mais c'est plus clair comme ça, à vous de choisir vos méthodes.

Et puisque nous sommes tombés si bas, ne reculons devant aucune bassesse supplémentaire, si vous voulez faire croire que votre site est très fréquenté, vous pouvez insérer un simple: if (Math.random()>0.5){alert('Ce pseudo est déjà utilisé, essayez en un autre...');} et même à augmenter le taux d'échec à 0.8 ou 0.9 pour faire croire qu'il est vraiment très très fréquenté.

Rappel: Ce pseudo s'écrit dans la machine du visiteur, si vous voulez vraiment le comparer, il vous faudra enregister aussi tous les pseudos sur le serveur qui héberge vos pages au moyen d'un script cgi-bin, d'une base de donnée ou de Javascript serveur et de quelques programmes ou plugins de plus, ceci ne sera certainement pas gratuit, et de plus nécessitera au moins l'emploi d'un kilo de tranxène, ou vingt kilos de chanvre indien haché fin et de 2354 feuilles de papier à cigarettes (comptez 3000 pour les maladroits), bref ceci dépasse largement le cadre de ce guide et peut nuire à votre santé, n'insistez pas.


Évitez les indigestions
Ne vous forcez quand même pas à remplir chacune de vos page avec 4000 caractères de "celui qui lit est bête", si vous partagez un serveur vous ne ferez que pénaliser les autres et augmenter inutilement le temps de chargement de vos pages.

RetourInfo Suite

Dernière mise à jour de cette page: 14/06/2002, visiteurs: depuis le 6 avril 2002