xml_set_external_entity_ref_handler()
La fonction xml_set_external_entity_ref_handler() enregistre un callback pour gérer les références d'entités externes dans un parseur XML PHP.
La fonction xml_set_external_entity_ref_handler() est une fonction PHP intégrée qui enregistre un callback défini par l'utilisateur pour gérer les références d'entités externes dans un parseur XML SAX (Expat) classique. Une entité externe est une référence dans un document XML — déclarée avec <!ENTITY name SYSTEM "uri"> — qui pointe vers un contenu stocké en dehors du document. Lorsque le parseur rencontre une telle référence pendant l'analyse, il invoque votre callback afin que vous puissiez décider quoi en faire : l'ignorer, charger des données approuvées depuis une base de données, ou la rejeter dans le cadre d'une validation de sécurité.
Cette page couvre la syntaxe de la fonction, les paramètres que PHP passe à votre callback, sa valeur de retour, un exemple complet et exécutable, ainsi que les mises en garde de sécurité et de dépréciation à connaître avant de l'utiliser.
Syntaxe
xml_set_external_entity_ref_handler(XMLParser $parser, callable $handler): boolParamètres
| Paramètre | Description |
|---|---|
$parser | La ressource de parseur XML créée avec xml_parser_create(). Le handler est attaché à ce parseur spécifique. |
$handler | Le callback à exécuter pour chaque référence d'entité externe. Il peut s'agir du nom d'une fonction (sous forme de chaîne), ou — lorsque xml_set_object() a été utilisé — d'un nom de méthode. Passer une chaîne vide supprime le handler. |
Valeur de retour
Retourne true en cas de succès, ou false en cas d'échec (par exemple, si $parser n'est pas un parseur valide).
La signature du callback
PHP appelle votre handler avec cinq arguments, dans cet ordre :
handler(XMLParser $parser, string $open_entity_names, string $base, string $system_id, ?string $public_id): int$open_entity_names— une liste séparée par des espaces des entités actuellement ouvertes, utilisée pour détecter la récursion.$base— l'URI de base pour résoudre$system_id(généralement une chaîne vide).$system_id— l'identifiant système (l'URISYSTEM "...") de l'entité externe.$public_id— l'identifiant public, ounullsi aucun n'a été déclaré.
Votre callback doit retourner une valeur non nulle (vraie) pour que l'analyse continue. Retourner 0, false ou rien interrompt l'analyse avec une erreur XML_ERROR_EXTERNAL_ENTITY_HANDLING.
Exemples d'utilisation
Voici un exemple pratique d'utilisation de xml_set_external_entity_ref_handler() en PHP.
Exemple : Définir une fonction de gestion des références d'entités externes
Supposons que vous ayez un document XML qui référence une entité externe et que vous souhaitiez inspecter cette référence lors de l'analyse du document. Vous créez un parseur avec xml_parser_create(), enregistrez le handler, analysez les données avec xml_parse() et libérez le parseur avec xml_parser_free() :
Définir une fonction de gestion des références d'entités externes en PHP
function handle_external_entity_ref($parser, $open_entity_names, $base, $system_id, $public_id) {
// Inspect — but do NOT blindly load — the external entity.
echo "External entity referenced: {$system_id}\n";
// Return a non-zero value so parsing continues.
return 1;
}
$xml_parser = xml_parser_create();
xml_set_external_entity_ref_handler($xml_parser, "handle_external_entity_ref");
$xml_data = '<?xml version="1.0"?>
<!DOCTYPE root [
<!ENTITY ext SYSTEM "data.xml">
]>
<root>&ext;</root>';
xml_parse($xml_parser, $xml_data, true);
xml_parser_free($xml_parser);Le handler se déclenche une fois pour la référence &ext; et affiche :
External entity referenced: data.xmlÉtant donné que le callback se contente d'afficher l'identifiant système et retourne 1, le parseur est invité à continuer sans récupérer réellement data.xml — ce qui est exactement le comportement sécurisé par défaut souhaité.
Pourquoi le handler peut ne jamais se déclencher
Dans la plupart des versions modernes de PHP, le chargement des entités externes est désactivé au niveau de libxml, de sorte que le parseur ignore silencieusement les références d'entités et votre callback n'est jamais appelé. Il s'agit d'un renforcement intentionnel. Si vous devez l'activer, vous le contrôlez globalement avec libxml_disable_entity_loader() — mais pour tout ce qui n'est pas une entrée fiable et contrôlée, vous devriez laisser le chargement désactivé.
⚠️ Avertissement de sécurité : La gestion des entités externes est un vecteur classique d'attaques XML External Entity (XXE), qui peuvent exposer des fichiers locaux (
file:///etc/passwd), déclencher des requêtes côté serveur, ou provoquer un déni de service. Ne résolvez jamais$system_idpour récupérer des URI arbitraires ou des chemins locaux provenant d'entrées non fiables. Pour une analyse sensible à la sécurité, préférez des bibliothèques modernes telles queDOMDocumentouXMLReaderavec le chargement des entités désactivé.
Note de dépréciation : Depuis PHP 8.4, passer une chaîne non-callable comme handler est déprécié — un nom de fonction simple qui existe réellement fonctionne encore, mais une chaîne non résolue génère désormais un avertissement de dépréciation. Pour un code compatible avec les futures versions, passez un callable réel tel qu'une
Closureou un tableau[$object, 'method']. L'extension SAX Expat classique est en mode maintenance — le nouveau code devrait privilégierXMLReaderouDOMDocument.
Conclusion
Dans cet article, nous avons couvert la fonction PHP xml_set_external_entity_ref_handler() : sa syntaxe, les cinq arguments que PHP passe à votre callback, pourquoi le callback doit retourner une valeur non nulle pour maintenir l'analyse en cours, et un exemple complet et exécutable. Nous avons également signalé les deux points qui posent problème — le handler ne se déclenche souvent jamais car le chargement des entités externes est désactivé par défaut, et le traitement d'entrées non fiables via cette fonction ouvre la porte aux attaques XXE. Utilisez-la uniquement avec des entrées fiables, préférez un callable réel à un nom de chaîne sur PHP 8.4+, et tournez-vous vers XMLReader ou DOMDocument pour tout ce qui est sensible à la sécurité.
Pour les handlers SAX associés, voir xml_set_element_handler() et xml_set_object().