The manual Page
English version
accueil | glossaire | downloads | liens ]
 

Le bouton "format imprimable"

Objectif du script

L'objectif de ce script PHP est d'avoir une manière ultra-simple d'afficher les pages web de PHP sans cadres, de manière à pouvoir les imprimer. En effet, les tableaux à largeur fixe s'impriment très mal.

Au niveau de la programmation des pages, on veut s'affranchir au maximum de 2 principales contraintes : ne pas avoir à écrire 2 fois les pages web (une avec les cadres et l'autre sans), pouvoir faire un include statique d'une portion de code HTML en bas des pages (comme pour footer.html) ; c'est le script appelé qui doit se débrouiller pour savoir quelle page transformer.

Il y a au moins deux méthodes pour réaliser ce script. L'une utilise une variable que Apache fournit à PHP : $HTTP_REFERER, et l'autre une variable d'environnement : $PHP_SELF. Le script utilisé sur ce site est le deuxième. Nous verrons plus loin pourquoi. Les deux solutions ne diffèrent que par une chose : la façon de trouver le nom du fichier à ouvrir et analyser pour lui donner le format imprimable.

Solution utilisant $HTTP_REFERER

Principe

Le principe est très simple : il suffit de remarquer que certains serveurs web fournissent des variables d'environnement aux scripts CGI, dont une qui contient l'URL de la page qui a appelé la page en cours. Cette variable, c'est $HTTP_REFERER.

Si vous cliquez sur l'icône en bas de cette page, votre navigateur, puis le serveur web va transmettre au script imprime.php un $HTTP_REFERER qui va valloir /www.themanualpage.org/php/sources/imprime.php. On va utiliser cette variable pour aller ouvrir le fichier appelant en lecture, parser ce fichier et ne garder que la portion intéressante.

Cette variable est très utile, mais elle présente hélas deux problèmes. Tout d'abord c'est le navigateur qui fait la requête sur le serveur web qui définit la valeur de cette variable, et il se trouve que beaucoup de navigateurs ne la précisent pas. Ensuite, cette variable est renvoyée par le serveur web Apache, mais pas forcément par d'autres serveurs web. La conséquence, c'est qu'un certain nombre de visiteurs ne pourront pas utiliser correctement le bouton "format imprimable", soit à cause de leur navigateur, soit à cause du serveur web lui-même. C'est pour cela que la deuxième solution présentée plus bas a été choisie sur ce site.

Implémentation

Il y a 2 choses à faire : écrire le script imprime.php, mais également faire en sorte que les pages appellent ce script. Cette dernière opération se fait tout simplement grâce à un lien HTML pointant directement sur le script :

<A href="/utils/imprime.php">format imprimable</A>

Ce code est à ajouter sur chaque page que l'on veut rendre imprimable.

Pour le script, la première chose à faire est de vérifier le contenu de la variable $HTTP_REFERER. On regarde d'abord si elle est non vide, et si le script PHP a été appelé par une page de TmP.

if (($HTTP_REFERER == "") || (! eregi("themanualpage.org",
                                      $HTTP_REFERER))) {
	echo "Oups ! Impossible d'ouvrir le fichier !";
	echo "Sorry! I cannot open this page.";
}

Si l'URL est satisfaisante, on parse cette URL pour récupérer le nom du document d'origine. Cela se fait avec la fonction parse_url :

$url = parse_url($HTTP_REFERER);

$url est un tableau associatif qui contient en particulier le champ path. Ce champ sera utilisé pour déterminer le fichier à ouvrir. Il se peut que la valeur de ce champ ne comporte par de nom de fichier .php ou .php3. Cela arrive lorsque l'on cherche à imprimer le fichier index.php(3) ; il faut donc rajouter le nom :

// Si extension .php3 manquante, on essaie index.php3
if (! eregi("\.php3", $url["path"])) {
	$nom = $url["path"]."index.php3";
} else {
	$nom = $url["path"];
}

Solution utilisant $PHP_SELF

Principe

Le principe reste finalement le même : on va utiliser une autre variable d'environnement : $PHP_SELF, sauf que cette variable correspond au nom du fichier du script en cour d'éxécution. Cela signifie que cette variable n'a la valeur qui nous intéresse que dans la page que l'on cherche à imprimer. Il va donc falloir passer cette valeur à imprime.php3. Comme nous allons le voir, cela va se faire par la méthode GET (le lien pointant vers imprime.php3 aura un format spécial).

