Luis Colorado A propos de l'Auteur: Luis Colorado travaille comme administrateur de systèmes Unix et d'accès Internet pour Telefónica Sistemas S.A. en Espagne. Il est diplômé de Physique de Universidad Complutense à Madrid et a developpé plusieurs utilitaires libres pour Unix. Ecrire à l'auteur
|
Résumé:
Cet article décrit
un programme qui permet d'accéder à une base de données
depuis une page HTML. L'objectif de ce programme est le contrôle
de l'accès aux données, la flexibilité de la configuration
et l'indépendance vis à vis de la mise en page. Ce programme
est le résultat d'une série d'idées provenant de la
lecture de plusieurs articles sur M4 qui sont sortis récemment dans
les magazines Linux Journal et
LinuxFocus
(www.linuxfocus.org) pendant ces 12 derniers mois.
De plus, la disponibilité de nombreux serveurs web et moteurs de base de données contraste avec le manque d'utilitaires qui permettent d'interfacer les 2 environnements (La majorité de ces applications sont commerciales ou ont de sérieuses insuffisances dans les formats qu'elles peuvent prendre en compte).
Le programme tente d'unifier les 2 mondes grâce à une application qui satisfait les points suivants:
Permettre le contrôle de la sécurité du site. L'application supporte une méthode assez générale pour sélectionner une configuration et peut être facilement configurable pour contrôler l'accès au site web
C'est un fait bien connu que HTML est un langage de formatage pour formater
des documents qui pourront être affichés avec un navigateur
Internet. Une caractéristique de base d'un bon générateur
de texte est un langage convenable pour formater le texte offrant suffisamment
de possiblités de contrôle pour l'arrangement des paragraphes
et parties de texte dans la composition finale de la page. Cependant, dans
la plupart des langages de formatage, il y a toujours une série
de macros qui permettent de manipuler les éléments flottants
du document (tables, images, etc, qui s'ajustent dynamiquement sur la page
au chargement).
La plupart des utilitaires que je connais pour interfacer HTML et des
bases de données, génèrent l'information sur le texte
affiché en étendant le jeu de balises HTML (NdT: en anglais, tag).
Ces nouvelles balises prennent le rôle de 'macros'. Cependant,
cette approche à un serieux inconvénient: La plupart du temps,
nous devons modifier les éléments dans les balises du code HTML natif
et c'est une limitation importante. Souvent, ces utilitatires
doivent créer des balises dans le but d'obtenir un effet déterminé
sur une balise HTML existante. Mon programme utilise M4 dans le but de
remplacer les macros partout où cela est nécessaire.
Le programme ne génère aucun texte formaté, et c'est
pourquoi il est indépendant du format de sortie du langage utilisé.
Le programme génère une série de macros comme résultat
d'une requête puis M4 génère un document HTML en utilisant
ces macros et un modèle HTML donné.
M4 fut originellement développé pour lier
la CGI (Common Gateway Interface) avec la base de données PostgreSQL.
Rapidement, des gens ont réalisé qu'il était suffisamment
général pour supporter d'autres interfaces (par exemple une
passerelle entre une serveur LDAP et d'autres bases de données comme
Informix ou Oracle).
Plus tard, l'interface fut standardisée incorporant toutes les fonctionnalités nécessaires et les modules PostgreSQL furent réécris en fonction de la nouvelle interface. Maintenant, il est possible d'écrire de nouveaux pilotes qui permettent au programme de supporter d'autres gestionnaires de base de données. |
|
Prenons un exemple: Supposons que le client doive nous transmettre des informations dans la QUERY_STRING, au format suivant:
CHAMP=ValeurNotez que la query_string doit satisfaire ce format et aucune information ne doit être ajoutée à la chaîne de caractères.
La mise en oeuvre de cette syntaxe se fait facilement en écrivant les termes suivants dans la règle de sélection:
QUERY_STRING: "^CHAMP=[^&]*$";La ligne ci-dessus garantit que la règle sera invoquée seulement si la QUERY_STRING est au bon format... Mais, de plus, si nous plaçons des parenthèses autour de la valeur, alors le programme pourra analyser la valeur correspondante:
QUERY_STRING: "^CHAMP=([^&]*)$";Dans le processus, le programme transforme les séquences d'échappement de la forme %xx introduite pour le navigateur.
QUERY_STRING: "^CHAMP=([^&]*)$";
! HTTP_ADDRESS: "^194\.142\.12\.";(Cet exemple invalidera la règle si la requête vient de 194.142.12.xxx)
[ QUERY_STRING: "UTILISATEUR=([^&]*)" ];Ces définitions nous permettent de transmettre la valeur de l'utilisateur si le client la fournit mais n'invalide pas la règle si le client ne la spécifie pas. Avec toute cette artillerie, nous pouvons commencer à construire des règles. Nous regrouperons un nombre de termes qui nous permettront de construire une règle valide. Nous les placerons entre accolades "{ }" et nous les appellerons "la partie gauche de la règle".
La partie gauche et la partie droite d'une règle sont délimitées par des accolades "{ }" et sont séparées par le symbole`->'.
La partie droite contient les termes avec une même syntaxe: un nom de variable, le caractère ':', une chaîne de caractères et le caractère fin de chaîne ';'. Tous les termes du coté droit sont des assignations de valeurs à des variables effectuées par M4.
et la règle déclarée dans le site web est :
QUERY_STRING: "NAME=([^&]*)"; QUERY_STRING: "FAMNAME1=([^&]*)"; QUERY_STRING: "FAMNAME2=([^&]*)";Le résultat serait:
term_0_match_0 <- "NAME=JOSE"; term_0_match_1 <- "JOSE"; term_1_match_0 <- "FAMNAME1=DE LA FUENTE" ; (noté le remplacement du caractère + par ` ') term_1_match_1 <- "DE LA FUENTE"; term_2_match_0 <- "FAMNAME2=LOPEZ"; term_2_match_1 <- "LOPEZ";Pilotes:
Nous ne décrirons pas, dans cet article, l'utilisation des pilotes. Tout est déjà expliqué dans la documentation fournie avec la distribution de PG2CGI. Le lecteur intéressé est encouragé à lire le manuel de référence
Pour le moment, il n'existe qu'un seul pilote pour la connexion à la base de données PostgreSQL. Cependant, l'auteur a prévu d'écrire un autre pilote pour les bases de type LDAP.
Un exemple:
Examinons maintenant le source d'un exemple complet.
Considérons la table de déclarations provenant de la base de données de déclarations à slug.cvt.es (Suivez le lien "AVISO A LOS NAVEGANTES"). C'est un exemple très simple qui utilise 2 modèles pour voir des enregistrements individuellement ou une liste complète. /etc/html2sql.cfg
{ PATH_INFO: "^/avisos/?$"; # Selectionne by PATH_INFO [SERVER_ADMIN: ".*"]; # Obtient des informations de SERVER_ADMIN. Optionnel } -> { DRIVER: "POSTGRESQL"; PGTTY: "/dev/console"; # Envoie les log à la console PGDATABASE: "postgres"; # Nous faisons une requête (Toujours écrire l'oid qui # l'utilisera en interne dans le fichier modèle # pour lier les enregistrements individuels). PGQUERY: "select oid,ct,titulo,texto,mt" " from avisos" " where (dt is NULL or dt > 'now')" " order by mt desc"; # Fichier contenant le modèle M4FILE: "/usr/local/etc/httpd/plantillas_m4/avisos.m4"; WEBMASTER: "term_1_match_0"; #TESTMODE: "TRUE"; } # La règle de sélection suivante permet de sélectionner une déclaration (aviso) # avec un OID connu (clé primaire ou primary key). L'information est incluse dans # la variable PATH_INFO de la CGI. { PATH_INFO: "^/avisos/([0-9]+)/?$"; SERVER_ADMIN: ".*"; } -> { DRIVER: "POSTGRESQL"; PGTTY: "/dev/console"; # Comme précédemment, permet d'écrire les "logs" sur la console PGDATABASE: "postgres"; OID: "term_0_match_1"; # assigne un OID # Encore une fois la sélection est importante. Nous incluons l'OID # au début du champ pour le cas où nous souhaitons écrire # un hyperlien pour effacer cet enregistrement. PGQUERY: "select oid,ct,titulo,texto,mt,dt,autor" " from avisos" " where (dt is NULL or dt > 'now') and oid=OID"; # Le modèle est différent maintenant M4FILE: "/usr/local/etc/httpd/plantillas_m4/avisos_oid.m4"; WEBMASTER: "term_1_match_0"; #TESTMODE: "TRUE"; } |
define(<<<for>>>, <<<dnl
ifelse(eval((<<<$2>>>) <= (<<<$3>>>)), 1, <<<define(<<<$1>>>,<<<$2>>>)$4<<<>>>dnl for(<<<$1>>>,eval(<<<$2>>>+1),<<<$3>>>, <<<$4>>>)dnl >>>)dnl >>>)dnl divert(0)dnl Mime-Version: 1.0 Content-type: text/html <HTML>
<!-- la tabla est\xe1 vac\xeda
-->
>>>,<<<dnl /* PGRES_NTUPLES != 0 )( */
for(<<<i>>>,0,eval(PGRES_NTUPLES-1),<<<dnl
</table>
>>>)dnl /* PGRES_NTUPLES */ >>>,<<<dnl /* ifelse PGRES_RESULTSTATUS )(*/ Error en el resultado: <B>PGRES_RESULTSTATUS</b><BR>
>>>)dnl <CENTER><HR WIDTH=100></center>
|
divert(-1)
$Id: generic_list.m4,v 1.1 1998/07/06 17:13:33 luis Exp $ define(<<<cell>>>, <<<PGRES_CELL_$1_$2>>>) define(<<<field>>>, <<<PGRES_FNAME_$1>>>) define(<<<for>>>, <<<dnl ifelse(eval((<<<$2>>>) <= (<<<$3>>>)), 1, <<<define(<<<$1>>>,<<<$2>>>)$4<<<>>>dnl for(<<<$1>>>,eval(<<<$2>>>+1),<<<$3>>>, <<<$4>>>)dnl >>>)dnl >>>)dnl divert(0)dnl Mime-Version: 1.0 Content-type: text/html <HTML>
ifelse(PGRES_RESULTSTATUS, <<<PGRES_TUPLES_OK>>>,<<<dnl
<!-- la tabla est\xe1 vac\xeda
-->
>>>,<<<dnl /* PGRES_NTUPLES != 0 )( */
>>>)dnl /* PGRES_NTUPLES */ >>>,<<<dnl /* ifelse PGRES_RESULTSTATUS )(*/ Error en el resultado: <B>PGRES_RESULTSTATUS</b><BR>
>>>)dnl <CENTER><HR WIDTH=100></center>
|
Le résultat peut-être vu à ces adresses:
http://slug.ctv.es/cgi-bin/pg2cgi/avisos/
ou
http://slug.ctv.es/cgi-bin/pg2cgi/avisos/20384
Traduit, de l'anglais, par Éric Santonacci, texte original en espagnol
© Luis Colorado
1998
LinuxFocus 1999 Contacter le Webmestre. |