Travaux Dirigés de aci
2. Analyse de formulaires avec SAX

Cette séance est consacrée à l’analyse d’un formulaire Web pour fabrication d’une requête HTTP. Le programme C à écrire recevra sur son flux d’entrée un texte HTML supposé contenir un ou plusieurs formulaires. Il admet un argument optionnel n, par défaut égal à 1, indiquant le numéro de formulaire (donc la n-ième balise FORM) du texte pour lequel il doit construire la requête, en répertoriant toutes les balises de saisies rencontrées dans la portée de la balise FORM concernée.

Voici un résumé des spécifications complètes du W3C à ce sujet. Les seules balises à considérer sont FORM, OPTION, BUTTON, INPUT, SELECT et TEXTAREA. Seules les quatre dernières fournissent un paramètre à inclure dans la requête, sous réserve qu’elles possèdent un attribut name. Dans quelques cas décrits ci-dessous, il faut de plus que l’attribut SELECTED soit présent. Il n’est pas exigé que les attributs name soient tous différents (c’est utile pour les sélections multiples). La balise BUTTON, graphiquement plus souple que la balise INPUT, n’en est qu’un un sous-ensemble pour ce qui est de la construction de la requête. La balise INPUT comporte un attribut TYPE pouvant prendre 10 valeurs : BUTTON, CHECKBOX, FILE, HIDDEN, IMAGE, PASSWORD, RADIO, SUBMIT, TEXTE et RESET. Cette dernière valeur, qui s’adresse au navigateur, est à ignorer ici. Les autres, hormis FILE, sont quasiment identiques quant à la requête.

Les documents analysés seront supposés n’avoir aucune balise form imbriquée dans une autre, et toutes les balises sont supposées en minuscules. Plus généralement, on suppose les documents conformes au XHTML1.1, on fera donc appel à un Simple Analyser for XML.


sendform.c
peroraison.c
peroraison.h
Makefile


1 Utilisation de SAX

SAX est un modèle d’analyse en une seule passe, dirigée par les événements : chaque fois que l’analyseur rencontre une entité grammaticale, il donne la main à une fonction spécifique préalablement associée à cette entité lors de la construction de l’analyseur. Bien qu’il ne s’agisse pas d’événements interactifs (comme on le verra dans X-WINDOW) sa programmation en est assez proche.

Il existe une version de SAX pour C nommé Expat dont il faut télécharger la distribution. Le fichier DOC/REFERENCE.HTML fournit toute les informations nécessaires à l’utilisation d’EXPAT. Afin d’en faire le tri voici quelques indications pour être rapidement opérationnel.

La fonction à appeler au départ est XML_PARSER_CREATE, avec "ISO-8859-1" comme argument (sinon tout caractère non ASCII sera considéré comme une erreur). Elle retourne une structure de type XML_PARSER (qu’il n’est pas nécessaire de détailler) qui sera fournie comme premier argument à toutes les autres fonctions, en particulier XML_PARSER_FREE pour libérer la place occupée lorsque l’analyseur n’est plus utile.

La fonction essentielle est XML_PARSE qui analye la chaîne donnée en deuxième argument et dont la longueur est donnée en troisième argument (le 0 final n’est donc pas utile) ; le quatrième argument est un booléen indiquant si cette chaîne est la fin du document (tout cela permet donc d’analyser un flux sans le recopier intégralement en mémoire). Si l’analyse se termine sur une erreur, XML_PARSE retourne la valeur XML_STATUS_ERROR.

Pour utiliser EXPAT a d’autres tâches qu’une simple vérification de conformité, il faut associer aux entités grammaticales de XML un preneur spécifique. Ce preneur est une fonction sans résultat passée en deuxième argument de fonctions d’initialisation, nommées XML_SET_Entité_HANDLER. Ainsi, initialiser un analyseur p en exécutant XML_SET_CHARACTER_DATA_HANDLER(p, f) conduira p à appeler la fonction f chaque fois qu’il rencontrera du texte entre deux balises. Le preneur f doit être une fonction de 3 arguments : le premier, de type VOID *, est sans importance pour le moment ; le deuxième, de type const XML_Char * (une extension de char * à tout format de caractère) est le texte rencontré ; le troisième est la longueur de celui-ci. Attention : le deuxième n’est pas une chaîne terminée par 0.

