Séance 6
12 mars 2007
Le "Common Gateway Interface" est un protocole qui permet au page html
d'exécuter les programmes. Ceci autorise les possibilités illimitées aux pages html.
Common : Utilisable dans tous les systèmes d'exploitation et avec tous les langages de programmation.
Gateway : CGI dans accès aux services
Interface : CGI est un protocole formellement spécifié.
On peut exécuter un script à partir d'un page
html via l'usage
d'un formulaire.
Syntaxe de la balise FORM : <FORM ACTION ="script.cgi" METHOD="get">
script.cgi identifie le programme utilisé pour traiter le
formulaire.
méthode définit la méthode
à employer pour transmettre au serveur l'information
recueillie dans les champs du formulaire.
Les scripts cgi sont installés dans un répertoire cgi-bin du serveur.
..[serveur]/cgi-bin/script.cgi
L'ENSIMAG a fait un lien "soft" dans le cgi-bin vers chaque
membre du cours : cgi-bin/jlc -> ~jlc/cgi-bin.
Il faut que les programmes en cgi-bin soient executable par tout le
monde!
Fait le commande :
cd cgi-bin // aller au repertoire
chmod a+x * // all have access executable
Soit le script s6.1.cgi installé en cgi-bin.
#!/usr/local/bin/perl
#file s6.1.cgi
print "Content-type: text/html", "\n\n";
print "<HTML>" , "\n";
print "<TITLE>Current Users</TITLE>" , "\n";
print "<BODY>" , "\n";
print `who`; # le commande "who" est executee
print "</BODY>" , "\n";
print "</HTML>" , "\n";
exit(0);
la ligne "print `who`;" fait appelle à la commande Unix, "who".
La sortie de "who" au STDOUT.
<HTML>
<TITLE>Who is logged in? </TITLE>
<BODY BGCOLOR=#FFFFFF >
<H1>Who is logged on?</H1>
<A HREF="/cgi-bin/s6.1.cgi"> Who</A> is logged on
</FORM>
</BODY>
</HTML>
On peut utiliser "href" ou "form" pour appeler le script.
La différence est dans le passage de paramètres.
Les paramètres sont codés :?arg=value&arg=value
Exemple : /cgi-bin/s6.1.cgi?arg=value&arg=value
Avec des formulaires, la chaîne de caractères des paramètres sont composées automatiquement.
S'on utilise "href" , il faut construire une chaîne de caractères codés pour les paramètres.
Exemple d'un script CGI appelé par un formulaire
L'html du formulaire s6.1.html
<HTML>
<TITLE>Qui est sur la systeme ?</TITLE>
<BODY BGCOLOR=#FFFFFF >
<FORM ACTION ="/cgi-bin/s6.1.cgi" METHOD="get">
<H1>Who is logged on?</H1>
<INPUT TYPE=SUBMIT Value="Who">
</FORM>
</BODY>
</HTML>
Note le "?" a la fin de l'appel. http://ensisun.imag.fr/cgi-bin/s6.1.cgi?
Il y a deux méthodes de passage des paramètres aux scripts :
GET les données sont transmises par avec la requête à l'URL.
POST les données sont envoyées et lues via STDIN.
GET
POST
File s6.2.html
<HTML>
<TITLE>Exemple d'une Forme</TITLE>
<BODY BGCOLOR=#FFFFFF >
<FORM ACTION ="/cgi-bin/s6.2.cgi" METHOD="get">
<H1>Veuillez completer ce formulaire</H1>
<P>Nom: <input name="name" size="48">
<br>
<INPUT TYPE=SUBMIT Value="Valider">
<INPUT TYPE=RESET Value="Reinitialiser">
</FORM>
</BODY>
</HTML>
avec le script s6.2.cgi
#!/usr/local/bin/perl
#file name s6.2.cgi
print "Content-type: text/html", "\n\n";
print "<HTML>" , "\n";
print "<TITLE>s6.2.cgi</TITLE>" , "\n";
print "<BODY>" , "\n";
$query_string = $ENV{'QUERY_STRING'};
print "Script called with $query_string", "\n";
print "</BODY>" , "\n";
print "</HTML>" , "\n";
exit(0);
La requête est :
http://ensisun.imag.fr/cgi-bin/s6.2.cgi?name=Jim+Crowley
La chaîne "name=Jim+Crowley" est retourné par la variable d'environnement
"'QUERY_STRING';
La variable de l'environnement QUERY-STRING contient
une chaîne avec tous les paramètres, avec la forme :
cle=value.
Value est limité à la lettre et nombre.
Les variables d'environnement sont accessibles via $ENV{...}
Les programmes du CGI disposent d'un nombre important de variable d'environnement .
(avec le format protocole://NomServeur:port/path )
QUERY_STRING Chaîne de caractères caractérisant la requête
#!/usr/local/bin/perl
# file s6.3.cgi
print "Content-Type: text/html", "\n\n";
print "<HTML>", "\n";
print "<HEAD> <TITLE>Environnement du serveur</TITLE> </HEAD>", "\n";
print "<HR><PRE>", "\n";
print "Server Name: ", $ENV{'SERVER_NAME'}, "<BR>", "\n";
print "Running on port: ", $ENV{'SERVER_PORT'}, "<BR>", "\n";
print "Server Software",$ENV{'SERVER_SOFTWARE'}, "<BR>", "\n";
print "Server Protocol",$ENV{'SERVER_PROTOCOL'}, "<BR>", "\n";
print "Adresse IP de la machine du serveur: ", $ENV{'HTTP_HOST'}, "<BR>", "\n";
print "Repertoire contenant le serveur", $ENV{'DOCUMENT_ROOT'}, "<BR>", "\n";
print "Adresse IP de la machine cliente", $ENV{'REMOTE_ADDR'}, "<BR>", "\n";
print "Adresse symbolique de la machine cliente: ", $ENV{'REMOTE_HOST'},"<BR>","\n";
print "Login de la personne effectuant la requete:",$ENV{'REMOTE_IDENT'},"<BR>", "\n";
print "</BODY>" , "\n";
print "</HTML>" , "\n";
exit(0);
Avec le page html : s6.3.html
<HTML>
<TITLE>Echo les Variables d'Environement</TITLE>
<BODY BGCOLOR=#FFFFFF >
<H1>Les Variables de l'Environement</H1>
<p>
Les <A HREF="/cgi-bin/s6.3.cgi">Variables</A>
de l'environement.
<br>
</FORM>
</BODY>
</HTML>
1. Les caractères non ASCII (code > 128) sont remplacés par %xx ou xx est le code ASCII.
2. Les caractères réservés sont remplacés par leur code ASCII. Ils sont :
< > " # % ! $ \ & ( ) + = } [ ] \ : ; ~ ? , / [TAB]
3. L'espace est remplacé par le signe +
4. Les pairs noms/valeur sont transformés par la chaîne de caractères : nom=valeur
5. Les différentes chaînes de caractères sont contaminées en insérant le symbole & entre les paires : nom1=valeur1&nom2=valeur2&...
Voici un script PERL pour convertir une chaîne a une chaîne codée pour CGI:
#!/usr/local/bin/perl
print "String to encode: ";
$string = <STDIN>;
chop($string);
string =~ s/(\W)/sprintf("%%%x", ord($1))/eg;
print "Encoded String: ";
print $string, "\n";
exit(0);
On peut décoder les lignes avec une substitution en PERL.
La syntaxe d'une substitution est tr/vieux/nouvelle/
#!/usr/local/bin/perl
print "String to decode: ";
$string = <STDIN>;
chop($string);
$string =~ tr/+/ /;
$string =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack("C", hex($1))/eg;
print "Decoded String: ";
print $string, "\n";
exit(0);
En PERL, on peut convertir les chaînes de la forme nom=valeur dans
une "hash" ou "nom" est la clé et "valeur" est la valeur avec une commande
"split:". Syntaxe : (clé, valeur) = split( /char/, $chaine);
Par exemple :
$query_string = $ENV{'QUERY_STRING'};
($field_name, $command) = split(/=/, $query_string);
#!/usr/local/bin/perl
#file s6.4.cgi
print "Content-type: text/html", "\n\n";
print "<HTML>" , "\n";
print "<TITLE>Execution d'un commande unix</TITLE>" , "\n";
print "<BODY>" , "\n";
$query_string = $ENV{'QUERY_STRING'};
print "query_string : $query_string.<BR>", "\n";
($field, $value) = split(/=/, $query_string);
print "field = $field.<br>value= $value. <br>", "\n";
print "<br>", "\n";
print "<br>", "\n";
print `$value`;
print "</BODY>" , "\n";
print "</HTML>" , "\n";
exit(0);
avec s6.4.html
<HTML>
<TITLE>Commandes UNIX</TITLE>
<BODYBGCOLOR=#FFFFFF >
<FORM ACTION ="/cgi-bin/s6.4.cgi" METHOD="get">
<H1>Executer un commande UNIX</H1>
<br>
<P>Commande: <input name="commande" size="48">
<br>
<INPUT TYPE=SUBMIT Value="Valider">
<INPUT TYPE=RESET Value="Reinitialiser">
</FORM>
</BODY>
</HTML>
S'il y a des arguments, il faut aussi les décoder avec
$form_info =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack("C", hex($1))/eg;
Exemple :
s6.5.html : Exécuter une commande à partir d'un formulaire.
<HTML>
<TITLE>Commandes UNIX</TITLE>
<BODYBGCOLOR=#FFFFFF >
<FORM ACTION ="/cgi-bin/s6.5.cgi" METHOD="get">
<H1>Executer un commande UNIX</H1>
<P>Commande: <input name="commande" size="48">
<br>
<INPUT TYPE=SUBMIT Value="Valider">
<INPUT TYPE=RESET Value="Reinitialiser">
</FORM>
</BODY>
</HTML>
s6.5.cgi :
#!/usr/local/bin/perl
# File name s6.5.cgi
print "Content-type: text/html", "\n\n";
print "<HTML>" , "\n";
print "<TITLE>Execution d'un commande unix</TITLE>" , "\n";
print "<BODY>" , "\n";
#get the query string and decode it
$query_string = $ENV{'QUERY_STRING'};
print "query = $query_string<br>", "\n";
$query_string =~ tr/+/ /; #substitute " " for "+"
$query_string =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack("C", hex($1))/eg;
print "query = $query_string<br>", "\n";
#split the query string at "="
($field_name, $command) = split(/=/, $query_string);
print "Execution du commande : $command", "\n";
print "<br>", "\n";
print "<br>", "\n";
print `$command`;
print "</BODY>" , "\n";
print "</HTML>" , "\n";
exit(0);
L'exemple suivant permet d'exécuter une logicielle ou commande Unix
a partir d'un page web:
Attn. Ceci peut être TRES dangereux. L'utilisateur peut taper "rm -r *"
ou bien n'importe quel autre commande.
Avec POST, il faut lire la réponse par STDIN.
En PERL, ceci se fait par :
$size = $ENV{'CONTENT_LENGTH'};
read (STDIN, $query_string, $size};
exemple : s6.6.html
<HTML>
<TITLE>Exemple d'une Forme</TITLE>
<BODY BGCOLOR=#FFFFFF >
<H1>Veuillez completer ce formulaire</H1>
<FORM ACTION ="/cgi-bin/s6.6.cgi" METHOD="POST">
<P>Nom: <input name="name" size="48">
<br>
<INPUT TYPE=SUBMIT Value="Valider">
<INPUT TYPE=RESET Value="Reinitialiser">
</FORM>
</BODY>
</HTML>
s6.6.cgi
#!/usr/local/bin/perl
print "Content-type: text/html", "\n\n";
print "<HTML>" , "\n";
print "<TITLE>s6.6.cgi</TITLE>" , "\n";
print "<BODY>" , "\n";
$size = $ENV{'CONTENT_LENGTH'};
read (STDIN, $query_string, $size);
print "Script called with $query_string <p>", "\n";
print "Size of query_string is $size.", "\n";
print "query string is $query_string<br>", "\n";
$query_string =~ tr/+/ /; #substitute " " for "+"
$query_string =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack("C", hex($1))/eg;
print "decode of query : $query_string<br>", "\n";
#split the query string at "="
($field_name, $command) = split(/=/, $query_string);
print "Execution du commande : $command", "\n";
print "<br>", "\n";
print "<br>", "\n";
print `$command`;
print "</BODY>" , "\n";
print "</HTML>" , "\n";
exit(0);
La choix de méthode (GET ou POST) est disponible dans la variable
d'environnement : "REQUEST_METHOD".
On peut écrire des scripts qui acceptent les deux méthodes GET et POST.
$method = $ENV{'REQUEST_METHOD'};
if ($method eq "GET")
{
$query = $ENV{'QUERY_STRING'};
} elseif ($method eq "POST")
{
read (STDIN, $query, $ENV{'CONTENT_LENGTH');
} else
{
&return_error(500, "Server Error", "Unsupported Method");
}
Exemple :
#!/usr/local/bin/perl
#file s6.7.cgi
print "Content-type: text/html", "\n\n";
print "<HTML>" , "\n";
print "<TITLE>s6.7.cgi</TITLE>" , "\n";
print "<BODY>" , "\n";
$method = $ENV{'REQUEST_METHOD'};
if ($method eq "GET")
{
$query = $ENV{'QUERY_STRING'};
} elsif ($method eq "POST")
{
$size = $ENV{'CONTENT_LENGTH'};
read (STDIN, $query_string, $size);
} else
{
&return_error(500, "Server Error", "Unsupported Method");
}
print "Script called with query_string: $query", "\n";
print "</BODY>" , "\n";
print "</HTML>" , "\n";
exit(0);
exemple : s6.7.html
<HTML>
<TITLE>Exemple d'une Forme</TITLE>
<BODY BGCOLOR=#FFFFFF >
<H1>Veuillez completer ce formulaire</H1>
<FORM ACTION ="/cgi-bin/s6.7.cgi" METHOD="GET">
<P>Nom: <input name="name" size="48">
<br>
<INPUT TYPE=SUBMIT Value="Valider">
<INPUT TYPE=RESET Value="Reinitialiser">
</FORM>
</BODY>
</HTML>