CGI - Classe simple pour CGI (Common Gateway Interface)
# script CGI script pour creer un formulaire # puis renvoyer les valeurs fournies.
use CGI qw/:standard/; print header, start_html('Un exemple simple'), h1('Un exemple simple'), start_form, "Quel est votre nom ? ",textfield('nom'),p, "Quels sont les mots cles ?", p, checkbox_group(-name=>'mots', -values=>['eenie','meenie','minie','moe'], -defaults=>['eenie','minie']), p, "Quelle est votre couleur favorite ? ", popup_menu(-name=>'couleur', -values=>['rouge','vert','bleu','chartreuse']),p, submit, end_form, hr;
if (param()) { print "Votre nom est ",em(param('nom')),p, "Les mots cles sont : ",em(join(", ",param('mots'))),p, "Votre couleur favorite est :",em(param('couleur')), hr; }
Cette bibliothèque perl utilise les objets perl5 pour faciliter la création de formulaires Web et permettre l'analyse de leur contenu. Ce package définit des objets CGI, des entités qui contiennent les valeurs de la requête courante ainsi que d'autres variables d'état. En utilisant le méthode de l'objet CGI, vous pouvez examiner les mots-clé et les paramètres envoyés à votre script et créer un formulaire dont les valeurs initiales sont celles de la requête courante (en préservant donc les informations d'état). Le module propose des fonctions pour produire du HTML propre, permettant ainsi de réduire le code nécessaire et les erreurs sous-jacentes. Il intègre aussi des fonctions pour quelques-unes des fonctionnalités les plus avancées des scripts CGI comme le téléchargement de fichiers, les cookies, les feuilles de styles en cascade (CSS - cascading style sheets), le « SERVER PUSH » et les frames.
CGI.pm accepte aussi le style de programmation orienté fonction pour ceux qui n'ont pas besoin des possibilités de l'orienté objet.
La version courante de CGI.pm est disponible à :
http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html ftp://ftp-genome.wi.mit.edu/pub/software/WWW/
CGI.pm propose deux styles de programmation : la programmation orientée objet et la programmation orientée fonction. En programmation orientée objet, vous créez un ou plusieurs objets CGI puis vous utilisez leurs méthodes pour créer les différents éléments de la page. Chaque objet CGI commence avec la liste des paramètres nommés tels qu'ils ont été passés à votre script CGI par le serveur. Vous pouvez modifier ces objets, les sauver dans un fichier ou une base de données et les recréer. Puisque chaque objet correspond à un ``état'' du script CGI et puisque la liste des paramètres de chaque objet est différente de celle des autres, cela vous permet d'enregistrer l'état du script pour le rétablir plus tard.
Par exemple, en utilisant le style de programmation orienté objet, voici comment créer une simple page ``Hello World'' :
#!/usr/local/bin/perl -w use CGI; # chargement du module CGI $q = new CGI; # creation d'un nouvel objet CGI print $q->header, # creation de l'en-tete HTTP $q->start_html('hello world'), # debut du HTML $q->h1('hello world'), # titre de niveau 1 $q->end_html; # fin du HTML
Avec le style de programmation orienté fonction, il existe un objet CGI par défaut avec lequel vous n'aurez que très rarement à interagir. Vous n'aurez qu'à appeler des fonctions pour retrouver les paramètres du CGI, créer des balises HTML, gérer les cookies et ainsi de suite. Cela vous fournit une interface de programmation propre mais limitée à un seul objet CGI à la fois. L'exemple suivant affiche la même page que précédemment mais en utilisant l'interface orientée fonction. Les principales différences sont que vous devez maintenant importer un ensemble de fonctions dans votre espace de nommage (habituellement les fonctions ``standard'') et que vous n'avez pas besoin de créer d'objet CGI.
#!/usr/local/bin/perl use CGI qw/:standard/; # chargement des fonctions standard de CGI print header, # creation de l'en-tete HTTP start_html('hello world'), # debut du HTML h1('hello world'), # titre de niveau 1 end_html; # fin du HTML
Les exemples dans ce document utilisent principalement le style orienté objet. Regardez COMMENT IMPORTER DES FONCTIONS pour trouver des informations importantes concernant la programmation orientée fonction avec CGI.pm.
La plupart des routines de CGI.pm acceptent plusieurs arguments, parfois jusqu'à 20 arguments optionnels ! Pour simplifier l'interface, toutes les routines utilisent un style d'appel par argument nommé qui ressemble à cela :
print $q->header(-type=>'image/gif',-expires=>'+3d');
Chaque nom d'argument est précédé d'un tiret. Ni la casse (majuscules / minuscules) ni l'ordre n'ont d'importance dans la liste d'arguments. -type, -Type et -TYPE sont acceptables. En fait, seul le premier argument doit commencer par un tiret. Si un tiret est présent en tête du premier argument, CGI.pm l'ajoutera si nécessaire à tous les arguments qui suivent.
Plusieurs routines sont couramment appelées avec un seul argument. Dans ce cas,
vous pouvez fournir cet argument sans préciser son nom. header()
est l'une
de ces routines. Dans son cas, son argument unique est le type de document.
print $q->header('text/html');
Les autres routines de ce type sont documentées plus loin.
Certains arguments nommés doivent être des scalaires, d'autres des références
vers un tableaux et d'autres encore des références à une table de
hachage. Parfois, vous pouvez passer n'importe quel type d'argument et la
routine en fera ce qui semblera le plus approprié. Par exemple, la routine
param()
est utilisée pour changer la valeur d'un paramètre CGI à une valeur
simple ou multiple. Les deux cas sont présentés ci-dessous :
$q->param(-name=>'veggie',-value=>'tomato'); $q->param(-name=>'veggie',-value=>['tomato','tomahto','potato','potahto']);
Un grand nombre de routines dans CGI.pm ne sont pas réellement définies dans le module mais plutôt générées automatiquement si besoin. Ce sont les ``raccourcis HTML'', des routines qui génèrent des balises HTML destinées aux pages générées dynamiquement. Les balises HTML ont à la fois des attributs (les paires attribut=``valeur'' à l'intérieur de la balise elle-même) et un contenu (tout ce qu'il y a entre la balise ouvrante et la balise fermante). Par convention, pour distinguer les attributs du contenu, CGI.pm reçoit les attributs HTML comme un premier argument qui est une référence vers une table de hachage et interprète les autres arguments, s'ils existent, comme le contenu. Cela marche de la manière suivante :
Code HTML produit ---- -------------- h1() <H1> h1('some','contents'); <H1>some contents</H1> h1({-align=>left}); <H1 ALIGN="LEFT"> h1({-align=>left},'contents'); <H1 ALIGN="LEFT">contents</H1>
Les balises HTML sont décrites en détails plus loin.
De nombreux nouveaux utilisateurs de CGI.pm restent perplexes devant les différences de convention entre les appels des ``raccourcis HTML'' qui nécessitent des accolades autour des attributs de la balise HTML et les appels des autres routines qui gèrent leurs attributs sans les accolades. Ne vous affolez pas. Pour que ce soit plus pratique, les accolades sont optionnelles pour toutes les routines sauf pour les ``raccourcis HTML''. Si vous voulez, vous pouvez utiliser des accolades à l'appel de n'importe quelle routine qui prend des arguments nommés. Par exemple :
print $q->header( {-type=>'image/gif',-expires=>'+3d'} );
Si vous utilisez l'option -w, vous récupérerez des messages d'avertissement vous indiquant que certains noms d'arguments de CGI.pm sont en conflit avec les fonctions Perl prédéfinies. Le cas le plus fréquent concerne l'argument -values qui est utilisé pour créer des menus à valeurs multiples, des groupes de boutons radio et autres. Pour contourner cet avertissement, vous avez plusieurs choix :
De nombreuses routines utiliseront tout de même les arguments nommés qu'elles ne reconnaissent pas. Par exemple, vous pouvez produire des champs d'en-tête HTTP non standard en fournissant les arguments nommés suivants :
print $q->header(-type => 'text/html', -cost => 'Three smackers', -annoyance_level => 'high', -complaints_to => 'bit bucket');
Cela produira l'en-tête HTTP non standard suivant :
HTTP/1.0 200 OK Cost: Three smackers Annoyance-level: high Complaints-to: bit bucket Content-type: text/html
Vous remarquerez que le caractère souligné (_) est automatiquement transformé en un tiret (-). Les routines de génération de HTML effectuent un autre type de transformation.
Cette fonctionnalité vous permet de vous adapter facilement aux changements fréquents du ``standard'' HTTP.
$query = new CGI;
Cela analysera l'entrée (à la fois pour les méthodes POST et GET) et stockera le résultat dans un objet perl5 appelé $query.
$query = new CGI(INPUTFILE);
Si vous fournissez un descripteur de fichier (filehandle) à la méthode new(),
elle lira les paramètres à partir de ce fichier (ou STDIN ou ce que vous
voulez). Ce fichier peut être sous n'importe laquelle des formes décrites plus
bas (i.e. une série de paires TAG=VALUE délimitées par des passages à la ligne
fonctionnera). Un fichier de ce type est facilement créé par la méthode save()
(voir plus bas). Plusieurs enregistrements peuvent être enregistrés et relus.
Les puristes de Perl seront contents d'apprendre que la méthode accepte aussi les références vers un descripteur de fichier ou même les références vers un type universel (typeglob) référençant un descripteur de fichier, qui est le moyen ``officiel'' pour passer un descripteur de fichier :
$query = new CGI(\*STDIN);
Vous pouvez aussi initialiser l'objet CGI avec un objet Filehandle ou IO::File.
Si vous utilisez l'interface orientée fonction et que vous voulez récupérer l'état de votre objet CGI à partir d'un descripteur de fichier, il vous faudra utiliser restore_parameters(). Cela réinitialisera l'objet CGI à partir du descripteur de fichier fourni.
open (IN,"test.in") || die; restore_parameters(IN); close IN;
Vous pouvez aussi initialiser l'objet requête à partir d'une référence à une table de hachage :
$query = new CGI( {'dinosaur'=>'barney', 'song'=>'I love you', 'friends'=>[qw/Jessica George Nancy/]} );
ou à partir d'une chaîne de requête formatée correctement en tenant compte du codage des caractères dans les URL :
$query = new CGI('dinosaur=barney&color=purple');
ou à partir d'un objet CGI préexistant (actuellement cela clonera la liste des paramètres mais aucun des autres champs spécifiques) :
$old_query = new CGI; $new_query = new CGI($old_query);
Pour créer une requête vide, initialisez la à partir d'une chaîne vide ou d'une table de hachage vide :
$empty_query = new CGI("");
- ou -
$empty_query = new CGI({});
@keywords = $query->keywords
Si le script est appelé comme résultat d'une recherche <ISINDEX>, les mots-clé demandés peuvent être récupérés sous la forme d'un tableau grâce à la méthode keywords().
@names = $query->param
Si le script est appelé avec une liste de paramètres
(e.g. ``name1=value1&name2=value2&name3=value3''), la méthode param()
retournera
une liste composée des noms des paramètres. Si le script est appelé comme un
script <ISINDEX> et contient une chaîne sans esperluette
(e.g. ``value1+value2+value3''), il n'y aura qu'un seul paramètre appelé
``keywords'' et contenant les mots-clé séparés par des ``+''.
REMARQUE : à partir de la version 1.5, le tableau des paramètres nommés retourné devrait être dans le même ordre que celui soumis par le navigateur. En général, cet ordre est le même que l'ordre d'apparition des paramètres dans le formulaire (par contre, cela ne fait pas partie des spécifications et ne peut donc être garanti).
@values = $query->param('foo');
- ou -
$value = $query->param('foo');
Passer un seul argument à la méthode param()
pour obtenir la valeur de ce
paramètre nommé. Si le paramètre est multivalué (e.g. une sélection multiple
dans une liste déroulante), vous pouvez demander à recevoir un tableau. Sinon
la méthode retourne une seule valeur.
Si la valeur n'est pas fournie par la chaîne de requête, comme dans les requêtes ``name1=&name2='' ou ``name1&name2'', elle sera retournée comme une chaîne vide. Cette fonctionnalité existe depuis la version 2.63.
$query->param('foo','un','tableau','de','valeurs');
Cela positionne la valeur du paramètre nommé 'foo' à un tableau de valeurs. C'est l'un des moyens de changer la valeur d'un champ APRÈS une première invocation du script. (Un autre moyen consiste à utiliser l'argument nommé -override qui est accepté par toutes les méthodes qui génèrent des éléments de formulaires.)
param()
reconnaît aussi un style d'appel par argument nommé décrit plus en
détail plus loin :
$query->param(-name=>'foo',-values=>['un','tableau','de','valeurs']);
- ou -
$query->param(-name=>'foo',-value=>'la valeur');
$query->append(-name=>'foo',-values=>['des','valeurs','en plus']);
Cela ajoute une valeur ou une liste de valeurs au paramètre nommé. Les valeurs sont ajoutées à la fin des valeurs précédentes du paramètre nommé si elles existent déjà. Sinon le paramètre est créé. Notez bien que cette méthode ne reconnaît que la syntaxe d'appel par argument nommé.
$query->import_names('R');
Cela crée une série de variables dans l'espace de nommage 'R'. Par exemple $R::foo, @R::foo. Pour une liste de mots-clé, une variable @R::keywords sera créée. Si aucun espace de nommage n'est spécifié, la méthode utilisera l'espace 'Q'. ATTENTION : n'importez rien dans 'main' ; c'est un énorme trou de sécurité !!!!!
Dans les versions précédentes, cette méthode s'appelait import(). Depuis la version 2.20, ce nom a été complètement supprimé pour éviter un conflit avec l'opérateur prédéfini du module Perl import.
$query->delete('foo');
Cela supprimera complètement ce paramètre. Cela est parfois utile pour supprimer certains paramètres que vous ne voulez pas renvoyer entre différents appels du script.
Si vous utilisez l'interface par appel de fonctions, utilisez ``Delete()'' à la place pour éviter un conflit avec l'opérateur Perl prédéfini delete.
$query->delete_all();
Cela effacera complètement tous les paramètres de l'objet CGI. C'est pratique pour s'assurer que ce sont les valeurs par défaut qui seront utilisées lorsque vous créerez votre formulaire.
Utilisez Delete_all()
à la place si vous utilisez l'interface par appel de
fonctions.
$q->param_fetch('address')->[1] = '1313 Mockingbird Lane'; unshift @{$q->param_fetch(-name=>'address')},'George Munster';
Si vous avez besoin d'accéder à la liste des valeurs d'un paramètre d'une manière non prévue par les méthodes précédentes, vous pouvez obtenir une référence directe vers elle en appelant la méthode param_fetch() avec le nom du paramètre. Cela vous renverra un référence vers le tableau des valeurs de ce paramètre que vous pourrez manipuler à votre guise.
Vous pouvez aussi utiliser l'argument nommé -name.
$params = $q->Vars; print $params->{'address'}; @foo = split("\0",$params->{'foo'}); %params = $q->Vars;
use CGI ':cgi-lib'; $params = Vars;
De nombreuses personnes veulent pouvoir accéder à l'ensemble des paramètres
comme si c'était une table de hachage dont les clés sont les noms des
paramètres CGI et dont les valeurs sont les valeurs des paramètres. La méthode
Vars()
fait cela. Appelée dans un contexte scalaire, elle retourne la liste
des paramètres sous la forme d'une référence vers une table de hachage liée
(par tie()). Changer la valeur attachée à une clé changera la valeur du
paramètre CGI qui lui est lié. Appelée dans un contexte de liste, elle
retourne la liste des paramètres comme une table de hachage ordinaire. Cela
vous permet de lire le contenu de la liste des paramètres mais pas d'en
changer les valeurs.
Quand vous utilisez ceci, vous devez faire attention aux paramètres CGI
multivalués. Puisqu'une table de hachage ne peut distinguer le contexte
(scalaire ou liste), les valeurs des paramètres multivalués sont retournées
comme une chaîne compacte où les différentes valeurs sont séparées par le
caractère ``\0'' (null). Vous devez découper (par split())
cette chaîne compacte
pour récupérer les valeurs individuellement. C'est une convention qui a été
introduite il y a bien longtemps par Steve Brenner dans son module cgi-lib.pl
conçu pour Perl version 4.
Si vous voulez utiliser Vars()
comme une fonction, importez l'ensemble de
fonctions :cgi-lib (voir aussi la section concernant la compatibilité
CGI-LIB).
$query->save(FILEHANDLE)
Cela écrira l'état courant du formulaire dans le descripteur de fichier fourni en argument. Vous pouvez le relire en fournissant le même descripteur de fichier à la méthode new(). Remarquez que le descripteur de fichier peut être un fichier, un tube ou n'importe quoi d'autre !
Le format du fichier enregistré est :
NAME1=VALUE1 NAME1=VALUE1' NAME2=VALUE2 NAME3=VALUE3 =
Le nom comme la valeur utilisent le codage des caractères utilisé dans les URL. Les paramètres CGI multivalués sont représentés par un nom répété. Un enregistrement de session est délimité par un symbole = seul. Vous pouvez écrire plusieurs enregistrements successifs puis les relire par plusieurs appels à new. Vous pouvez faire cela dans plusieurs sessions successives en ouvrant le fichier en mode ajout (append). Vous créerez ainsi une espèce de livre d'or simpliste ou un historique des requêtes des utilisateurs. Voici un petit exemple de création d'enregistrement de multiples sessions :
use CGI;
open (OUT,">>test.out") || die; $records = 5; foreach (0..$records) { my $q = new CGI; $q->param(-name=>'counter',-value=>$_); $q->save(OUT); } close OUT;
# reopen for reading open (IN,"test.out") || die; while (!eof(IN)) { my $q = new CGI(IN); print $q->param('counter'),"\n"; }
Le format utilisé pour ce fichier est identique au format d'échange de données ``Boulderio'' du Whitehead Genome Center et peut donc être manipulé et même intégré dans une base de données grâce aux utilitaires de ``Boulderio''. Voir :
http://stein.cshl.org/boulder/
pour des plus amples informations.
Si vous voulez utiliser cette méthode en style orienté fonction (non OO), le nom exporté pour cette méthode est save_parameters().
Des erreurs peuvent survenir durant le traitement des entrées utilisateur, en particulier lorsqu'on traite les fichiers en téléchargement. Lorsque ces erreurs surviennent, CGI stoppe le traitement et retourne une liste de paramètres vide. Vous pouvez tester l'existence et la nature des éventuelles erreurs en utilisant la fonction cgi_error(). Les messages d'erreurs sont formatés comme des codes de Status HTTP. Vous pouvez soit incorporer le texte de l'erreur dans une page HTML soit l'utiliser comme valeur de Status HTTP :
my $error = $q->cgi_error; if ($error) { print $q->header(-status=>$error), $q->start_html('Problems'), $q->h2('Request not processed'), $q->strong($error); exit 0; }
Quand vous utilisez l'interface orientée fonction (voir la section suivante), les erreurs n'ont lieu qu'au premier appel à param().
Pour utiliser l'interface orientée fonction, vous devez spécifier les routines ou l'ensemble des routines de CGI.pm que vous voulez importer dans l'espace de nommage de votre script. Cette importation implique un coût supplémentaire mais il reste petit.
use CGI <liste de routines>;
Les méthodes listées seront importées dans le package courant ; vous pourrez
les appeler directement sans créer d'objet CGI. L'exemple suivant montre
comment importer les méthodes param() et header()
et comment les
utiliser directement :
use CGI 'param','header'; print header('text/plain'); $zipcode = param('zipcode');
De manière générale, vous importerez plutôt un ensemble prédéfini de routines en vous référant à son nom. Tous les noms d'ensembles de fonctions sont précédés par le caractère ``:'' comme dans ``:html3'' (pour les balises définies par le standard HTML 3).
Voici une liste des ensembles de fonctions qui vous pouvez importer :
Si vous importez un nom de fonction qui ne fait pas partie de CGI.pm, le module traite ce nom comme une nouvelle balise HTML et génère les subroutines appropriées. Vous pouvez alors les utiliser comme n'importe quelle autre balise HTML. Cela permet de suivre le ``standard'' HTML dont l'évolution est très rapide. Par exemple, supposons que Microsoft sorte une nouvelle balise appelée <GRADIENT> (qui provoque un remplissage de l'écran par un dégradé circulaire jusqu'au redémarrage de la machine). Vous n'avez pas à attendre une nouvelle version de CGI.pm pour pouvoir l'utiliser :
use CGI qw/:standard :html3 gradient/; print gradient({-start=>'red',-end=>'blue'});
Remarquez que pour améliorer la vitesse d'exécution, CGI.pm n'utilise pas la syntaxe standard de Exporter pour spécifier les symboles à charger. Cela pourrait changer plus tard.
Si vous importez l'une des méthodes permettant de sauvegarder l'état du CGI ou permettant de générer des formulaires, un objet CGI par défaut sera créé et initialisé automatiquement la première fois que vous ferez appel à l'une des méthodes qui nécessite sa présence. Cela inclut param(), textfield(), submit() et autres. (Si vous avez besoin d'accéder directement à cet objet CGI, vous pouvez le trouver dans la variable globale $CGI::Q). En important le méthode de CGI.pm, vous pouvez créer des scripts visuellement élégants :
use CGI qw/:standard/; print header, start_html('Simple Script'), h1('Simple Script'), start_form, "What's your name? ",textfield('name'),p, "What's the combination?", checkbox_group(-name=>'words', -values=>['eenie','meenie','minie','moe'], -defaults=>['eenie','moe']),p, "What's your favorite color?", popup_menu(-name=>'color', -values=>['red','green','blue','chartreuse']),p, submit, end_form, hr,"\n";
if (param) { print "Your name is ",em(param('name')),p, "The keywords are: ",em(join(", ",param('words'))),p, "Your favorite color is ",em(param('color')),".\n"; } print end_html;
En plus des ensembles de fonctions, il y a un certain nombre de directives que vous pouvez importer. Ces directives, dont le nom est toujours précédé d'un tiret, modifie la manière dont fonctionnent certaines fonctions de CGI.pm. Les directives, les ensembles de fonctions et les fonctions individuelles peuvent tous être importés par la même ligne use(). Par exemple, l'instruction use suivante importe l'ensemble des fonctions standard et active le mode debug (directive -debug) :
use CGI qw/:standard -debug/;
Voici liste des directives reconnues :
use CGI qw(-any); $q=new CGI; print $q->gradient({speed=>'fast',start=>'red',end=>'blue'});
Comme l'utilisation de la directive any transforme n'importe quelle faute de frappe dans un nom de méthode en une nouvelle balise HTML, il faut l'utiliser avec beaucoup de précautions voir même ne pas l'utiliser du tout.
use CGI qw(-compile :standard :html3);
ou même :
use CGI qw(-compile :all);
Notez que l'utilisation de la directive -compile aura toujours pour effet
d'importer les fonctions compilées dans l'espace de nommage courant. Si vous
voulez compiler sans importation, utilisez plutôt la méthode compile()
(voir
plus bas).
?name=fred;age=24;favorite_color=3
Les chaînes de requête dont les valeurs sont séparées par des points-virgules
sont toujours reconnues mais elles ne seront émises par self_url()
et
query_string()
que si la directive -newstyle_urls est spécifiée.
C'est devenue le fonctionnement par défaut depuis la version 2.64.
use CGI qw(-no_debug :standard);
Voir la section concernant le déverminage pour plus de détails.
Pour être sûr que le fichier temporaire ne peut être lu par aucun autre script CGI, utilisez suEXEC ou un wrapper CGI pour faire tourner votre script. Le fichier temporaire est créé avec le mode 0600 (lisible ni par le groupe ni par le reste du monde).
Le répertoire temporaire est choisi en utilisant l'algorithme suivant :
Pour chaque emplacement, on vérifie que c'est un répertoire et qu'on peut effectivement écrire dedans. Sinon, l'algorithme essaie l'emplacement suivant.
De nombreuses méthodes génèrent des balises HTML. Comme expliqué plus bas, les fonctions de balisage génèrent automatiquement la balise ouvrante et la balise fermante. Par exemple :
print h1('Level 1 Header');
produit :
<H1>Level 1 Header</H1>
Il se peut que, parfois, vous vouliez produire la balise ouvrante ou fermante vous-même. Dans ce cas, vous pouvez utiliser l'appel start_balise ou end_balise comme dans :
print start_h1,'Level 1 Header',end_h1;
À quelques exceptions près (décrites plus bas), les fonctions start_balise et end_balise ne sont pas générées automatiquement lorsque vous faites use CGI. En revanche, vous pouvez spécifier les balises pour lesquelles vous voulez générer les fonctions start/end en plaçant un astérisque devant leur nom ou en demandant explicitement soit la fonction ``start_balise'' soit la fonction ``end_balise'' dans la liste d'import.
Exemple:
use CGI qw/:standard *table start_ul/;
Dans cet exemple, les fonctions suivantes sont générées en plus des fonctions standards :
start_table()
(génère une balise <TABLE>)
end_table()
(génère une balise </TABLE>)
start_ul()
(génère une balise <UL>)
end_ul()
(génère une balise </UL>)
La plupart des fonctions CGI.pm permettent la création de documents au vol. En général, vous produirez l'en-tête HTTP suivi du document lui-même. CGI.pm fournit les fonctions pour générer les en-têtes HTTP de tous types ainsi que du HTML. Pour produire des images GIF, regardez le module GD.pm.
Chacune de ces fonctions produit un fragment de HTML ou de HTTP que vous pouvez soit sortir directement pour qu'il soit récupéré par le navigateur, soit ajouter à une chaîne, soit enregistrer dans un fichier pour l'utiliser plus tard.
Normalement la première chose que vous avez à faire dans un script CGI est de produire l'en-tête HTTP. Cela indique au navigateur le type du document à recevoir et fournit d'autres informations optionnelles comme la langue, la date d'expiration et s'il faut cacher ce document. L'en-tête peut aussi servir à des fonctions spéciales comme le « server push » ou les pages payées à la consultation (« pay per view »).
print $query->header;
-ou-
print $query->header('image/gif');
-ou-
print $query->header('text/html','204 No response');
-ou-
print $query->header(-type=>'image/gif', -nph=>1, -status=>'402 Payment required', -expires=>'+3d', -cookie=>$cookie, -charset=>'utf-7', -attachment=>'foo.gif', -Cost=>'$2.00');
header() renvoie l'en-tête ``Content-type:''. Vous pouvez indiquer votre propre type MIME si vous le voulez sinon il est positionné par défaut à text/html. Un second paramètre optionnel spécifie le code de Status et un message lisible. Par exemple, vous pouvez spécifier ``204 No response'' pour créer un script qui dit au navigateur de ne rien faire du tout.
Le dernier exemple montre l'utilisation des arguments nommés pour passer les arguments aux méthodes de CGI. Les arguments reconnus sont -type, -status, -expires et -cookie. Tout autre argument nommé sera transformé en un en-tête après suppression du tiret initial, vous permettant de générer l'en-tête HTTP que vous voulez. Les caractères de soulignement internes sont transformés en tiret :
print $query->header(-Content_length=>3002);
La plupart des navigateurs ne stockent pas le résultat des scripts CGI. À chaque fois que le navigateur recharge la page, le script est à nouveau appelé. Vous pouvez changer ce comportement grâce au paramètre -expires. Lorsque vous spécifiez une date absolue ou une durée d'expiration par ce paramètre, certains navigateurs et serveurs proxy stockeront dans leur cache le résultat du script jusqu'à la date d'expiration. Toutes les formes suivantes sont valides pour le champ -expires :
+30s dans 30 secondes +10m dans 10 minutes +1h dans une heure -1d hier (i.e. "Le plus tôt possible") now immédiatement +3M dans 3 mois +10y dans 1 ans Thursday, 25-Apr-1999 00:40:33 GMT au jour et à l'heure indiqués
Le paramètre -cookie génère un en-tête qui indique au navigateur de fournir
un ``magic cookie'' durant toutes les transactions à venir avec votre
script. Les cookies de Netscape ont un format spécial qui inclut des attributs
intéressants comme une date d'expiration. Utilisez la méthode cookie()
pour
créer et gérer les cookies de sessions.
Le paramètre -nph, si il est positionné à la valeur 'vrai', produira les en-têtes corrects pour fonctionner en tant que script NPH (no-parse-header -- en-tête non analysé). Il vaut mieux l'utiliser avec certains serveurs qui veulent que tous les scripts soient NPH.
Le paramètre -charset permet de spécifier le jeu de caractères envoyé au navigateur. Par défaut, c'est ISO-8859-1. Un effet secondaire est de régler aussi la méthode charset().
La paramètre -attachment peut être utilisé pour transformer une page en un fichier à télécharger. Au lieu d'afficher le document, certains navigateur proposeront à l'utilisateur de l'enregistrer sur disque. La valeur du paramètre est le nom suggéré pour l'enregistrement du fichier. Pour que cela fonctionne, vous devrez positionner le -type à ``application/octet-stream''.
print $query->redirect('http://quelque.part/ailleurs/plus/loin');
Parfois vous ne voulez pas produire vous-même un document mais plutôt rediriger le navigateur ailleurs par exemple en choisissant un URL en vous basant sur l'heure ou l'identité de l'utilisateur.
La fonction redirect()
redirige le navigateur vers un URL différent. Si vous
utilisez une telle redirection, vous ne devriez pas afficher d'en-tête en
plus.
Un truc que je peux donner est que les liens relatifs peuvent ne pas fonctionner correctement lorsque vous générez une redirection vers un autre document de votre site. Cela est dû à une optimisation que certains serveurs utilisent (NdT: en fait ce sont les spécifications du protocole HTTP qui l'interdisent). La solution à cela est d'utiliser un URL complet (incluant la partie http:) vers le document choisi.
Vous pouvez aussi utiliser les arguments nommés :
print $query->redirect(-uri=>'http://quelque.part/ailleurs/plus/loin', -nph=>1);
print $query->start_html(-title=>'Secrets of the Pyramids', -author=>'fred@capricorn.org', -base=>'true', -target=>'_blank', -meta=>{'keywords'=>'pharaoh secret mummy', 'copyright'=>'copyright 1996 King Tut'}, -style=>{'src'=>'/styles/style1.css'}, -BGCOLOR=>'blue');
Après avoir créer l'en-tête HTTP, la plupart des scripts CGI continuent en
produisant un document HTML. La routine start_html()
crée le début du document
combiné avec quelques informations optionnelles qui contrôlent l'apparence et
le comportement du document.
Cette méthode retourne un en-tête HTML et la balise d'ouverture <BODY>. Tous les paramètres sont optionnels. Sous la forme de paramètres nommés, les paramètres reconnus sont -title, -author, -base, -xbase, -dtd, -lang et -target (voir plus bas pour les explications). Toute autre paramètre que vous fournirez, comme l'attribut non-officiel de Netscape BGCOLOR, sera ajouté à la balise <BODY>. Les paramètres supplémentaires doivent être précédés d'un tiret.
L'argument -xbase vous permet de choisir pour la balise <BASE>, un HREF différent de l'URL courant, comme dans :
-xbase=>"http://home.mcom.com/"
Tous les liens relatifs seront interprétés relativement à cet URL.
L'argument -target vous permet de choisir un cadre (frame) cible par défaut pour tous les liens et formulaires de la page. C'est une fonctionnalité HTML non-standard qui ne marche qu'avec les navigateurs de Netscape ! Consultez la documentation de Netscape concernant les frames pour les détails concernant cette fonctionnalité.
-target=>"answer_window"
Vous pouvez ajoutez de la méta-information à l'en-tête grâce à l'argument -meta. Cette argument doit être une référence à un tableau associatif (une table de hachage) contenant des paires nom/valeurs de méta-information. Elles seront transformées en une série de balises d'en-tête <META> qui ressembleront à quelque chose comme :
<META NAME="keywords" CONTENT="pharaoh secret mummy"> <META NAME="description" CONTENT="copyright 1996 King Tut">
Pour créer une balise <META> du type HTTP-EQUIV, utilisez -head comme décrit plus bas.
L'argument -style est utilisé pour incorporer une feuille de styles en cascade (CSS) dans votre code. Vois la section FEUILLES DE STYLES EN CASCADE pour plus d'information.
L'argument -lang est utilisé pour ajouter un attribut de langue dans la balise <HTML>. La valeur par défaut est ``en-US'' qui signifie Anglais US. Par exemple :
print $q->header(-lang=>'fr-CA'); # Francais canadien
Vous pouvez ajouter d'autres éléments HTML arbitraires à la partie <HEAD> grâce à -head. Par exemple, pour ajouter l'élément <LINK>, utilisez cela :
print start_html(-head=>Link({-rel=>'next', -href=>'http://www.capricorn.com/s2.html'}));
Pour ajouter plusieurs éléments HTML dans la partie <HEAD>, passez une référence vers un tableau :
print start_html(-head=>[ Link({-rel=>'next', -href=>'http://www.capricorn.com/s2.html'}), Link({-rel=>'previous', -href=>'http://www.capricorn.com/s1.html'}) ] );
Et voici comment créer une balise <META> HTTP-EQUIV :
print header(-head=>meta({-http_equiv => 'Content-Type', -content => 'text/html'}))
JAVASCRIPT : Les paramètres -script, -noScript, -onLoad, -onMouseOver, -onMouseOut et -onUnload sont utilisés pour insérer dans votre page des appels au langage JavaScript de Netscape. -script devrait pointer vers un bloc de texte contenant les définitions des fonctions JavaScript. Ce bloc sera placé à l'intérieur d'un bloc <SCRIPT> dans l'en-tête HTML (pas HTTP). Ce bloc est placé dans l'en-tête afin d'être sûr que votre page aura toutes ses fonctions JavaScript définies même si l'utilisateur presse le bouton stop avant le chargement complet de la page. CGI.pm essaie de présenter ce code de manière à ne pas choquer les navigateurs qui ne connaissent pas le JavaScript : malheureusement quelques navigateurs comme Chimera pour Unix ne l'accepteront pas malgré tout.
Les paramètres -onLoad et -onUnload pointent vers des fragments de code JavaScript qui seront exécutés lorsque votre page sera respectivement ouverte puis fermée par le navigateur. Habituellement ces paramètres sont des appels à des fonctions définies dans le champ -script :
$query = new CGI; print $query->header; $JSCRIPT=<<END; // Ask a silly question function riddle_me_this() { var r = prompt("What walks on four legs in the morning, " + "two legs in the afternoon, " + "and three legs in the evening?"); response(r); } // Get a silly answer function response(answer) { if (answer == "man") alert("Right you are!"); else alert("Wrong! Guess again."); } END print $query->start_html(-title=>'The Riddle of the Sphinx', -script=>$JSCRIPT);
Utilisez le paramètre -noScript pour passer un texte HTML qui sera affiché par les navigateurs qui n'ont pas d'interpréteur JavaScript (ou dont l'interpréteur JavaScript est désactivé).
Netscape 3.0 reconnaît plusieurs attributs pour la balise <SCRIPT>, entre autres LANGUAGE et SRC. Ce dernier est particulièrement intéressant car il vous permet de garder votre code JavaScript dans un fichier ou un script CGI séparé plutôt que de l'envoyer à chaque fois dans le source de vos pages. Pour utiliser ces attributs, passez au paramètre -script une référence vers une table de hachage contenant au moins une clé parmi -language, -src, ou -code :
print $q->start_html(-title=>'The Riddle of the Sphinx', -script=>{-language=>'JAVASCRIPT', -src=>'/javascript/sphinx.js'} );
print $q->(-title=>'The Riddle of the Sphinx', -script=>{-language=>'PERLSCRIPT', -code=>'print "hello world!\n;"'} );
Une dernière fonctionnalité vous permet d'inclure plusieurs sections <SCRIPT> dans votre en-tête. Passez juste la liste des sections script comme une référence à un tableau. Cela vous permet de spécifier différents fichiers sources pour différents dialectes de JavaScript. Exemple :
print $q->start_html(-title=>'The Riddle of the Sphinx', -script=>[ { -language => 'JavaScript1.0', -src => '/javascript/utilities10.js' }, { -language => 'JavaScript1.1', -src => '/javascript/utilities11.js' }, { -language => 'JavaScript1.2', -src => '/javascript/utilities12.js' }, { -language => 'JavaScript28.2', -src => '/javascript/utilities219.js' } ] );
Voir :
http://home.netscape.com/eng/mozilla/2.0/handbook/javascript/
pour plus d'informations sur JavaScript.
L'ancien mode d'appel fonctionne comme suit :
Paramètres :
print $query->end_html
Cela termine un document HTML en affichant les balises </BODY></HTML>.
$myself = $query->self_url; print q(<A HREF="$myself">I'm talking to myself.</A>);
self_url()
retourne un URL qui, lorsqu'il est utilisé, ré-invoquera le script
avec toutes ses informations d'état intactes. C'est très pratique lorsque vous
voulez naviguer à l'intérieur du document en utilisant de ancres internes sans
changer le contenu des formulaires courants. Quelque chose comme ça devrait
fonctionner :
$myself = $query->self_url; print "<A HREF=$myself#table1>See table 1</A>"; print "<A HREF=$myself#table2>See table 2</A>"; print "<A HREF=$myself#yourself>See for yourself</A>";
Si vous voulez mieux contrôler ce qui est retourné, utilisez plutôt la méthode url().
Vous pouvez aussi retrouver la chaîne de requête avant traitement grâce à
query_string()
:
$the_string = $query->query_string;
$full_url = $query->url(); $full_url = $query->url(-full=>1); # syntaxe alternative $relative_url = $query->url(-relative=>1); $absolute_url = $query->url(-absolute=>1); $url_with_path = $query->url(-path_info=>1); $url_with_path_and_query = $query->url(-path_info=>1,-query=>1);
La routine url() renvoie l'URL du script sous différents formats. Appelée sans argument, elle renvoie l'URL complet y compris le nom de la machine et le numéro de port :
http://your.host.com:80/path/to/script.cgi
Vous pouvez modifier ce format en utilisant les argument nommés suivants :
/path/to/script.cgi
script.cgi
$color = $query->url_param('color');
Un script CGI peut recevoir des paramètres via son URL en créant un formulaire qui utilise la méthode POST vers un URL contenant une chaîne de requête (un ``?'' suivi par des arguments). La méthode param() ne retournera que le contenu du formulaire POST-é et ignorera la chaîne de requête de l'URL. Pour retrouver les paramètres de l'URL, appelez la méthode url_param(). Elle s'utilise de la même manière que param(). La seule différence est qu'elle ne permet que la lecture des paramètres, pas leur modification.
Dans certaines circonstances, le contenu de la chaîne de requête de l'URL interférera avec des paramètres du formulaire POST-é portant le même nom. Si vous essayez de mélanger une chaîne de requête d'URL avec un formulaire soumis par la méthode GET, le résultat ne sera peut-être pas celui que vous attendez.
CGI.pm définit de méthodes rapides pour quasiment toutes (si ce n'est toutes) les balises HTML 3 et 4. Les méthodes HTML sont nommées d'après le nom d'un seul élément HTML et renvoient un fragment de texte HTML que vous pouvez afficher ou manipuler comme vous le voulez. Chaque méthode renvoie un fragment de code HTML que vous pouvez ajouter à une chaîne, enregistrer dans un fichier ou, plus couramment, imprimer de manière à être affiché par la fenêtre du navigateur.
Cet exemple illustre l'utilisation des méthodes HTML :
$q = new CGI; print $q->blockquote( "Many years ago on the island of", $q->a({href=>"http://crete.org/"},"Crete"), "there lived a Minotaur named", $q->strong("Fred."), ), $q->hr;
Le résultat est le code HTML suivant (des passages à la ligne ont été ajoutés pour améliorer la lisibilité) :
<blockquote> Many years ago on the island of <a HREF="http://crete.org/">Crete</a> there lived a minotaur named <strong>Fred.</strong> </blockquote> <hr>
Si cette syntaxe d'appel des méthodes HTML vous semble trop lourde, vous pouvez les importer dans votre espace de nommage et vous dispenser ainsi complètement de la syntaxe objet (voir la section suivante pour plus de détails) :
use CGI ':standard'; print blockquote( "Many years ago on the island of", a({href=>"http://crete.org/"},"Crete"), "there lived a minotaur named", strong("Fred."), ), hr;
Les méthodes HTML acceptent aucun, un ou plusieurs arguments. Si vous ne passez aucun argument, vous obtiendrez une balise seule :
print hr; # <HR>
Si vous passez un ou plusieurs arguments de type chaîne, ils seront concaténés séparés par un espace et placés entre la balise ouvrante et la balise fermante :
print h1("Chapter","1"); # <H1>Chapter 1</H1>"
Si le premier argument est une référence vers une table de hachage alors les clés et les valeurs associées de cette table deviendront les attributs de la balise HTML :
print a({-href=>'fred.html',-target=>'_new'}, "Open a new frame");
<A HREF="fred.html" TARGET="_new">Open a new frame</A>
Vous pouvez vous dispenser d'ajouter le tiret au début du nom de l'attribut si vous préférez :
print img {src=>'fred.gif',align=>'LEFT'};
<IMG ALIGN="LEFT" SRC="fred.gif">
Parfois des attributs de certaines balises HTML n'ont pas d'argument. Par exemple, les listes ordonnées peuvent être marquées comme COMPACT. La syntaxe pour cela est un argument qui pointe sur une valeur indéfinie (undef) :
print ol({compact=>undef},li('one'),li('two'),li('three'));
Avant la version 2.41 de CGI.pm, fournir une chaîne vide ('') comme valeur d'un argument aboutissait au même résultat. Mais cela a été modifié pour permettre de créer des balises de la forme <IMG ALT=``''>. La différence est illustrée par les deux codes suivants :
CODE RESULTAT img({alt=>undef}) <IMG ALT> img({alt=>''}) <IMT ALT="">
L'une des fonctionnalités sympathiques des méthodes HTML est leur distributivité. Si vous leur fournissez un argument de type référence vers une liste, la balise sera distribuée sur chacun des éléments de la liste. Par exemple, voici un moyen de créer une liste ordonnée :
print ul( li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy']) );
Cette exemple produira le code HTML suivant :
<UL> <LI TYPE="disc">Sneezy</LI> <LI TYPE="disc">Doc</LI> <LI TYPE="disc">Sleepy</LI> <LI TYPE="disc">Happy</LI> </UL>
C'est extrêmement pratique pour créer des tableaux. Par exemple :
print table({-border=>undef}, caption('When Should You Eat Your Vegetables?'), Tr({-align=>CENTER,-valign=>TOP}, [ th(['Vegetable', 'Breakfast','Lunch','Dinner']), td(['Tomatoes' , 'no', 'yes', 'yes']), td(['Broccoli' , 'no', 'no', 'yes']), td(['Onions' , 'yes','yes', 'yes']) ] ) );
Supposons ce petit bout de code :
print blockquote(em('Hi'),'mom!'));
Il retournera normalement la chaîne que vous attendez, à savoir :
<BLOCKQUOTE><EM>Hi</EM> mom!</BLOCKQUOTE>
Vous remarquerez l'espace entre l'élément ``Hi'' et l'élément ``mom!''. CGI.pm ajoute cet espace supplémentaire en utilisant l'interpolation de tableau qui est contrôlé par la variable magique $``. Parfois vous ne voudrez pas de cet espace supplémentaire. Par exemple quand vous essayerez d'aligner une série d'images. Dans ce cas, il vous suffit de donner la chaîne vide comme valeur à la variable $''.
{ local($") = ''; print blockquote(em('Hi'),'mom!')); }
Je vous suggère de placer votre code dans un bloc comme ici. Sinon la modification de $`` affectera tous les codes suivants jusqu'à un autre changement de valeur explicite.
Quelques balises HTML ne suivent pas le modèle standard pour différentes raisons.
comment() génère un commentaire HTML (<!-- comment -->). Appelez-la de la manière suivante :
print comment('here is my comment');
À cause de conflits avec les fonctions prédéfinies de Perl, les fonctions suivantes commencent par une majuscule :
Select Tr Link Delete Accept Sub
De plus, start_html(), end_html(), start_form(), end_form(),
start_multipart_form()
et toutes les méthodes liées aux balises de création de
formulaire sont spéciales. Se reporter à leurs sections respectives.
Par défaut, tout le code HTML émis par les fonctions de génération de
formulaires est passé au travers d'une fonction appelée escapeHTML()
:
$escaped_string = escapeHTML("unescaped string");
recode les caractères spéciaux HTML de la chaîne.
En supposant que vous avez spécifié le jeu de caractères ISO-8859-1 (la valeur
par défaut), les règles standard d'encodage HTML seront utilisées. Le
caractère ``<'' deviendra ``<'', ``>'' deviendra ``>'', ``&'' deviendra ``&'' et
les doubles apostrophes deviendront ``"''. De plus, les caractères de codes
héxadécimaux 0x8b et 0x9b, que de nombreux navigateurs sous Windows
interprètent comme les caractères inférieur et supérieur, seront remplacés par
les entités HTML numériques correspondantes (``‹'' et ``›''). Si vous
changez manuellement le jeu de caractères, soit en appelant explicitement la
méthode charset()
soit en passant un argument -charset à la méthode header(),
alors tous les caractères seront remplacés par leur entités HTML numériques
correspondantes puisque CGI.pm n'a pas de tables de correspondance pour tous
les encodages possibles.
L'encodage automatique ne s'applique pas aux autres méthodes telle que
h1(). Vous devez appeler escapeHTML()
vous-même surtout sur les données non
sûres afin de protéger vos pages contre les mauvaises blagues que des gens
pourraient saisir dans les champs d'un formulaire (livre d'or, etc.). Pour
changer le jeu de caractères, utilisez la méthode charset(). Pour désactiver
complètement l'auto-encodage, utilisez autoEscape()
:
Par défaut, tout le HTML produit par ces fonctions arrive comme une seule longue ligne sans aucun passage à la ligne ni indentation. Ce n'est pas joli mais cela réduit la taille des documents de 10 à 20%. Pour obtenir du joli HTML, utilisez le module la page de manuel CGI::Pretty, une sous-classe qui est une contribution de Brian Paulsen.
Note générale : toutes les méthodes de création de formulaire renvoient à l'appelant une chaîne de caractères contenant une ou plusieurs balises qui créeront l'élément de formulaire demandé. Vous êtes responsable des chaînes réellement renvoyées. Elles sont faites de telle sorte que vous puissiez mettre des balises autour des éléments de formulaire.
Une autre note : les valeurs par défaut que vous spécifiez pour les formulaires sont uniquement utilisées la première fois que le script est appelé (lorsque la chaîne de requête n'existe pas). Pour les appels ultérieurs au script (quand un chaîne de requête existe), les valeurs de la dernière requête sont utilisées même si elles sont vides.
Si vous voulez changer la valeur d'un champ par rapport à sa valeur précédente, vous avez deux possibilités :
param()
pour la changer.
print $query->textfield(-name=>'field_name', -default=>'starting value', -override=>1, -size=>50, -maxlength=>80);
Encore une autre note : par défaut, le texte et les noms des éléments de
formulaire sont encodés selon les spécifications HTML. Ce qui veut dire que
vous pouvez utiliser en toute sécurité ``<CLICK ME>'' comme nom de bouton. En
renvanche, cela gêne votre capacité à incorporer des caractères HTML spéciaux,
comme Á, dans vos champs. Si vous souhaitez désactiver l'encodage
automatique, appelez la méthode autoEscape()
avec une valeur ``false'' juste
après avoir créé l'objet CGI :
$query = new CGI; $query->autoEscape(undef);
print $query->isindex(-action=>$action);
-ou-
print $query->isindex($action);
Affiche une balise <ISINDEX>. Pas très intéressant. Le paramètre -action spécifie l'URL du script qui traitera la requête. Par défaut, c'est l'URL du script en cours.
print $query->start_form(-method=>$method, -action=>$action, -enctype=>$encoding); <... divers balises de formulaire ...> print $query->endform;
-ou-
print $query->start_form($method,$action,$encoding); <... divers balises de formulaire ...> print $query->endform;
start_form()
renverra une balise <FORM> avec les attributs optionnels que vous
indiquerez pour la méthode, l'action et l'encodage du formulaire. Par défaut,
ces paramètres valent :
method: POST action: this script enctype: application/x-www-form-urlencoded
Note : auparavant cette méthode était nommée startform(). startform()
est
toujours reconnu comme un alias.
endform()
renvoie la balise fermante </FORM>.
L'argument enctype de start_form()
indique au navigateur comment encoder les
différents champs du formulaire avant des les envoyer au serveur. Deux valeurs
sont possibles :
Les formulaires qui utilisent ce type d'encodage ne sont pas facilement interprétés par les scripts CGI, sauf si ceux-ci utilisent CGI.pm ou tout autre bibliothèque conçue pour les traiter.
Pour des raisons de compatibilité, la méthode start_form()
utilise par défaut
l'ancienne version d'encodage. Si vous voulez utiliser la nouvelle version par
défaut, vous pouvez appeler la méthode start_multipart_form() à la place de
start_form().
JAVASCRIPT : les paramètres -name et -onSubmit sont disponibles pour faire du JavaScript. Le paramètre -name donne un nom au formulaire qui, ainsi, peut être identifié et manipulé par des fonctions JavaScript. -onSubmit devrait pointer vers une fonction JavaScript qui sera exécutée juste avant que le formulaire soit envoyé à votre serveur. Vous pouvez utiliser cette fonction pour vérifier la consistance et la cohérence du contenu du formulaire. Si vous détectez une chose incorrecte, vous pouvez soit afficher une fenêtre d'alerte soit corriger vous-même les données erronées. La soumission du formulaire sera annulée si votre fonction retourne une valeur fausse (false).
D'habitude, le gros des fonctions JavaScript est défini dans un bloc <SCRIPT>
dans l'en-tête HTML et -onSubmit ne fait qu'un appel à l'une de ces
fonctions. Voir start_html()
pour les détails.
print $query->textfield(-name=>'field_name', -default=>'starting value', -size=>50, -maxlength=>80); -ou-
print $query->textfield('field_name','starting value',50,80);
textfield()
renverra un champ d'entrée texte.
Paramètres :
Comme avec toutes ces méthodes, le champ sera initialisé avec son contenu précédent provenant des appels antérieurs au script. Quand le formulaire est traité, la valeur du champ texte peut être retrouvée par :
$value = $query->param('foo');
Si vous voulez le réinitialiser à sa valeur initiale après un appel précédent au script, vous pouvez faire comme ça :
$query->param('foo',"I'm taking over this value!");
NOUVEAU DEPUIS LA VERSION 2.15 : si vous ne voulez pas que le champ conserve sa dernière valeur, vous pouvez forcer sa valeur courante en utilisant le paramètre -override (ou -force) :
print $query->textfield(-name=>'field_name', -default=>'starting value', -override=>1, -size=>50, -maxlength=>80);
JAVASCRIPT : vous pouvez bien sûr renseigner les paramètres -onChange, -onFocus, -onBlur, -onMouseOver, -onMouseOut et -onSelect pour attacher à ces évènements des routines JavaScript de traitement. La routine attachée à onChange sera appelée à chaque fois que l'utilisateur change le contenu du champ texte. Vous pouvez faire une validation du texte si vous voulez. onFocus et onBlur sont appelés respectivement quand le point d'insertion entre ou sort du champ texte. onSelect est appelé quand l'utilisateur change la portion de texte sélectionnée à l'intérieur du champ.
print $query->textarea(-name=>'foo', -default=>'starting value', -rows=>10, -columns=>50);
-ou-
print $query->textarea('foo','starting value',10,50);
textarea()
est similaire à textfield()
excepté qu'il vous permet de spécifier
le nombre de lignes et de colonnes pour la boite d'entrée de texte
multiligne. Vous pouvez renseigner une valeur initiale pour le champ qui peut
être longue et contenir plusieurs lignes.
JAVASCRIPT : les paramètres -onChange, -onFocus, -onBlur , -onMouseOver, -onMouseOut, et -onSelect sont reconnus. Voir textfield().
print $query->password_field(-name=>'secret', -value=>'starting value', -size=>50, -maxlength=>80); -ou-
print $query->password_field('secret','starting value',50,80);
password_field()
est identique à textfield(), excepté que son contenu sera
affiché sous forme d'étoiles sur la page web.
JAVASCRIPT : Les paramètres -onChange, -onFocus, -onBlur , -onMouseOver, -onMouseOut, et -onSelect sont reconnus. Voir textfield().
print $query->filefield(-name=>'uploaded_file', -default=>'starting value', -size=>50, -maxlength=>80); -ou-
print $query->filefield('uploaded_file','starting value',50,80);
filefield()
crée un champ de téléchargement de fichier pour les navigateurs
type Netscape 2.0. Afin d'en tirer tous les avantages, vous devez utiliser
le nouveau format d'encodage multipart pour ce formulaire. Vous pouvez faire
cela en appelant start_form() avec un encodage &CGI::MULTIPART, ou en
appelant la nouvelle méthode start_multipart_form() au lieu de
start_form().
Paramètres :
Pour des raisons de sécurité, les navigateurs ne prêtent pas attention à ce champ et la valeur initiale est donc toujours vide. Pire, le champ perd son comportement ``persistant'' et oublie son contenu précédent. Cet attribut spécifiant la valeur initiale existe pourtant dans les spécifications HTML et il est donc possible que certains navigateurs en tiennent compte un jour.
Quand le formulaire est traité, vous pouvez retrouver le nom du fichier
téléchargé en appelant la méthode param()
:
$filename = $query->param('uploaded_file');
Des navigateurs différents renverront des choses légèrement différentes pour ce nom. Certains navigateurs renverront uniquement le nom du fichier. D'autres renverront le chemin complet du fichier en utilisant les conventions de chemin de la machine de l'utilisateur. Ceci étant, le nom retourné est toujours le nom du fichier sur la machine de l'utilisateur. Il n'a aucun rapport avec le nom du fichier temporaire que CGI.pm crée pendant le téléchargement (voir ci-dessous).
Le nom du fichier renvoyé est aussi un descripteur de fichier. Vous pouvez lire le contenu du fichier en utilisant les appels standard de lecture de fichier de Perl :
# Lire un fichier texte et l'afficher while (<$filename>) { print; }
# Copier un fichier binaire dans un endroit sur open (OUTFILE,">>/usr/local/web/users/feedback"); while ($bytesread=read($filename,$buffer,1024)) { print OUTFILE $buffer; }
Cependant, il y a des problèmes avec la double nature des champs de
téléchargement de fichiers. Si vous utilisez use strict
, alors Perl se
plaindra quand vous essayerez d'utiliser une chaîne de caractères comme
descripteur de fichier. Vous pouvez évidemment contourner ce problème en
plaçant le code de lecture du fichier dans un bloc contenant la directive no
strict
. Plus sérieusement, il est possible pour l'utilisateur distant, de
taper n'importe quoi dans le champ de téléchargement, auquel cas, ce que vous
récupérerez de param()
ne sera pas du tout un descripteur de fichier, mais
seulement une chaîne de caractères.
Pour travailler de manière sûre, utilisez la fonction upload()
(introduite
dans la version 2.47). Lorsqu'elle est appelée avec le nom d'un champ de
téléchargement, upload()
renvoie un descripteur de fichier, ou undef si le
paramètre n'est pas un descripteur de fichier valide.
$fh = $query->upload('uploaded_file'); while (<$fh>) { print; }
C'est l'idiome recommandé.
Lorsqu'un fichier est téléchargé, le navigateur envoie toujours, en
accompagnement, des informations le concernant, via différents en-têtes. Ces
informations incluent habituellement le type MIME du contenu. Les futurs
navigateurs peuvent aussi envoyer d'autres informations (comme la date de
modification ou la taille). Pour retrouver ces informations, appelez
uploadInfo()
. Cette fonction renvoie une référence à un tableau associatif
contenant tous les en-têtes du document.
$filename = $query->param('uploaded_file'); $type = $query->uploadInfo($filename)->{'Content-Type'}; unless ($type eq 'text/html') { die "HTML FILES ONLY!"; }
Si vous utilisez une machine qui distingue les types de données ``texte'' et ``binaire'', soyez sûr de comprendre quand et comment les utiliser (voir le Camel book). Sinon, vous pourrez constater que le contenu des fichiers binaires est altéré durant leur téléchargement.
Il y a de temps en temps des problèmes dus à l'analyse des fichiers téléchargés. Cela se produit habituellement quand l'utilisateur presse le bouton ``Stop'' avant la fin du téléchargement. Dans ce cas, CGI.pm renverra undef pour le nom du fichier et renverra ``400 Bad Request (malformed multipart POST)'' dans cgi-error(). Ce message d'erreur est conçu de telle sorte que vous pouvez l'utiliser comme Status dans les en-têtes HTTP à renvoyer au navigateur. Exemple :
$file = $query->upload('uploaded_file'); if (!$file && $query->cgi_error) { print $query->header(-status=>$query->cgi_error); exit 0; }
Libre à vous de créer des pages HTML personnalisées à renvoyer en cas d'erreur.
JAVASCRIPT : Les paramètres -onChange, -onFocus, -onBlur , -onMouseOver, -onMouseOut, et -onSelect sont reconnus. Voir textfield().
print $query->popup_menu('menu_name', ['eenie','meenie','minie'], 'meenie');
-ou-
%labels = ('eenie'=>'your first choice', 'meenie'=>'your second choice', 'minie'=>'your third choice'); print $query->popup_menu('menu_name', ['eenie','meenie','minie'], 'meenie',\%labels);
-ou (appel par parametres nommes)-
print $query->popup_menu(-name=>'menu_name', -values=>['eenie','meenie','minie'], -default=>'meenie', -labels=>\%labels);
popup_menu()
crée un menu.
Quand le formulaire est traité, la valeur sélectionnée dans le menu déroulant peut être retrouvée en utilisant :
$popup_menu_value = $query->param('menu_name');
JAVASCRIPT : popupmenu()
reconnaît les attributs suivants : -onChange,
-onFocus, -onMouseOver, -onMouseOut, et -onBlur. Voir la section
textfield()
pour savoir en quelles circonstances il est fait appel à ces
attributs.
print $query->scrolling_list('list_name', ['eenie','meenie','minie','moe'], ['eenie','moe'],5,'true'); -ou-
print $query->scrolling_list('list_name', ['eenie','meenie','minie','moe'], ['eenie','moe'],5,'true', \%labels);
-ou-
print $query->scrolling_list(-name=>'list_name', -values=>['eenie','meenie','minie','moe'], -default=>['eenie','moe'], -size=>5, -multiple=>'true', -labels=>\%labels);
scrolling_list()
crée une liste déroulante.
Paramètres :
Quand le formulaire est traité, tous les éléments sélectionnés de la liste sont renvoyés sous forme de liste par le paramètre 'list_name'. Les valeurs des éléments sélectionnés peuvent être retrouvées par :
@selected = $query->param('list_name');
JAVASCRIPT : scrolling_list()
reconnaît les attributs suivants : -onChange,
-onFocus, -onMouseOver, -onMouseOut, et -onBlur. Voir la section
textfield()
pour les détails concernant l'utilisation de ces attributs.
print $query->checkbox_group(-name=>'group_name', -values=>['eenie','meenie','minie','moe'], -default=>['eenie','moe'], -linebreak=>'true', -labels=>\%labels);
print $query->checkbox_group('group_name', ['eenie','meenie','minie','moe'], ['eenie','moe'],'true',\%labels);
NAVIGATEURS COMPATIBLES HTML3 SEULEMENT :
print $query->checkbox_group(-name=>'group_name', -values=>['eenie','meenie','minie','moe'], -rows=>2,-columns=>2);
checkbox_group()
crée une liste de cases à cocher qui sont regroupées sous le
même nom.
Paramètres :
checkbox_group()
à renvoyer un tableau compatible HTML3 contenant le groupe de
cases à cocher formaté avec le nombre de lignes et de colonnes spécifié. Vous
pouvez renseigner uniquement le paramètre -columns si vous le désirez.
checkbox_group()
calculera le nombre correct de lignes pour vous.
Pour ajouter des titres à vos lignes et colonnes dans le tableau renvoyé, vous pouvez utiliser les paramètres -rowheaders et -colheaders. Les deux acceptent un pointeur vers un tableau de titres à utiliser. Les titres sont purement décoratifs. Ils ne modifient pas l'interprétation des données des cases à cocher.
Quand le formulaire est traité, la liste de toutes les cases cochées sera renvoyée dans le paramètre nommé 'group_name'. Les valeurs des cases à cocher ``on'' peuvent être retrouvées par :
@turned_on = $query->param('group_name');
Les valeurs renvoyées par checkbox_group()
sont réellement un tableau de
valeurs. Vous pouvez les prendre et les utiliser dans des tableaux, listes ou
autres :
@h = $query->checkbox_group(-name=>'group_name',-values=>\@values); &use_in_creative_way(@h);
JAVASCRIPT : checkbox_group()
reconnaît le paramètre -onClick. Il permet à
un bout de code JavaScript ou un appel de fonction de s'exécuter à chaque fois
que l'utilisateur clique sur l'un des boutons du groupe. Vous pouvez
rechercher l'identité du bouton cliqué en utilisant la variable ``this''.
print $query->checkbox(-name=>'checkbox_name', -checked=>'checked', -value=>'ON', -label=>'CLICK ME');
-ou-
print $query->checkbox('checkbox_name','checked','ON','CLICK ME');
checkbox()
est utilisé pour créer une case à cocher isolée qui n'est pas
associée à d'autres de façon logique.
Paramètres :
La valeur de la case à cocher peut être retrouvée en utilisant :
$turned_on = $query->param('checkbox_name');
JAVASCRIPT : checkbox()
reconnaît le paramètre onClick. Voir
checkbox_group()
pour plus de détails.
print $query->radio_group(-name=>'group_name', -values=>['eenie','meenie','minie'], -default=>'meenie', -linebreak=>'true', -labels=>\%labels);
-ou-
print $query->radio_group('group_name',['eenie','meenie','minie'], 'meenie','true',\%labels);
NAVIGATEURS COMPATIBLES HTML3 SEULEMENT :
print $query->radio_group(-name=>'group_name', -values=>['eenie','meenie','minie','moe'], -rows=2,-columns=>2);
radio_group()
crée un groupe de boutons radio associés de manière logique.
(activer l'un des boutons du groupe désactive les autres)
Paramètres :
radio_group()
à renvoyer un tableau compatible HTML3 contenant le groupe de
boutons radio formaté avec les nombres de lignes et de colonnes
spécifiés. Vous pouvez renseigner uniquement le paramètre -columns si vous le
désirez ; radio_group()
calculera le nombre correct de lignes pour vous.
Pour inclure des titres de lignes et de colonnes dans le tableau renvoyé, vous pouvez utiliser les paramètres -rowheaders et -colheaders. Les deux acceptent un pointeur vers un tableau de titres à utiliser. Les titres sont purement décoratifs. Ils ne modifient pas l'interprétation des données des cases à cocher.
Quand le formulaire est traité, le bouton radio sélectionné peut être retrouvé en utilisant :
$which_radio_button = $query->param('group_name');
Les valeurs renvoyées par radio_group()
sont toujours un tableau de valeurs.
Vous pouvez les prendre et les utiliser dans des tableaux, listes ou autres :
@h = $query->radio_group(-name=>'group_name',-values=>\@values); &use_in_creative_way(@h);
print $query->submit(-name=>'button_name', -value=>'value');
-ou-
print $query->submit('button_name','value');
submit()
créera le bouton de soumission de requête. Tous les formulaires
devrait en avoir un.
Paramètres :
Vous pouvez savoir quel bouton a été pressé en utilisant différentes valeurs pour chacun d'eux :
$which_one = $query->param('button_name');
JAVASCRIPT : submit()
reconnaît le paramètre onClick. Voir
checkbox_group()
pour plus de détails.
print $query->reset
reset()
crée un bouton ``reset''. Notez qu'il remet les valeurs du formulaire
dans l'état où elles étaient la dernière fois que le script a été appelé, PAS
obligatoirement à celui par défaut.
Notez qu'il y a conflit avec la fonction de base Perl reset(). Utilisez
CORE::reset() pour obtenir la fonction reset()
standard.
print $query->defaults('button_label')
defaults()
crée un bouton qui, lorsqu'on l'utilise, remet tous les champs du
formulaire à leur valeur par défaut, enlevant ainsi tous les changements que
l'utilisateur aurait pu faire.
print $query->hidden(-name=>'hidden_name', -default=>['value1','value2'...]);
-ou-
print $query->hidden('hidden_name','value1','value2'...);
hidden()
construit un champ texte qui ne peut pas être vu par l'utilisateur
(NdT: sauf en lisant les sources du document HTML). Il est très pratique pour
transmettre une information sur l'état d'une variable d'un appel du script à
l'autre.
Paramètres :
Retrouvez la valeur d'un champ caché de cette façon :
$hidden_value = $query->param('hidden_name');
Notez que comme tous les autres éléments de formulaire, la valeur d'un champ caché est ``persistante''. Si vous voulez remplacer la valeur d'un champ caché avec d'autres valeurs après que le script ait été appelé une première fois, vous devrez le faire manuellement :
$query->param('hidden_name','new','values','here');
print $query->image_button(-name=>'button_name', -src=>'/source/URL', -align=>'MIDDLE');
-ou-
print $query->image_button('button_name','/source/URL','MIDDLE');
image_button()
donne une image cliquable. Quand elle est cliquée, la position
du clic est renvoyée à votre script dans les deux paramètres ``button_name.x''
et ``button_name.y'', où ``button_name'' est le nom que vous lui avez donné.
Paramètres :
Retrouvez la valeur du bouton de cette manière :
$x = $query->param('button_name.x'); $y = $query->param('button_name.y');
JAVASCRIPT : image_button()
reconnaît le paramètre onClick. Voir
checkbox_group pour plus de détails.
print $query->button(-name=>'button_name', -value=>'user visible label', -onClick=>"do_something()");
-ou-
print $query->button('button_name',"user label","do_something()");
button()
produit un bouton compatible avec le JavaScript de Netscape
2.0. Quand il est pressé, le bout de code JavaScript pointé par par le
paramètre onClick sera exécuté. Sur les navigateurs autres que Netscape,
cet élément de formulaire ne sera probablement même pas affiché.
Les versions 1.1 et supérieures de Netscape, ainsi que toutes les versions d'Internet Explorer, supportent la notion de ``cookie'' qui aide au suivi d'une session avec un navigateur. CGI.pm proposent quelques méthodes qui gèrent les cookies.
Un cookie est une paire nom=valeur, un peu comme les paramètres nommés dans une requête CGI. Les scripts CGI créent un ou plusieurs cookies et les envoient au navigateur dans l'entête HTTP. Le navigateur mémorise la liste des cookies qui appartiennent à un serveur Web particulier et les renvoient au script CGI lors d'appels ultérieurs.
En plus de la paire nom=valeur, chaque cookie a quelques attributs optionnels :
L'accès aux cookies HTTP se fait par la méthode cookie() :
$cookie = $query->cookie(-name=>'sessionID', -value=>'xyzzy', -expires=>'+1h', -path=>'/cgi-bin/database', -domain=>'.capricorn.org', -secure=>1); print $query->header(-cookie=>$cookie);
cookie() crée un nouveau cookie. Ses paramètres sont :
$cookie=$query->cookie(-name=>'family information', -value=>\%childrens_ages);
header()
:
"+1h" dans une heure
=item B<-secure>
Si ce paramètre est positionné à vrai (``true''), ce cookie ne sera utilisé qu'à travers une session sécurisée (par SSL).
Le cookie créé par cookie()
doit être incorporé aux en-têtes HTTP en passant
par la chaîne retournée par le méthode header()
:
print $query->header(-cookie=>$my_cookie);
Pour créer plusieurs cookies, passez à header()
une référence à un tableau :
$cookie1 = $query->cookie(-name=>'riddle_name', -value=>"The Sphynx's Question"); $cookie2 = $query->cookie(-name=>'answers', -value=>\%answers); print $query->header(-cookie=>[$cookie1,$cookie2]);
Pour retrouver un cookie, demandez-le par son nom en appelant la méthode
cookie()
sans paramètre -value :
use CGI; $query = new CGI; %answers = $query->cookie(-name=>'answers'); # $query->cookie('answers') marcherait aussi !
Les espaces de nommage des cookies et des paramètres CGI sont distincts. Si
vous avez un paramètre nommé 'answers' et un cookie nommé 'answers', les
valeurs retournées par param()
et cookie()
sont indépendantes l'une de
l'autre. Par contre, il est très simple de transformer un paramètre CGI en un
cookie et vice-versa :
# transforme un parametre CGI en un cookie $c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]); # vice-versa $q->param(-name=>'answers',-value=>[$q->cookie('answers')]);
Voir le script d'exemple cookie.cgi pour avoir quelques idées sur l'utilisation réelle des cookies.
Les scripts CGI.pm peuvent écrire dans plusieurs cadres ou fenêtres du navigateur en utilisant les mécanismes de cadres (frames) de HTML 4. Il y a trois techniques pour définir de nouveaux cadres par programmation :
votre(vos)
script(s)
(avec les
paramètres appropriés) comme SRC pour chacun de ces cadres (frames).
Il n'y a rien de prévu pour créer des sections <FRAMESET> dans CGI.pm mais le HTML est très simple à écrire. Lisez la documentation fournie par Netscape pour plus de détails :
http://home.netscape.com/assist/net_sites/frames.html
header()
:
print $q->header(-target=>'ResultsWindow');
Cela dit au navigateur de charger le résultat de votre script dans le cadre nommé ``ResultsWindow''. Si aucun cadre de ce nom n'existe, le navigateur ouvrira une nouvelle fenêtre et y affichera le résultat de votre script. Il y a un certain nombre de noms magiques que vous pouvez utiliser comme cible (target). Lisez la documentation fournie par Netscape pour plus de détails.
print $q->start_form(-target=>'ResultsWindow');
Lorsque votre script est réinvoqué par le formulaire, sa sortie sera chargée dans le cadre nommé ``ResultsWindow''. Si aucun cadre de ce nom n'existe, il sera créé.
Le script ``frameset.cgi'' dans le répertoire d'exemples montre un moyen de créer des pages dans lesquelles le formulaire et sa réponse sont dans des cadres côte à côte.
CGI.pm propose un support limité des feuilles de styles en cascade de HTML3 (css). Pour incorporer un feuille de styles dans votre document, passez un paramètre -style à la méthode start_html(). La valeur de ce paramètre peut être un scalaire, auquel cas il est intégré directement dans une section <STYLE>, ou peut être une référence à une table de hachage. Dans ce dernier cas, votre table de hachage devrait contenir une clé -src et/ou une clé -code. La valeur associée à la clé -src doit être un URL désignant une feuille de styles externe. La valeur associée à la clé -code doit être une valeur scalaire qui sera incorporée dans une section <STYLE>. Les définitions présentes dans -code cacheront celles de même nom présentes dans -src. D'où l'appellation ``en cascade''.
Vous pouvez aussi spécifier le type de feuille de styles en ajoutant un paramètre optionnel -type dans la table de hachage pointée par -style. Le style par défaut est 'text/css'.
Pour vous référer à un style dans le corps de votre document, ajoutez le paramètre -class à n'importe quel élément HTML :
print h1({-class=>'Fancy'},'Welcome to the Party');
Ou définissez le style au vol grâce au paramètre -style :
print h1({-style=>'Color: red;'},'Welcome to Hell');
Vous pouvez aussi utiliser la nouvelle balise span() pour appliquer un style à toute une portion de texte :
print span({-style=>'Color: red;'}, h1('Welcome to Hell'), "Where did that handbasket get to?" );
Notez que vous devez importer l'ensemble de fonctions ``:html3'' pour avoir accès à la méthode span(). Voici un exemple « vite fait, mal fait » d'utilisation des CSS. Voir les spécifications CSS sur http://www.w3.org/pub/WWW/TR/Wd-css-1.html pour plus d'information.
use CGI qw/:standard :html3/;
# ici une feuille de styles directement dans la page $newStyle=<<END; <!-- P.Tip { margin-right: 50pt; margin-left: 50pt; color: red; } P.Alert { font-size: 30pt; font-family: sans-serif; color: red; } --> END print header(); print start_html( -title=>'CGI with Style', -style=>{-src=>'http://www.capricorn.com/style/st1.css', -code=>$newStyle} ); print h1('CGI with Style'), p({-class=>'Tip'}, "Better read the cascading style sheet spec before playing with this!"), span({-style=>'color: magenta'}, "Look Mom, no hands!", p(), "Whooo wee!" ); print end_html;
En passant une référence à un tableau comme paramètre -style, vous pourrez incorporer plusieurs feuille de styles dans votre document.
Si vous utilisez votre script à partir d'une ligne de commande ou dans le debugger Perl, vous pouvez passer au script une liste de mots-clé ou de paires paramètre=valeur sur la ligne de commande ou à partir de l'entrée standard (vous n'avez pas à bidouiller votre script pour qu'il lise les variables d'environnement). Vous pouvez passer les mots-clé ou les paires de la manière suivante :
your_script.pl keyword1 keyword2 keyword3
ou comme ça :
your_script.pl keyword1+keyword2+keyword3
ou comme ça :
your_script.pl name1=value1 name2=value2
ou comme ça :
your_script.pl name1=value1&name2=value2
Pour désactiver cette fonctionnalité, utilisez la directive (pragma) -no_debug.
Pour tester la méthode POST, vous devez activer le mode déverminage complet grâce à la directive -debug. Cela vous permettra de saisir sur l'entrée standard des paires paramètre=valeur séparées par des passages à la ligne.
Lorsque vous déverminer, vous pouvez utiliser les apostrophes, les guillemets et les barres obliques inversées (backslashes) d'une manière classique pour votre shell afin de vous permettre de saisir des espaces ou autres caractères bizarres dans vos paires paramètre=valeur :
your_script.pl "name1='I am a long value'" "name2=two\ words"
La méthode Dump()
produit une chaîne constituée de toutes les paires
nom/valeur de la requête sous la forme de listes imbriquées. C'est pratique
pour déverminer :
print $query->Dump
Produit quelque chose tel que :
<UL> <LI>nom1 <UL> <LI>valeur1 <LI>valeur2 </UL> <LI>nom2 <UL> <LI>valeur1 </UL> </UL>
Comme raccourci, vous pouvez interpoler l'objet CGI complet dans une chaîne et il sera remplacé par un joli code HTML comme ci-dessus :
$query=new CGI; print "<H2>Current Values</H2> $query\n";
(NdT: pour moi, cela n'a jamais marcher...)
Quelques-unes des variables d'environnement les plus utiles peuvent être consultées via cette interface. Les méthodes sont les suivantes :
Remarquez la majuscule qui a été ajoutée entre la version 2.43 et la version 2.44 afin d'éviter un conflit avec la fonction Perl accept().
cookie()
pour un
moyen de positionner et retrouver des cookies tout cuits.
Appelée sans paramètres, raw_cookie()
retourne la structure compacte des
cookies. Vous pouvez séparer les différents cookies en la découpant (par
split) avec comme séparateur la séquence de caractères ``; ''. Appelée avec le
nom de l'un des cookies, retrouve ce cookie sous sa forme non décodée. Vous
pouvez utiliser la méthode cookie()
pour obtenir les noms des cookies ou
utiliser la méthode raw_fetch()
du module CGI::Cookie.
path_info()
retournera ``/additional/stuff''.
Note: Microsoft Internet Information Server est buggué du point de vue des chemins additionnels. Si vous utilisez une bibliothèque DLL Perl, le serveur IIS essayera d'exécuter le chemin additionnel comme un script Perl. Si vous utilisez le fichier ordinaire d'association, l'information de chemin sera présente dans l'environnement mais de manière incorrecte. La meilleurs chose à faire est d'éviter l'utilisation des chemins additionnels dans les scripts CGI utilisés avec IIS.
path_info()
sauf que le chemin additionnel est transformé en un chemin
d'accès physique, e.g. ``/usr/local/etc/httpd/htdocs/additional/stuff''.
Microsoft IIS est tout aussi buggué pour ce chemin transformé.
multipart/form-data
ou application/x-www-form-urlencoded
.
Par exemple, les trois exemple suivants sont équivalents :
$requested_language = $q->http('Accept-language'); $requested_language = $q->http('Accept_language'); $requested_language = $q->http('HTTP_ACCEPT_LANGUAGE');
Les scripts NPH ou ``no-parse-header'' (``en-tête non analysé'') shunte complètement le serveur en envoyant directement tous les en-têtes HTTP au navigateur. Cela peut amener un bénéfice en performance mais c'est surtout utilisé pour tirer avantage d'extensions HTTP qui ne seraient pas supportées directement par votre serveur telles que le ``push'' ou les en-têtes ``PICS'' (Platform for Internet Content Selection).
Les serveurs utilisent différentes conventions pour indiquer que des scripts CGI sont NPH. La plupart des serveurs Unix cherche le préfixe ``nph-'' au début du nom du script. Le serveur Macintosh WebSTAR et Microsoft's Internet Information Server, au contraire, décide si un script est NPH en examinant la première ligne produite par le script.
CGI.pm supporte les scripts NPH grâce à un mode NPH spécial. Lorsque ce mode
est utilisé, CGI.pm produira les en-têtes supplémentaires nécessaires lorsque
les méthodes header()
ou redirect()
seront appelées.
Microsoft Internet Information Server utilise obligatoirement le mode NPH. Depuis la version 2.30, CGI.pm détecte automatiquement lorsque le script est appelé depuis IIS et se met tout seul dans le mode NPH. Bien que vous n'avyez pas besoin de le faire manuellement, cela n'entraîne rien de fâcheux si vous le faites.
Il y a plusieurs moyens pour passer CGI.pm en mode NPH :
use CGI qw(:standard -nph)
CGI->nph(1)
header()
ou redirect()
print $q->header(-nph=>1);
CGI.pm propose trois fonctions simples pour produire des documents multipart, le type nécessaire pour implémenter le « server push ». Ces fonctions ont été gracieusement fournies par Ed Jordan <ed@fidalgo.net>. Pour les importer dans votre espace de noms, vous devez importer l'ensemble ``:push''. Vous devez aussi mettre votre script en mode NPH et positionner la variable $| à 1 pour éviter les problèmes de tampon (bufferisation).
Voici un script simple qui illustre le « server push » :
#!/usr/local/bin/perl use CGI qw/:push -nph/; $| = 1; print multipart_init(-boundary=>'----------------here we go!'); while (1) { print multipart_start(-type=>'text/plain'), "The current time is ",scalar(localtime),"\n", multipart_end; sleep 1; }
Ce script initialise le « server push » en appelant multipart_init(). Il rentre ensuite dans une boucle infinie dans laquelle il débute une nouvelle section multipart en appelant multipart_start(), affiche l'heure locale et termine la section multipart en appelant multipart_end(). Il attend alors une seconde et recommence.
multipart_init()
multipart_init(-boundary=>$boundary);
Initialise le système multipart. L'argument -boundary spécifie quelle chaîne MIME servira de borne pour séparer les différentes parties du document. Si non spécifié, CGI.pm choisira pour vous une borne raisonnable.
multipart_start()
multipart_start(-type=>$type)
Démarre une nouvelle partie d'un document multipart en utilisant le type MIME spécifié (par -type). Par défaut, c'est le type text/html.
multipart_end()
multipart_end()
Termine une partie. Souvenez-vous que vous devez appeler multipart_end()
pour
chaque appel à multipart_start().
Les utilisateurs intéressés par les applications « server push » devrait jeter un oeil au module CGI::Push.
Un problème potentiel avec CGI.pm est que, par défaut, il tente de traiter les formulaires POSTés quel que soit la taille qu'ils ont. Un hackeur rusé pourrait attaquer votre site en envoyant à un script CGI un énorme POST de plusieurs méga-octets. CGI.pm tentera de lire entièrement ce POST dans une variable, gonflant ainsi en taille jusqu'à saturation de la mémoire. Pendant que le script tentera d'allouer la mémoire, le système ralentira dramatiquement. C'est une forme d'attaque par déni de service.
Une autre attaque possible pour un utilisateur distant consiste à contraindre CGI.pm à accepter le téléchargement d'un énorme fichier. CGI.pm acceptera le téléchargement et le stockera dans un répertoire temporaire même si votre script ne s'attend pas du tout à recevoir un fichier téléchargé. CGI.pm effacera automatiquement ce fichier lorsque le script s'arrêtera mais en attendant l'utilisateur distant aura réussi à remplir l'espace disque du serveur causant ainsi des problèmes à d'autres programmes.
Le meilleur moyen d'éviter ces attaques de déni de service est de limiter le quantité de mémoire, de temps CPU et d'espace disque qu'un script CGI peut utiliser. Quelques serveurs WEB possèdent des fonctionnalités intégrées pour accomplir cela. Dans les autres cas, vous pouvez utiliser les commandes shell limit ou ulimit pour plafonner l'utilisation des ressources par les CGI.
CGI.pm propose lui-aussi quelques fonctionnalités simples de protection contre les attaques de type déni de service mais vous devez les activer explicitement. Elles se présentent sous la forme de deux variables globales dans l'espace de nom CGI :
Vous pouvez utiliser ces variables de deux manières.
use CGI qw/:standard/; use CGI::Carp 'fatalsToBrowser'; $CGI::POST_MAX=1024 * 100; # max 100K posts $CGI::DISABLE_UPLOADS = 1; # no uploads
Une tentative d'envoi d'un POST plus large que $POST_MAX octets aura pour
conséquence le retour par la fonction param() d'une liste de paramètres CGI
vide. Vous pouvez tester cela en vérifiant cgi_error(), soit après avoir
créé l'objet CGI soit, si vous utilisez l'interface orientée fonction, après
le premier appel à param(). Si le POST est trop volumineux alors cgi_error()
retournera le message ``413 POST too large''.
Ce message est défini par le protocole HTTP et est conçu pour être retourné au navigateur en tant que code d'état (status) du script CGI. Par exemple :
$uploaded_file = param('upload'); if (!$uploaded_file && cgi_error()) { print header(-status=>cgi_error()); exit 0; }
Par contre, il n'est pas sûr que tous les navigateurs sachent quoi faire de ce code d'état. Il peut être intéressant de créer une page HTML qui informe l'utilisateur de ce problème.
Pour faciliter la migration des programmes existant qui utilisent cgi-lib.pl, la routine de compatibilité ``ReadParse'' est fournie. La migration est simple:
ANCIENNE VERSION require "cgi-lib.pl"; &ReadParse; print "The value of the antique is $in{antique}.\n";
NOUVELLE VERSION use CGI; CGI::ReadParse print "The value of the antique is $in{antique}.\n";
La routine ReadParse()
de CGI.pm crée une variable liée (par tie())
nommée %in
qui peut être utilisée pour accéder aux paramètres de la requête. Comme avec
ReadParse, vous pouvez aussi fournir votre propre variable. Les
fonctionnalités très peu utilisées de ReadParse telles que la création de @in
ou de $in ne sont pas supportées.
Une fois que vous avez utilisé ReadParse, vous pouvez retrouver l'objet requête lui-même par ce moyen :
$q = $in{CGI}; print $q->textfield(-name=>'wow', -value=>'does this really work?');
Cela vous permet de commencer à utiliser les fonctionnalités les plus intéressantes de CGI.pm sans nécessité une réécriture complète de votre vieux script.
Copyright 1995-1998, Lincoln D. Stein. Tous droits réservés.
Cette bibliothèque est un logiciel libre ; vous pouvez la redistribuer et/ou la modifier dans les mêmes conditions que Perl.
Envoyer les rapports de bug et les commentaires (en anglais) à : lstein@cshl.org. Lorsque vous envoyez un rapport de bug, précisez la version de CGI.pm, la version de Perl, le nom et la version de votre serveur Web ainsi que le nom et la version du système d'exploitation que vous utilisez. Si le problème dépend de navigateur utilisé, envoyez aussi les informations concernant ce navigateur.
Copyright 1995-1998, Lincoln D. Stein. All rights reserved.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Address bug reports and comments to: lstein@cshl.org. When sending bug reports, please provide the version of CGI.pm, the version of Perl, the name and version of your Web server, and the name and version of the operating system you are using. If the problem is even remotely browser dependent, please provide information about the affected browers as well.
Merci à :
#!/usr/local/bin/perl
use CGI;
$query = new CGI;
print $query->header; print $query->start_html("Example CGI.pm Form"); print "<H1> Example CGI.pm Form</H1>\n"; &print_prompt($query); &do_work($query); &print_tail; print $query->end_html;
sub print_prompt { my($query) = @_;
print $query->start_form; print "<EM>What's your name?</EM><BR>"; print $query->textfield('name'); print $query->checkbox('Not my real name');
print "<P><EM>Where can you find English Sparrows?</EM><BR>"; print $query->checkbox_group( -name=>'Sparrow locations', -values=>[England,France,Spain,Asia,Hoboken], -linebreak=>'yes', -defaults=>[England,Asia]);
print "<P><EM>How far can they fly?</EM><BR>", $query->radio_group( -name=>'how far', -values=>['10 ft','1 mile','10 miles','real far'], -default=>'1 mile');
print "<P><EM>What's your favorite color?</EM> "; print $query->popup_menu(-name=>'Color', -values=>['black','brown','red','yellow'], -default=>'red');
print $query->hidden('Reference','Monty Python and the Holy Grail');
print "<P><EM>What have you got there?</EM><BR>"; print $query->scrolling_list( -name=>'possessions', -values=>['A Coconut','A Grail','An Icon', 'A Sword','A Ticket'], -size=>5, -multiple=>'true');
print "<P><EM>Any parting comments?</EM><BR>"; print $query->textarea(-name=>'Comments', -rows=>10, -columns=>50);
print "<P>",$query->reset; print $query->submit('Action','Shout'); print $query->submit('Action','Scream'); print $query->endform; print "<HR>\n"; }
sub do_work { my($query) = @_; my(@values,$key);
print "<H2>Here are the current settings in this form</H2>";
foreach $key ($query->param) { print "<STRONG>$key</STRONG> -> "; @values = $query->param($key); print join(", ",@values),"<BR>\n"; } }
sub print_tail { print <<END; <HR> <ADDRESS>Lincoln D. Stein</ADDRESS><BR> <A HREF="/">Home Page</A> END }
Ce module est énorme et monolithique. De plus il fait de nombreuses choses telles la manipulation d'URL, l'analyse des entrés CGI, l'écriture du HTML, etc. qui sont aussi faites dans le modules LWP. Il devrait être abandonné en faveur des modules CGI::* mais je continue à travailler dessus.
Remarquez que le code est parfois tordu pour éviter des avertissements inutiles lorsque les programmes utilisent l'option -w.
la page de manuel CGI::Carp, la page de manuel URI::URL, la page de manuel CGI::Request, la page de manuel CGI::MiniSvr, la page de manuel CGI::Base, la page de manuel CGI::Form, la page de manuel CGI::Push, la page de manuel CGI::Fast, la page de manuel CGI::Pretty