Afin de prendre en main cet outil, dans le programme OUTLINE.C, remplacer l’appel de XML_SET_ELEMENT_HANDLER par un appel de XML_SET_CHARACTER_DATA_HANDLER sur une fonction à définir, de sorte que le programme obtenu écrive dans le flux de sortie une copie du flux d’entrée expurgé de toutes ses balises.

Compléter le Makefile fourni pour qu’il prenne en compte la bibliothèque EXPAT.


Obtenir un formulaire de soumission de comptes rendus

2 La balise form

Le canevas fourni adapte à Expat la technique du tableau de fonctions utilisé pour le serveur POP. Ecrire la fonction HTTPFORM repérant si la balise est celle cherchée, et si oui mémorisant dans son premier argument ses 3 attributs importants : ACTION, METHOD et ENCTYPE, en utilisant la fonction FIND_ATRIBUTE. Si l’attribut method est vide, mettre dans la structure la valeur par défaut ; GET. Chercher dans l’attribut action s’il apparaît un deux-points ainsi que deux / consécutifs, et éclater cette valeur d’attribut sur les trois champs action (qui peut être http, javascript, mailto), host et script.


Obtenir un formulaire de soumission de comptes rendus

3 Les balises input et button

Le canevas définit les fonctions invoquées lors de la rencontre d’une balise INPUT et d’une balise BUTTON. Ces deux fonctions en invoquent une troisième, HttpInput_and_Button, en lui donnant la valeur du champ TYPE qui est implicitement égal à BUTTON (pour la balise BUTTON) et à TEXT (pour la balise INPUT). Sur le modèle du tableau de fonctions utilisé pour les balises, définir un tableau de fonctions pour les types de la balise INPUT et s’en servir pour définir la fonction HttpInput_and_Button. En utilisant la fonction ADD_TO_REQUEST_URI, définir ensuite les 8 fonctions traitant les 8 types mentionnés ci-dessus. Pour les types CHECKBOX et RADIO, le paramètre ne doit être inclus que si l’attribut CHECKED est présent.


Obtenir un formulaire de soumission de comptes rendus

4 La balise textarea

La difficulté réside dans la séparation entre le nom du paramètre, attribut de la balise TEXTAREA, et sa valeur qui est le texte qui suit la balise. Il faut donc mémoriser dans la structure transmise au preneur si un nom est en attente de sa valeur, et retirer cette indication lorsqu’on rencontrera la balise fermante (ce que fait le preneur ENDELEMENT qui vous est fourni.

Définir le preneur HTTPTEXTAREA mémorisant le nom du paramètre à transmettre. Définir ensuite le preneur HANDLERCHARACTERDATA qui, si un nom est en attente de sa valeur, rajoutant à la requête le texte ici présent, toujours en utilisant la fonction ADD_TO_REQUEST_URI.


Obtenir un formulaire de soumission de comptes rendus

5 Les balises select et option

La balise SELECT contient l’attribut NAME, mais ce sont les balises OPTIONS emboîtées à l’intérieur de cette balise qui possèdent un attribut VALUE. Si une balise OPTION n’a pas d’attribut VALUE, sa valeur sera le texte compris entre cette balise OPTION et sa balise fermante. Cette valeur, et le nom spécifié par la balise SELECT, ne seront envoyés que si l’attribut SELECTED est présent dans la balise OPTION. Plusieurs balises OPTION peuvent avoir été choisies (si l’attribut MULTIPLE est présent dans la balise SELECT, mais cette indication ne concerne pas l’envoi de requête). Ecrire les fonctions HTTPOPTION et HTTPSELECT réalisant ces spécifications.


Obtenir un formulaire de soumission de comptes rendus

6 Construction de la requête

Définir la fonction CONSTRUIRE_REQUETE, appelée à la fin de la fonction MAIN, envoyant sur le flux de sortie la requete demandée.


Obtenir un formulaire de soumission de comptes rendus

logo-spip E. Saint-James & F. Kordon - Master Informatique - UPMC Valid XHTML 1.0!
Calculé le 21 janvier 2021 à 18h47min