Enlever la balise meta « generator » sur votre site WordPress

Je sais qu’il y a quelque temps, j’avais fait un article sur comment rajouter une balise meta « generator » à un site MODX, mais cette balise peut remettre en question la sécurité de votre site.

Une faille de sécurité ?

Connaître le CMS derrière un site peut faciliter la vie à toute personne voulant vous nuire. En effet, beaucoup de CMS étant open-source et ayant une communauté très active, si jamais une faille est découverte dans un système, la nouvelle circule vite. De plus, les failles peuvent varier d’une version à une autre du même CMS.

Juste en examinant le code source des pages d’un site et en analysant la structure des dossiers pour les différents fichiers de style et de script, on peut deviner le CMS derrière. Mais révéler la version précise de ce CMS reviens à dire là et comment vous frapper pour vous faire le plus mal possible.

Continuer la lecture

Automatisation des opérations en base suite au déplacement des fichiers de médias

Dans mon dernier article, je présentais la manière dont j’ai procédé pour déplacer les fichiers de ma bibliothèque de médias WordPress.

Toutes les différentes opérations des étapes décrites dans cet article étaient faites à la main, ce qui peut être long, et une faute de frappe ou un oubli peut être source d’erreurs.

Mais n’ayez pas peur, j’ai créé un script PHP permettant d’automatiser les étapes concernant les actions en base de données.

Je vais vous présenter ici la manière de procéder en PHP pour l’automatisation des modifications des deux tables à modifier :

  • la table contenant les meta données : wp_postmeta
  • la table contenant les articles et pages : wp_posts

Quelle que soit la table à modifier, on va procéder de la même manière : on lit chaque ligne de la table devant être modifiée, et pour chaque ligne on modifie la valeur à l’aide de preg_replace() avant de la mettre à jour.

Le même pattern/masque d’expression régulière et la même chaîne de remplacement sont utilisés pour tout appel à preg_replace().

Table wp_postmeta

Pour cette table, selon la meta donnée traitée il faut procéder de manière différente :

  • dans le cas de la clé « _wp_attached_file », on se contente d’un appel simple : preg_replace('@<pattern>@', '<chaîne de remplacement>', '<valeur de la clé>') avant de faire la mise à jour
  • dans le cas de la clé « _wp_attachment_metadata », il faut préalablement désérialiser l’array (avec unserialize()) avant de faire appel à preg_replace(), et il faut bien penser à à nouveau sérialiser le tableau (avec serialize()) avant la mise à jour.

Table wp_posts

Pour cette table, seul un appel à preg_replace() est nécessaire, mais avec une légère différence : il faut préfixer le masque de recherche et la chaîne de remplacement avec « uploads/ », car les liens vers les pages de votre site WordPress peuvent également contenir le pattern recherché (« <année>/<mois> » surtout).

L’appel à preg_replace() devient donc : preg_replace('@uploads/<pattern>@', 'uploads/<chaîne de remplacement>', '<valeur de la clé>').

Bonus

Voici un petit script, à placer à la racine de votre installation WordPress :

<?php

$search_pattern = '[0-9]{4}/[0-9]{2}/';

$replace = '';

/***********************************
 *
 *	/!\ NE PAS MODIFIER AU-DELA /!\
 *
 ***********************************/

include_once('./wp-config.php'); // pour récupérer la configuration de BDD de l'installation WordPress

$dsn = sprintf('mysql:host=%s;dbname=%s;charset=%s', DB_HOST, DB_NAME, DB_CHARSET);

$db = new PDO($dsn, DB_USER, DB_PASSWORD);

// Modification des posts
$read_posts = $db->query('SELECT ID, post_content FROM '.$table_prefix.'posts WHERE post_type IN ("post", "page")');

$write_post = $db->prepare('UPDATE '.$table_prefix.'posts SET post_content=:post_content WHERE ID=:post_id');

