SELFHTML/Aides à la navigation CGI/Perl Éléments de langage Perl |
Travaux CGI typiques en Perl | |
Solutions CGI typiques en Perl |
|
Perl diffère par exemple de PHP ou de ASP en ce qu'il n'est pas conçu spécialement pour des applications Web, mais qu'il est un langage de programmation ouvert pour des solutions de toutes sortes basées sur des scripts. Il possède cependant des propriétés qui le qualifient comme langage pour les scripts CGI: En font partie les puissantes fonctions pour le traitement des chaînes de caractères et les descripteurs de fichier, mais aussi les nombreuses fonctions spécifiques à Unix, parmi lesquelles les scripts CGI écrits en Perl et qui sont mis en œuvre dans des environnements typiques de serveurs Web comme Linux et Apache et dont vous pouvez profiter. Par la conception modulaire de Perl, il existe entre-temps des modules qui se prêtent spécialement à l'utilisation dans les scripts CGI - avant tout le module CGI, dons vous disposez à chaque installation standard de Perl. Vous devez en tous cas voir de plus près les possibilités de ce module quand vous écrivez des scripts CGI.
Si vous manquez encore d'assurance en Perl et ne vous sentez pas de taille pour programmer une application CGI de bout en bout d'après vos propres idées, alors vous pouvez piocher dans les nombreux scripts disponibles sur la toile. Il existe de nombreux fournisseurs qui proposent des scripts en gratuiciel ou en partagiciel. Pour faire tourner un tel script sur votre serveur ou sur un environnement HTTP local et l'adapter à vos besoins, vous devez toutefois vous attaquer au texte source du script et pouvoir retracer la logique de programmation appliquée par le développeur du script. Quand vous avez de la chance, le script de votre choix est bien documenté et il n'est pas difficile de l'adapter à ses propres besoins. Dans l'index des liens de l'offre en ligne de SELFHTML actuel, vous trouverez un récapitulatif de fournisseurs de scripts CGI tout faits en Perl et autres langages:
Index de liens SELFHTML: CGI/Perl
Ci-après, quelques domaines d'application typiques de scripts CGI sont abordés. Il est décrit à quoi ressemble le déroulement du programme d'un script correspondant, et quelles composantes de Perl y sont indispensables. Les descriptions contiennent des liens aux endroits où vous trouverez d'autres détails.
Un compteur d'accès peut être soit graphique, soit basé sur le texte. Pour un compteur graphique, le script CGI est appelé en HTML au moyen d'un repère <img>
- Exemple (HTML):
<img src="/cgi-bin/counter.pl" alt="Compteur"> |
Pour un compteur basé sur le texte, cela se fait à l'aide de Server Side Includes - Exemple (HTML):
<!--#exec cgi="/cgi-bin/counter.pl"--> |
Le script appelé doit d'abord lire le fichier avec l'état actuel du compteur, incrémenter le compteur de 1 et écrire le nouvel état du compteur dans le fichier. Pour cela existent en Perl les Fonctions pour l'entrée et la sortie et la lecture et l'écriture de données. Quand il s'agit d'un compteur basé sur le texte, le script peut envoyer l'état du compteur par exemple avec un entête HTTP avec le type Mime text/html
au navigateur, qui insère le nombre à l'endroit de l'instruction Server-Side-Include. Pour un compteur graphique, le script doit retourner un graphique du type GIF, PNG ou bien JPEG, étant donné que le navigateur attend quelque chose d'équivalent dans son repère <img>
. Les graphiques PNG peuvent être créés de façon dynamique en Perl par exemple avec le module CPAN nommé GD
.
Le formulaire courriel résout le fâcheux problème mailto
pour les formulaires HTML. Un tel script peut traiter un formulaire HTML quelconque et envoyer les données par courriel à un destinataire prévu, en règle générale le fournisseur du projet Web. En HTML, le formulaire courriel est simplement mentionné comme attribut action
dans le formulaire HTML - Exemple:
<form action="/cgi-bin/formmail.pl" method="post"> |
Le script est appelé quand un utilisateur envoie le formulaire. Le script doit utiliser le traitement de formulaires avec le module CGI, pour lire les données de formulaire transmises. Ensuite il doit composer un courriel avec les données du courriel. Pour ce faire sont avant tout importants l' opérateur pour concaténer des chaînes de caractères et les fonctions pour les chaînes de caractères, mais aussi des connaissances sur la construction d'un courriel ainsi que sur la façon d'envoyer un courriel. La suite d'instructions typiques pour le faire est la suivante:
my $Sendmail_Prog = "/usr/lib/sendmail"; open(MAIL,"|$Sendmail_Prog -t") || print "Le programme de courrier électronique n'a pas pu être lancé\n"; print MAIL "To: $mailto\n"; print MAIL "Subject: $subject\n\n"; print MAIL "$texte_courriel\n"; close(MAIL) || print "Erreur lors de l'envoi du courriel!"; |
L'important lors de l'application de la fonction open est que le programme sendmail
, qui envoie les courriels soit aussi effectivement présent, et cela dans le chemin mentionné. Le chemin de l'exemple et la disponibilité de sendmail
se basent à des ordinateurs Unix typiques. Demandez le cas échéant à votre fournisseur d'accès! Le courriel lui-même comme vous pouvez le voir dans l'exemple est écrit avec des instructions print
dans le canal d'entrée et sortie du programme sendmail
nommé avec open
- dans l'exemple, il s'agit du canal nommé MAIL
. Il est important que le courriel contienne une première ligne commençant par To:
et une autre commençant par Subject:
. Avant la sortie du texte du courriel, donc des données du formulaire préparées auparavant pour la sortie, deux caractères de contrôle \n\n
doivent être notés, donc une ligne vide. La façon et le moyen de transmettre les données peut varier. Consultez de toutes façons les instructions et les questions fréquemment posés chez votre fournisseur d'accès et le cas échéant, les instructions de votre programme de courrier électronique!
Outre l'envoi du courriel, le script doit naturellement aussi envoyer une sortie au navigateur à l'aide d'une instruction CGI nécessaire en Perl. Pour un formulaire courriel, il l'agit logiquement d'une page de remerciements qui confirme à l'utilisateur que son formulaire a bien été traité.
Dans l'offre en ligne de SELFHTML actuel, vous trouverez un article spécialisé: formulaire courriel simple, qui décrit un exemple complet d'un formulaire courriel.
Il y a plusieurs façons de programmer un livre de visites. L'une d'entre elles est d'écrire les inscriptions du livre de visites dans un fichier HTML statique qui est affiché quand l'utilisateur appelle le livre de visites. Le fichier pourrait contenir un formulaire dans lequel l'utilisateur peut porter sa propre inscription comme l'ont été les inscriptions existantes. Le script qui gère le livre de visites est alors appelé quand l'utilisateur envoie le formulaire avec sa propre inscription. Pour ce faire est noté dans le repère d'ouverture <form>
un appel correspondant - Exemple:
<form action="/cgi-bin/guestbook.pl" method="post"> |
Le script doit utiliser le traitement de formulaires avec le module CGI pour lire les données de formulaire transmises. Supposons que le formulaire ait deux champs: un pour le nom du visiteur qui écrit dans le livre de visites (name="nom_utilisateur"
), et un pour le texte (name="texte_utilisateur"
). Ensuite il serait possible, après la lecture avec le module CGI en Perl, d'accéder au contenu du champ nom_utilisateur
avec par exemple une construction telle que $cgi->param($nom_utilisateur)
.
De plus le script doit lire le fichier HTML avec les inscriptions faites jusqu'alors. Avec la fonction open par exemple, le fichier peut être ouvert et peut ensuite être lu par exemple dans une liste. Chaque élément de la liste est alors une ligne du fichier HTML.
Pour que le script s'y retrouve dans le code HTML qu'il lit et sache où il doit insérer les nouvelles données, le fichier doit contenir, à l'endroit correspondant sur une ligne distincte, une "marque secrète", ce qui peut être résolu par un commentaire HTML - Exemple:
<!-- NOUVEAU --> |
Mais il est également judicieux que le fichier HTML mette encore à la disposition du script une notice interne, sur une ligne distincte avant chaque inscription existante . Cela aussi et possible avec des commentaires. Exemple d'une inscription dans le fichier HTML:
<!-- INSCRIPTION [Christian Delacroix] [21.04.2002]--> <table border="1"><tr> <th>von:</th><td>Christian Delacroix</td> <th>am:</th><td>21.04.2002</td> </tr><tr> <td colspan="2">Cette page magnifique a tranformé ma vie etc...</td> </tr></table> |
Cela facilite ensuite pour le script une recherche éventuelle dans le fichier. Pour insérer les données de formulaire que le script s'est vu transmettre et a lues, il doit d'abord composer le code habituel pour une inscription dans le livre de visites et y insérer les données du formulaire. Dans l'exemple, le script composerait donc un tableau HTML et mettrait dans les cellules prévues à cet effet, les valeurs des données du formulaire. Le mieux est que le script déclare pour cela une liste et lui affecte pour chaque ligne du code HTML un élément avec le code HTML correspondant. À la fin de chaque inscription dans une liste doit figurer \n
pour "nouvelle ligne". Pour le faire, vous avez besoin de la fonction push et de l' opérateur pour concaténer des chaînes de caractères - Exemple:
my @nouvelle_inscription; push(@nouvelle_inscription, "<!-- INSCRIPTION [".$cgi->param($nom_utilisateur)."] [".$Datum."]-->\n"); push(@nouvelle_inscription, "<table border=\"1\"><tr>\n"); push(@nouvelle_inscription, "<th>von:</th><td>".$cgi->param($nom_utilisateur)."</td>\n"); push(@nouvelle_inscription, "<th>le:</th><td>".$Datum."</td>\n"); push(@nouvelle_inscription, "</tr><tr>\n"); push(@nouvelle_inscription, "<td colspan=\"2\">".$cgi->param($texte_utilisateur)."</td>\n"); push(@nouvelle_inscription, "</tr></table>\n"); |
La date du jour sauvegardée dans $Datum
doit naturellement être d'abord recherchée par le script. Pour cela existent les fonctions pour la date et l'heure.
Le script doit maintenant insérer la nouvelle inscription à l'endroit où dans le fichier établi jusqu'alors, figure la marque pour l'insertion avec <!-- NOUVEAU -->
. Il y a une variante possible qui consiste à faire une nouvelle liste, composée des lignes de l'ancien fichier et des lignes de la nouvelle inscription. Pour cela le script peut traiter dans une boucle foreach l liste avec les lignes lues du fichier et à l'aide d'une Expression régulière de chercher /^<!-- NOUVEAU -->$/
et d'insérer à l'endroit correspondant la liste avec la nouvelle inscription. Le code pourrait par exemple ressembler à:
my @nouvelles_lignes; my $ligne; foreach $ligne (@lignes) { # @lignes = lignes du fichier lues auparavant if(/^<!-- NEU -->/) { # bien, insérer l'inscription ici foreach(@nouvelle_inscription) { # @nouvelle_inscription = lignes HTML composées auparavant push(@nouvelles_lignes,$_); # ajouter ligne par ligne } push(@nouvelles_lignes,"<!-- NOUVEAU -->\n"); # pour la prochaine fois ... } else { # chaque ancienne ligne qui ne contient pas /^<!-- NOUVEAU -->/ push(@nouvelles_lignes,$ligne); # copier simplement dans la nouvelle liste } } |
La nouvelle liste @nouvelles_lignes
contient donc ensuite le lignes de la nouvelle version du fichier HTML du livre de visites. Cette liste doit simplement maintenant être écrite encore dans le même fichier qui a été lu auparavant. Cela marche avec l'ouverture en écriture avec open et l'écriture dans le descripteur du fichier du fichier ouvert avec print.
Pour finir, le script ne doit naturellement pas oublier d'envoyer une sortie au navigateur à l'aide d'une instruction CGI nécessaire en Perl . le mieux est bien de sortir simplement un entête HTTP et @nouvelles_lignes
. Ce sont deux commandes print
, et déjà l'utilisateur qui a envoyé le formulaire peut voir le livre de visites avec sa propre inscription.
Il y a bien sûr encore beaucoup d'autres choses importantes que le livre de visites doit régler. Pae exemple, les fichiers qu'un script CGI ouvre doivent être protégés essentiellement contre un accès multiple accidentel - car deux utilisateurs peuvent très bien en même temps envoyer un formulaire avec une nouvelle inscription. Alors deux processus avec le même script se gêneraient l'un l'autre. Ce qu'on appelle le verrouillage de fichier pour la protection de l'accès marche avec la fonction flock. De plus, le script doit réagir quand le fichier HTML avec les inscriptions du livre de visites devient trop important. Dans ce cas, le script pourrait écrire une partie de la liste avec les inscriptions les plus anciennes dans un deuxième fichier et lier ce fichier avec le fichier avec les inscriptions plus récentes, c'est à dire donc poser un lien HTML au deuxième fichier dans le premier fichier.
Vous n'avez pas besoin d'une base de données pour chaque application, avec laquelle un visiteur de pages Web peut demander des données. Les stocks de données d'une taille ne dépassant quelques Megaoctets et qui ne sont pas utilisés trop intensément, peuvent tout à fait se garder aussi dans des fichiers texte (par exemple séparés par des virgule ou dans une structure XML), qui peuvent ensuite être gérés avec des scripts CGI en Perl. Vous avez besoin quelque soit le cas de figure d'une "Application frontale" publique (donc une application Web) pour les requêtes à un stock de données ou bien d'une application frontale accessible seulement en interne pour la gestion d'un stock de données (également une application Web qui rend possible l'ajout, la modification et l'effacement d'enregistrements au moyen de formulaire. Vous ne devez ensuite choisir une véritable banque de données que lorsque le stock de données nécessite une maintenance intensive (beaucoup de modifications dans le stock de données - un cas pour le "verrouillage de tableaux"), ou bien quand la structure des données est fortement relationnelle et travaille avec de nombreuses consultations de tables, ou lorsque le stock de données est vraiment très grand et que sa taille approximative dépasse quelques mégaoctets Il faut bien sûr que sur le serveur un logiciel de bases de données correspondant soit installé - par exemple le produit gratuiciel populaire MySQL. Ce dernier s'est imposé entre-temps de telle façon dur la toile qu'il est pratiquement sans concurrence pour des bases de données relationnelles de taille moyenne. Demandez le cas échéant à votre fournisseur d'accès si vous disposez de MySQL là ou vous avez loué un emplacement sur le WWW ou plutôt prenez ce facteur en compte lors du choix de votre fournisseur d'accès dans la mesure ou vous avez besoin d'une liaison de données. MySQL est certes utilisé essentiellement en relation avec PHP, mais il est tout aussi possible d'écrire avec Perl des applications frontales de bases de données pouvant communiquer avec MySQL.
Avant d'écrire une application frontale de base de données en Perl, vous devez d'abord vous attaquer intensivement à MySQL, aux interfaces de bases de données et au langage de requête SQL. Pour cela il y a des documentations et des livres. Dans l'index des liens de l'offre en ligne de SELFHTML actuel vous trouverez les liens correspondants:
SELFHTML index des liens: Liaison de données
Cette partie succincte ne peut ici traiter que quelques détails généraux du point de vue de Perl. Dans un script Perl qui doit communiquer avec une base de données MySQL, il faut y faire figurer au début des lignes analogues à celles-ci:
use CGI; use DBI; my $DB_NAME = "produits"; my $DB_DSN = "DBI:mysql:database=$DB_NAME"; my $DB_USER = ""; my $DB_PASSWD = ""; my $dbh = DBI->connect($DB_DSN, $DB_USER, $DB_PASSWD) or die "Erreur lors de la liaison avec la base de données: $!"; |
DBI
est un module CPAN, dont vous avez besoin en règle générale pour pouvoir accéder avec Perl aux bases de données. Il représente une interface indépendante des bases de données, aux différents pilotes spécifiques aux bases de données. Votre script Perl communique donc avec la base de données en ce sens qu'il utilise les fonctions et méthodes du module DBI.
Dans l'exemple de code, le script déclare quelques scalaires, qui sont indispensables pour le module et la liaison avec la base de données. $DB_NAME
est le nom de la base de données. DB_DSN
est une information pour le module DBI concernant le pilote devant être utilisé pour la liaison avec la base de données (dans l'exemple: mysql
), et quelle est la base de données à ouvrir (dans l'exemple la base de données sauvegardée dans $DB_NAME
). Comme le serveur SQL de MySQL, qui surveille les accès à la base de données et les sorties vers des processus externes appelants, ne lâche les données des bases de données que contre l'identification et le mot de passe de l'utilisateur, ceux-ci sont également à mentionner lors de la liaison à la base de données. Dans l'exemple, les scalaires correspondantes $DB_USER
et $DB_PASSWD
se voient affecter un contenu vide. Pour une utilisation autorisée de la base de données, vous devez cependant mentionner ici les données d'identification.
Avec DBI->connect(...)
la liaison à la base de données est établie. La valeur retournée est sauvegardée dans une variable du descripteur de la base de données, dans l'exemple $dbh
. Par ce descripteur vous pouvez, dans le déroulement ultérieur du script adresser les fonctions ou méthodes du module DBI comme dans cet exemple:
my @DB_champs = $dbh->list_fields('donnees_produits'); $dbh->disconnect; |
list_fields
recherche les noms de champs d'une certaine table de la base de données, dans l'exemple, la table donnees_produits
. Avec $dbh->disconnect
une liaison à la banque de données est refermée à la fin. La communication proprement dite avec la base de données a cependant lieu par des commandes SQL appropriées. L'exemple qui suit montre comment noter ces commandes dans un script Perl et lancer ensuite une requête dans la base de données:
my $SQL_Statement = "SELECT numero, nom, description FROM donnees_produits ". "WHERE donnees_produits.numero >= ".$cgi->param($de_numero). " AND donnees_produits.numero <= ".$cgi->param($a_numero). " ORDER BY ".$cgi->param($champ_tri); my $requete = $dbh->prepare($SQL_Statement); $requete->execute(); my @Datensatz; while(@enregistrement = $requete->fetchrow_array()) { traiter_enregistrement(@enregistrement); } |
Pour la requête dans la base de données, vous devez former une commande SQL et la sauvegarder dans une scalaire. Pour cela, vous devez connaître la syntaxe SQL. Normalement, il en ira comme dans l'exemple et votre script CGI tirera les paramètres de la requête d'un formulaire HTML, que l'utilisateur qui a appelé le script en envoyant le formulaire, a rempli. Pour cela, le script doit utiliser le traitement de formulaires avec le module CGI pour lire les données de formulaire transmises. Une construction dynamique d'une commande SQL à partir des données de formulaire est alors possible avec l' opérateur pour concaténer des chaînes de caractères. À la fin la commande $requete = $dbh->prepare($SQL_Statement)
fait savoir au module DBI le souhait d'effectuer une requête. et après la commande de requête peut être lancée avec $requete->execute()
. La base de données renvoie maintenant dans l'ordre tous les enregistrements trouvés. Chaque enregistrement comprend plusieurs champs. Chaque enregistrement est retourné séparément en tant que liste. Dans une boucle while, qui tourne aussi longtemps que l'appel de $requete->fetchrow_array()
donne un nouvel enregistrement, un sous-programme nommé traiter_enregistrement
est appelé dans l'exemple et reçoit comme paramètre, la liste actuelle de l'enregistrement. Ce sous programme pourrait par exemple préparer le code HTML pour la sortie d'un enregistrement. Car il faut qu'ensuite le script envoie une sortie au navigateur à l'aide d'une instruction CGI nécessaire en Perl.
Pour la gestion de la base de données par une application frontale script Perl/formulaire HTML la façon de procéder est très semblable et ne nécessite que des commandes SQL supplémentaires pour l'ajout ou la réécriture d'enregistrements modifiés dans la base de données. Il est important de protéger un tel Front-end pour la maintenance de bases de données interne contre les accès publics. Cela peut se faire en deux temps: d'un côté un tel formulaire d'application frontale ne doit se trouver que dans un répertoire htaccess protégé et de l'autre le formulaire doit également contenir des champs pour le nom d'utilisateur et son mot de passe pour un accès en écriture de la base de données.
Fonctions pour les chaînes de caractères | |
Programmation orientée sur l'objet | |
SELFHTML/Aides à la navigation CGI/Perl Éléments de langage Perl |
© 2001 Stefan Münz / © 2003 Traduction Serge François, 13405@free.fr
selfhtml@fr.selfhtml.org