Tous les billets parus dans / PHP

php.ini : forcer des options spécifiques pour chaque site

Petit truc très utile si jamais vous disposiez d’un serveur mutualisé hébergeant plusieurs sites et que vous souhaitiez – par exemple – augmenter le POST_MAX_SIZE pour un de vos clients afin de lui permettre de téléverser des photos de haute qualité via l’admin de WordPress.

À la racine de votre dossier public, ajoutez un .htaccess contenant :

suPHP_ConfigPath /home/public_html/

et au même endroit, un fichier nommé php.ini contenant les configs à surpasser (override), par exemple:

upload_max_filesize=10M
post_max_size=10M
max_execution_time=200
max_input_time=200

MÀJ : Merci au collègue Éric qui me souligne au passage la nécessité d’avoir installé le module suPHP pour que cette astuce fonctionne.


Mise en cache de pages dynamiques

Voici un petit tutoriel pour expliquer comment – très simplement – mettre une page dynamique en cache pour en accélérer l’affichage et limiter les ressources côté serveur (apache et mysql).

Premièrement, suffit de créer deux fonctions. La première – debut_cache() – testera l’existence d’un fichier cache récent pour l’affichier, ou initialisera le buffer et débutera la mise en cache du contenu. La deuxième – fin_cache() – prend le contenu mis dans le buffer et va, suivant le besoin, écrire un fichier statique avec le contenu généré par le serveur qui sera alors repris par les requêtes suivants jusqu’à son expiration.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function debut_cache() 
{
	global $cachedFile;
	if(CACHE > 0) {
		if (!isset($_POST) || count($_POST) == 0) {
			$hash = md5(serialize($_GET) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
			$filename = basename($_SERVER['PHP_SELF'] . '.' . $_SERVER['HTTP_HOST'] . '.' . $hash . '.html');
			if (file_exists(CACHE_DIR . $filename) AND (time() - filemtime(CACHE_DIR. $filename)) < CACHE) {
				readfile(CACHE_DIR . $filename);
				exit();
			} else {
				$cachedFile = CACHE_DIR . $filename;
				ob_start();
			}
		} else $cachedFile = false;
	}
}
   
function fin_cache() 
{
	global $cachedFile;
	if((CACHE > 0) AND $cachedFile) {	
		$hoststr= getenv("HOSTNAME");
		$host = explode (".", $hoststr);
		$page = ob_get_contents();
		$page .= '<!-- Page mise en cache @ ' . date('Y-m-d H:i:s') . ' -->';
		ob_end_flush();	
		if ($file = fopen($cachedFile, 'w')) {
    			fwrite($file, $page);
    			fclose($file);
    		}		
	}
}

Juste avant de faire l’appel, il importe de définir deux variables (des constantes globales dans cet exemple).

1
2
3
4
5
//temps pour le cache (secondes)... 0 pour annuler la cache
define('CACHE', 60*15);  //15 min

//dossier de cache
define('CACHE_DIR', '/www/cache/');

Ensuite, on se lance :

1
2
3
4
5
6
7
8
9
10
//lancer la mise en cache
debut_cache();
 
//---------------------------------------------
//afficher normalement votre page ici
//elle sera mise dans le buffer
//---------------------------------------------

//afficher le contenu (du buffer ou du fichier mis en cache)
fin_cache();

Raccourcir une URL avec l’API de Bit.ly en PHP

Voici une petite fonction qui m’a été bien utile pour raccourcir une URL en utilisant l’API de Bit.ly et la classe SimpleXML (disponible dans PHP 5).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function shorten($url, $bitly_login, $bitly_apiKey)
{
	//bit.ly defaults
	$bitly_version 	= '2.0.1';
	$bitly_history	= 1;
	
	//url à interroger pour le retour via XML
	$connectURL = 'http://api.bit.ly/shorten?version='.$bitly_version.'&longUrl='.$url.'&login='.$bitly_login.'&apiKey='.$bitly_apiKey.'&history='.$bitly_history.'&format=xml&callback=?';
	
	//lire le contenu retourné par l'URL
	$content = file_get_contents($connectURL);
	if ($content !== false) {
		//créer l'object avec SimpleXML (PHP 5)
		$bitly = new SimpleXMLElement($content);
		//s'assurer qu'il n'y a pas d'erreur
		if($bitly->errorCode == 0)
			return $bitly->results[0]->nodeKeyVal->shortUrl;
	} 
	return false;
}

Suffit donc de l’appeler de cette manière :

1
2
3
4
5
6
7
//vos infos bit.ly
$bitly_login = 'username';
$bitly_apiKey = 'R_1234567898765432123456789';
//appel de la fonction
$shorten = shorten('http://estrade.ca', $bitly_login, $bitly_apiKey);
//retourner l'url raccourcie
echo $shorten;

Convertir des sauts de lignes en paragraphes

Un petit truc pratique lorsqu’on a à traiter une chaîne de texte dont les sections sont séparées par des sauts de ligne (n ou r) et qu’on désire séparer tout ça en paragraphes.

Assumons donc que nous avons un texte du genre :

1
2
$texte = "Ceci est un paragraphe nn En voici un 
	deuxième nn Et finalement un troisième.";

On s’attend donc à avoir trois paragraphes enrobés de la balise <P> plutôt qu’un seul bloc qui sera converti en de multiples <br />, probablement via la fonction nl2br(). Voici donc l’expression régulière à utiliser pour nettoyer votre texte :

1
2
$texte = preg_replace("/(rn)+|(n|r)+/", "</p><p>", $texte);
$texte = '<p>' . $texte . '</p>';

Notez que si, explicitement dans votre texte, les sauts de ligne sont déjà remplacés par un <BR />, vous n’avez qu’à utiliser cette expression régulière en lieu et place de la première :

1
2
3
//va convertir toutes les multiples instances de <br /> ou <br> ou <BR> 
$texte = preg_replace("/(<brs*/?[>]s*)+/i", "</p><p>", $texte );
$texte = '<p>' . $texte . '</p>';

Dans tous les cas, une fois que vous afficherez le texte en question, il ressemblera à ceci :
<P >
Ceci est un paragraphe
</P >
<P >
En voici un deuxième
</P >
<P >
Et finalement un troisième.
</P >


Protéger la fonction mail() des injections d’en-têtes

Vous avez développé un formulaire d’envoi par courriel utilisant la fonction mail()? Si oui, avez-vous pensé à vous protéger des injections d’en-têtes, lesquelles peuvent faire de votre beau petit script de 10 lignes un relai de spam considérable? Non? Qu’attendez-vous?

Comment les spammers s’y prennent?

Très simple! Il ne font qu’entrer un truc du genre dans un champ de votre formulaire :

1
email@domaine.com n CC: spam1@domaine.com, spam2@domaine.com...

Les en-têtes e-mail étant très sensibles, elles considèrent le saut de ligne (r) ou les nouvelles lignes (n) explicites comme le début d’une nouvelle directive (ici, l’insertion d’une liste d’adresses en copie-conforme). Voyez une multitude d’exploit ici.

Comment s’en protéger?

Encore une fois, rien de plus facile. Dans votre validation, vous n’avez qu’à y aller d’une petite expression régulière sur les champs soumis :

1
2
if ( eregi("(r|n)", $_GET['nom']) || eregi("(r|n)", $_GET['email']) )
	exit("Va-t'en, spammer!");

N’oubliez pas de traiter chacun des champs qui sont utilisés dans la construction des en-têtes (nom, courriel, format, charset, etc.) de votre message.


Script de partage pour médias sociaux

Je viens de créer un petit module pour Fanatique dont j’entends aussi faire bénéficier Matinternet et Showbizz dès que j’aurai quelques minutes. C’est rien de bien compliqué… seulement un bloc proposant les principaux réseaux (?) sociaux en français pour fins de sauvegarde et diffusion des articles consultés.

C’est rien de bien compliqué, mais c’est fort utile (et c’était sur ma to-do list depuis au moins deux éternités).

Et comme la notion de partage est au coeur des motivations ayant entraîné cet ajout, j’ai décidé de partager le code source du produit avec vous :)

Voici donc le package : partager.rar

Amusez-vous!