Techniques de Programmation pour Internet

Année Spéciale Informatique

ENSIMAG 2002- 2003

James L. Crowley

Séance 5

04 mars 2003

Common Gateway Interface

Plan :

CGI : Common Gateway Interface

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é.

Formulaires HTML


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">

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

Exécution d'un script par une ficher HTML

Exemple d'un script CGI appelé par href

Soit le script s5.1.cgi installé en cgi-bin.

#!/usr/local/bin/perl

#file s5.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.

Le html du formulaire s5.0.html

<HTML>

<TITLE>Who is logged in? </TITLE>

<BODY BGCOLOR=#FFFFFF >

<H1>Who is logged on?</H1>

<A HREF="/cgi-bin/jlc/Seance5/s5.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/jlc/Seance5/s5.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 s5.1.html

<HTML>

<TITLE>Qui est sur la systeme ?</TITLE>

<BODY BGCOLOR=#FFFFFF >

<FORM ACTION ="/cgi-bin/jlc/Seance5/s5.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/jlc/Seance5/s5.1.cgi?

Passage des Paramètres aux SCRIPTs : GET et POST

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.

Méthode GET ou POST ?

GET

POST

Passage des Paramètres avec GET

File s5.2.html

<HTML>

<TITLE>Exemple d'une Forme</TITLE>

<BODY BGCOLOR=#FFFFFF >

<FORM ACTION ="/cgi-bin/s5.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 s5.2.cgi

#!/usr/local/bin/perl

#file name s5.2.cgi

print "Content-type: text/html", "\n\n";

print "<HTML>" , "\n";

print "<TITLE>s5.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/s5.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{...}

Environnement du serveur

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

Exemple d'accès aux variables d'environnement

#!/usr/local/bin/perl

# file s5.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 : s5.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/s5.3.cgi">Variables</A>

de l'environement.

<br>

</FORM>

</BODY>

</HTML>

Codage des Paramètres

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);

Extraction des paramètres

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 s5.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 s5.4.html

<HTML>

<TITLE>Commandes UNIX</TITLE>

<BODYBGCOLOR=#FFFFFF >

<FORM ACTION ="/cgi-bin/jlc/Seance5/s5.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 :

s5.5.html : Exécuter une commande à partir d'un formulaire.

<HTML>

<TITLE>Commandes UNIX</TITLE>

<BODYBGCOLOR=#FFFFFF >

<FORM ACTION ="/cgi-bin/s5.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>

s5.5.cgi :

#!/usr/local/bin/perl

# File name s5.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.

Passage des Paramètres avec POST

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 : s5.6.html

<HTML>

<TITLE>Exemple d'une Forme</TITLE>

<BODY BGCOLOR=#FFFFFF >

<H1>Veuillez completer ce formulaire</H1>

<FORM ACTION ="/cgi-bin/s5.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>

s5.6.cgi

#!/usr/local/bin/perl

print "Content-type: text/html", "\n\n";

print "<HTML>" , "\n";

print "<TITLE>s5.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);

Accommodation de GET et POST.

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")
{
} elseif ($method eq "POST")
{
} else
{
}

Exemple :

#!/usr/local/bin/perl

#file s5.7.cgi

print "Content-type: text/html", "\n\n";

print "<HTML>" , "\n";

print "<TITLE>s5.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 : s5.7.html

<HTML>

<TITLE>Exemple d'une Forme</TITLE>

<BODY BGCOLOR=#FFFFFF >

<H1>Veuillez completer ce formulaire</H1>

<FORM ACTION ="/cgi-bin/jlc/Seance5/s5.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>