while ($post = $read_posts->fetch(PDO::FETCH_ASSOC)) {
	// Pour ne réécrire que les appels aux médias et pas les liens (qui peuvent aussi contenir une structure AAAA/MM)
	if ( !preg_match('@uploads/'.$search_pattern.'@', $post['post_content']) ) {
		continue;
	}

	$write_post->bindParam(':post_content', preg_replace('@uploads/'.$search_pattern.'@', 'uploads/'.$replace, $post['post_content']), PDO::PARAM_STR);
	$write_post->bindParam(':post_id', $post['ID'], PDO::PARAM_INT);
	$write_post->execute();
}

$read_posts->closeCursor();

// Modification des meta données
$read_metas = $db->query('SELECT meta_id, meta_key, meta_value FROM '.$table_prefix.'postmeta WHERE meta_key IN ("_wp_attached_file", "_wp_attachment_metadata")');

$write_meta = $db->prepare('UPDATE '.$table_prefix.'postmeta SET meta_value=:meta_value WHERE meta_id=:meta_id');

while ($meta = $read_metas->fetch(PDO::FETCH_ASSOC)) {
	if($meta['meta_key'] == '_wp_attached_file') {
		$meta_value = preg_replace('@'.$search_pattern.'@', $replace, $meta['meta_value']);
	} else {
		$meta_array = unserialize($meta['meta_value']);

		$meta_array['file'] = preg_replace('@'.$search_pattern.'@', $replace, $meta_array['file']);

		$meta_value = serialize($meta_array);
	}

	$write_meta->bindParam(':meta_value', $meta_value, PDO::PARAM_STR);
	$write_meta->bindParam(':meta_id', $meta['meta_id'], PDO::PARAM_INT);
	$write_meta->execute();
}

$read_metas->closeCursor();

⚠ Attention, ce script n’a été testé que sur une version de test locale. Pensez bien à faire une sauvegarde de votre base avant de l’exécuter. ⚠

Déplacer les fichiers de la bibliothèque de médias de WordPress

Si pour une raison ou une autre vous voulez déplacer les fichiers médias dans les dossiers de votre site WordPress, je vais vous expliquer comment faire.

Dans mon cas, j’ai eu ce besoin quand j’ai voulu désactiver l’organisation en dossier annuels et mensuels par défaut, et déplacer tous mes médias à la racine du dossier des médias (wp-content/uploads).

Procédure en plusieurs étapes

Pour déplacer les fichiers médias de votre site WordPress, il faut procéder en plusieurs étapes :

  1. déplacer les fichiers
  2. modifications en base de données
  3. modification des articles et pages

1 – Déplacer les fichiers

Pour cette étape, rien de plus simple, il suffit d’utiliser votre client FTP pour déplacer vos fichiers.

2 – Modifications en base de données

Le déplacement des fichiers ne suffit pas, car le chemin vers le fichier est enregistré en base de données.

Mon premier réflexe a été d’aller voir en base le contenu de la table servant à stocker les informations concernant les médias : wp_posts. Et dans cette table, BINGO !, une colonne (« guid ») contient l’adresse complète vers mon fichier. Je m’empresse de modifier ce champ pour tous mes médias, et retourne sur la page de bibliothèque médias de mon blog, et là… rien…

En effet, ce champ « guid » n’est pas utilisé pour retrouver nos fichiers médias, mais utilisé dans la génération des flux (RSS ou autres) de votre site WordPress. Il est donc fortement déconseillé de changer cette colone, ce qui est trop tard pour moi (voir l’article sur le codex WordPress).

Le chemin vers le fichier d’un média est enregistré dans la table wp_postmeta. Dans cette table, chaque média a deux enregistrements qui lui correspondent : « _wp_attached_file » et « _wp_attachment_metadata » (ces noms correspondent à la valeur de la colonne « meta_key »).

La ligne « _wp_attached_file » est une simple chaîne de caractère qu’il est très facile de modifier.