La variable $PHP_SELF a l'avantage de toujours exister et correctement définie, car c'est l'interpréteur PHP lui-même qui la définit.

Implémentation

Il est possible de passer des variables par l'URL à un script quelconque. Par exemple, script.php3?var1=toto va permettre de transmettre la variable var1 à script.php3 affectée de la valeur "toto". Le code suivant sera donc ajouter en bas de chaque page que l'on veut rentre imprimable :

<A href="/utils/imprime.php?page=<? echo ereg_replace("\/www\.themanualpage\.org", "", $PHP_SELF); ?>" target="_blank">format imprimable</A>

imprime.php va donc récupérer une variable $page qui va contenir l'URL absolue de la page à imprimer. Par exemple : /php/sources/imprime.php.

Au niveau de l'implémentation dans imprime.php, on va d'abord s'assurer que l'on veut bien imprimer une page, i.e. que $page existe bien :

if ($page == "") {
	echo "Oups ! Impossible d'ouvrir le fichier !";
	echo "Sorry! I cannot open this page.";
}

Tout comme pour la version avec $HTTP_REFERER, il se peut qu'aucun nom de fichier .php3 ne soit préciser dans la variable $nom. Dans ce cas, il faut ajouter index.php3. De même pour index.php :

// Si extension .php3 manquante, on essaie index.php3
if (! eregi("\.php3", $page)) {
	$nom = $page."index.php3";
} else {
	$nom = $page;
}

Maintenant, dans ces conditions, $nom est équivalent au $nom de la version avec $HTTP_REFERER. Le reste du script est donc absolument identique.

Fin du script

De la variable $nom, on déduit facilement le chemin absolu (ATTENTION ! sur le serveur) du document d'origine :

$fichier = fopen($REDIRECT_HOMEDIR.$nom, "r");

Il ne reste plus qu'à parcourir le fichier ligne par ligne et à repérer les lignes où on fait un include seul (ces lignes vont être supprimées). Attention également aux images, car leur chemin (relatif) doit être changé en chemin absolu :

while (! feof($fichier)) {
	$ligne = fgets($fichier, 4096);
	// On traite le cas particulier des liens relatifs dans les
	// images : il faut en faire des liens absolus
	//
	// Particular case: relative pathes of images must be changed
	// into absolute pathes
	if (eregi("<IMG ", $ligne)) {
		if (! eregi(" src=\"/", $ligne) &&
		    ! eregi("src=\"http://", $ligne)) {
			$ligne = eregi_replace(" src=\"(.*)\"",
			         " src=\"".dirname($nom)."/\\1\"",
			         $ligne);
		}
	}
	if (! eregi("<\? include\(.*\)\; \?", $ligne)) {
		echo $ligne;
		if (eregi("</HEAD>", $ligne)) {
			echo "<BODY bgcolor=\"#ffffff\">\n";
			echo "<H1>".$metatags["title"]."</H1>\n";
		}
	}
}

Tout à la fin du script, on rajoute le pied de page. Comme le site est à la fois en français et en anglais, le pied de page change en fonction de la langue. Pour cela, on regarde le nom du fichier traité et on cherche un éventuel "uk_" :

if (ereg("uk_", $HTTP_REFERER)) {
	message en anglais
} else {
	message en français
}

Fonctions utiles

nom description
$HTTP_REFERER URL de la page appelante
$PHP_SELF URL absolue du script en cours d'exécution
parse_url renvoie dans un tableau les différentes parties d'une URL (serveur, ressource...)
fopen ouvre un fichier (chemin absolu sur le disque dur)
feof dit si on est arrivé à la fin du fichier (end of file)
fgets lit un certain nombre de caractères dans un fichier
fclose ferme un fichier ouvert avec fopen
dirname chemin complet menant au fichier spécifié
ereg et eregi fonction permettant de savoir si une chaîne de caractères contient une autre chaîne de caractères (la deuxième fonction ne fait pas la différence entre minuscules et majuscules)

Télécharger le code utilisant $HTTP_REFERER

Télécharger le code utilisant $PHP_SELF


format imprimable format imprimable



Copyright © 2000-2006 themanualpage.org - Ce site est soumis aux conditions décrites dans les licences GNU GPL et FDL.