Quant à la ligne « _wp_attachment_metadata », il s’agit d’un array sérialisé (pour en savoir plus sur la sérialisation, lisez cet article sur OpenClassrooms). Le chemin est contenu dans la 6e « section » (entre point-virgules) de chaque tableau sérialisé. Quand vous modifiez le chemin, pensez bien à également changer le nombre de caractères ([...];s:21:"2019/04/logo_bleu.jpg;[...]" de l’entrée sérialisée.

3 – Modifications des articles et pages

Il reste maintenant à modifier en HTML les pages et articles qui incluent des médias de notre bibliothèque.

Créer un thème enfant pour WordPress

Un thème enfant est un thème reprenant toutes les fonctionnalités d’un thème existant, qu’on appelera « thème parent ».

Pourquoi créer un thème enfant ?

Les thèmes WordPress disponibles offrent déjà un large choix d’options pour les personnaliser. Mais, par exemple, disons que vous voulez modifier la couleur d’un ou plusieurs éléments, ou encore, rajouter une web font.

Afin d’effectuer ces modifications, le premier réflexe est de modifier le fichier style.css du thème. Mais cette solution présente un problème, toute mise à jour du thème modifié écrasera nos ajustements… On pourrait se dire qu’il n’y a qu’à ne pas faire cette mise à jour. Mais là encore, c’est un soucis, car certains thèmes complexes peuvent présenter des failles de sécurité.

En utilisant un thème enfant, on est donc assuré de disposer de la dernière version de notre thème, tout en gardant nos propres modifications.

Continuer la lecture

Retour sur ma première carte interactive

Dans mon dernier article (voir), j’ai indiqué que la première solution de carte interactive que j’avais présentée dans une série de deux articles (1 et 2) ne fonctionnait pas sous Chrome.

Récemment, en consultant le code d’une page de reserves-naturelles.org, je me suis aperçu que la carte des régions de ce site fonctionnait sur le même principe que ma première solution et fonctionnait sous Chrome.

En comparant les deux codes je me suis aperçu de la différence : la map utilisée avait un attribut id au lieu d’un attribut name, ce qui fait que Chrome était incapable de la charger.

La démo originale a été corrigée, mais j’ai également fait une nouvelle version utilisant uniquement du JavaScript natif.

Le code HTML reste le même. Le code JavaScript est le suivant :

var areas = document.getElementsByTagName("area"); // array de toutes les areas
var target = document.getElementById("hovered"); // image dont on va changer la source

for (var i=0; i < areas.length; i++) { // pour chaque area de la page
	areas[i].addEventListener("mouseenter", function(evt) { // attachement à l'entrée de la souris
		// on récupère l'attribut "id" de l'élément déclencheur avec evt.target.getAttribute("id")
		target.src = "/assets/files/images/" + evt.target.getAttribute("id") + ".png"; // on change la source de l'image de couverture
	});
	areas[i].addEventListener("mouseleave", function(evt) { // attachement à la sortie de la souris
		target.src = "/assets/files/images/map.gif"; // on rétablit l'image transparente
	});
}

Comme quoi, même après plusieurs années on apprend toujours.

Remake de ma carte interactive avec OpenLayers

Il n’y a pas très longtemps, en faisant la maintenance de mon site (oui, même si le contenu n’évolue quasiment pas, le site n’est pas à l’abandon) je suis retombé sur la carte interactive que j’avais réalisées plusieurs années auparavant.

Cette carte reposait sur l’utilisation d’une image comme fond de carte, et d’une map HTML plus un script jQuery.

J’avais résumé le processus de création dans deux articles :

  1. Création de la carte et du mappage
  2. Ajout interactivité avec jQuery

L’inconvénient de cette solution est quelle ne fonctionne pas sur Chrome. Et Chrome étant le navigateur avec la plus grosse part de marché cela est problématique.

Dernièrement, lors de ma mission chez Orange, j’ai été amené à travailler sur une partie de cartographie. Pour des raisons de confidentialité, il avait été décidé de ne pas utiliser de solution commerciale (celle de big G dans ce cas), mais une solution open-source.

Le choix final c’est arrêté sur la librairie OpenLayers, avec un fond OpenStreetMap.

Or cette librairie (compatible avec tous les navigateurs modernes) permet l’utilisation d’une image statique comme fond de carte (voir cet exemple). C’est donc pourquoi j’ai décidé de refaire une carte interactive à l’aide de cette librairie.

Création de la carte

Préparatifs

Comme avec toute librairie, il faut d’abord l’intégrer à votre page (via un CDN ou en local), ainsi que sa feuille de style.

Ensuite, il faut créer dans le corps de la page une div qui sera utilisée par OpenLayers pour créer la carte. De plus, cette div doit être préalablement dimensionnée, si vous ne souhaitez pas qu’elle occupe toute la largeur disponible.

Le script de création de la carte, quant à lui, doit être placé à la fin du body de la page.

Bon, tout est près ? Il est temps de passer à la création de notre carte.

Continuer la lecture

Pour un web plus écolo

Après avoir lu divers articles et visionné plusieurs vidéos à ce sujet, j’ai moi aussi envie de m’exprimer sur l’impact environnemental du Web, et sur quelques astuces afin de diminuer cet impact.

Le web a un impact environnemental ?

À tous ceux se posant encore cette question, je répond oui. Le Web n’est rien d’autre qu’un ensemble d’ordinateurs reliés entre eux. Et un ordinateur a besoin d’énergie pour fonctionner et effectuer les tâches qui lui sont demandées. Or, le Web est en activité 24h/24 et 7j/7, et est très utilisé (sans parler de la consommation énergétique des systèmes de refroidissement des data-center).

Continuer la lecture

Le multi-site avec MODX

Grâce à son système de contextes, MODX Revolution permet la gestion de plusieurs sites à partir de la même installation du système. Nous allons voir dans cet article comment faire.

Le système de contextes

Ce système permet de clairement séparer les ressources dans leur arbres (voir image ci-dessous). La première section correspond aux ressources crées pour le site principal, alors que la/les suivante(s) correspond(ent) à/aux autre(s) site(s) rajouté(s) au système par la suite.

Arbre multi-contextes
Continuer la lecture

Un menu pour mobile avec MODX

Avec la généralisation des terminaux mobiles (smartphones et tablettes) il est important de prendre en compte la taille réduite de leur affichage lors de la conception de votre site. Un élément essentiel du design d’un site est le menu principal de navigation. Pour les terminaux mobiles, une des solutions est de remplacer le classique combo liste de liens non ordonnée (<ul>) + css par une liste déroulante (<select>) et du JavaScript.

Menu pour smartphone
Continuer la lecture

Ajouter une méta « generator » à MODX Revolution

J’ai longtemps cherché à rajouter la balise méta « generator » à mon MODX Revolution, et en fouillant la foisonnante doc de MODX j’ai enfin trouvé une solution.

Ma solution utilise un snippet (pour aller chercher le numéro de version), et un chunk (pour mettre le tout en HTML).

Le snippet

Le numéro de version est un paramètre du système (‘settings_version’ pour être plus précis). Pour afficher un paramètre système, il faut utiliser la méthode getOption de la classe modx. Cela donne donc:

return $modx->getOption('settings_version');

Le chunk

Le chunk consiste juste en une meta avec un attribut name égal à ‘generator’, et un attribut content égal au retour du snippet (que j’ai appelé ‘generator’). Cela nous donne:

<meta name="generator" content="MODX Revolution [[!generator]]" />

Utilisation du chunk

Pour utiliser le chunk, il suffit simplement de l’appeler dans le header du modèle ([[$generator]]).