xml_set_external_entity_ref_handler()
La funzione xml_set_external_entity_ref_handler() è una funzione built-in di PHP che registra un callback per gestire i riferimenti a entità esterne.
La funzione xml_set_external_entity_ref_handler() è una funzione built-in di PHP che registra un callback definito dall'utente per gestire i riferimenti a entità esterne in un parser XML SAX (Expat) legacy. Un'entità esterna è un riferimento all'interno di un documento XML — dichiarato con <!ENTITY name SYSTEM "uri"> — che punta a contenuti memorizzati al di fuori del documento. Quando il parser incontra un tale riferimento durante l'analisi, invoca il callback in modo che tu possa decidere cosa farne: ignorarlo, caricare dati approvati da un database, o rifiutarlo come parte della validazione della sicurezza.
Questa pagina copre la sintassi della funzione, i parametri che PHP passa al tuo callback, il valore restituito, un esempio completo eseguibile e le avvertenze sulla sicurezza e la deprecazione che è necessario conoscere prima di utilizzarla.
Sintassi
xml_set_external_entity_ref_handler(XMLParser $parser, callable $handler): boolParametri
| Parametro | Descrizione |
|---|---|
$parser | La risorsa del parser XML creata con xml_parser_create(). Il gestore viene associato a questo specifico parser. |
$handler | Il callback da eseguire per ogni riferimento a entità esterna. Può essere il nome di una funzione (come stringa), oppure — quando è stato usato xml_set_object() — il nome di un metodo. Passare una stringa vuota annulla il gestore. |
Valore restituito
Restituisce true in caso di successo, o false in caso di errore (ad esempio, se $parser non è un parser valido).
La firma del callback
PHP chiama il tuo gestore con cinque argomenti, in quest'ordine:
handler(XMLParser $parser, string $open_entity_names, string $base, string $system_id, ?string $public_id): int$open_entity_names— un elenco separato da spazi delle entità attualmente aperte, utilizzato per rilevare la ricorsione.$base— l'URI base per risolvere$system_id(di solito una stringa vuota).$system_id— l'identificatore di sistema (l'URISYSTEM "...") dell'entità esterna.$public_id— l'identificatore pubblico, onullse non è stato dichiarato.
Il tuo callback deve restituire un valore non zero (truthy) per continuare l'analisi. Restituire 0, false o nulla interrompe l'analisi con un errore XML_ERROR_EXTERNAL_ENTITY_HANDLING.
Esempi di utilizzo
Vediamo un esempio pratico di utilizzo di xml_set_external_entity_ref_handler() in PHP.
Esempio: Impostazione di una funzione gestore per riferimenti a entità esterne
Supponiamo di avere un documento XML che fa riferimento a un'entità esterna e di voler ispezionare quel riferimento durante l'analisi del documento. Si crea un parser con xml_parser_create(), si registra il gestore, si analizzano i dati con xml_parse() e si libera il parser con xml_parser_free():
Impostazione di una funzione gestore per riferimenti a entità esterne in 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);Il gestore viene attivato una volta per il riferimento &ext; e stampa:
External entity referenced: data.xmlPoiché il callback si limita a visualizzare l'identificatore di sistema e restituisce 1, al parser viene detto di continuare senza recuperare effettivamente data.xml — che è esattamente il comportamento sicuro predefinito desiderato.
Perché il gestore potrebbe non essere mai attivato
Nella maggior parte delle build moderne di PHP, il caricamento delle entità esterne è disabilitato a livello di libxml, quindi il parser ignora silenziosamente i riferimenti alle entità e il tuo callback non viene mai chiamato. Questo è un hardening intenzionale. Se è necessario optare per l'attivazione, puoi controllarla globalmente con libxml_disable_entity_loader() — ma per qualsiasi input non attendibile e non controllato dovresti lasciare il caricamento disabilitato.
⚠️ Avviso di sicurezza: La gestione delle entità esterne è un vettore classico per gli attacchi XML External Entity (XXE), che possono divulgare file locali (
file:///etc/passwd), attivare richieste lato server, o causare denial of service. Non risolvere mai$system_idper recuperare URI arbitrari o percorsi locali da input non attendibili. Per l'analisi con requisiti di sicurezza, preferisci librerie moderne comeDOMDocumentoXMLReadercon il caricamento delle entità disattivato.
Nota sulla deprecazione: A partire da PHP 8.4, passare una stringa non-callable come gestore è deprecato — un semplice nome di funzione che esiste realmente funziona ancora, ma una stringa non risolvibile genera ora un avviso di deprecazione. Per un codice compatibile con le versioni future, passa un callable reale come una
Closureo un array[$object, 'method']. L'estensione SAX Expat legacy nel suo insieme è in modalità di manutenzione — il nuovo codice dovrebbe preferireXMLReaderoDOMDocument.
Conclusione
In questo articolo abbiamo trattato la funzione xml_set_external_entity_ref_handler() di PHP: la sua sintassi, i cinque argomenti che PHP passa al tuo callback, il motivo per cui il callback deve restituire un valore non zero per mantenere attiva l'analisi, e un esempio completo eseguibile. Abbiamo anche evidenziato le due cose che creano difficoltà — il gestore spesso non viene mai attivato perché il caricamento delle entità esterne è disabilitato per impostazione predefinita, e instradare input non attendibili attraverso di esso apre la porta agli attacchi XXE. Usalo solo con input attendibili, preferisci un callable reale rispetto a un nome stringa su PHP 8.4+, e ricorri a XMLReader o DOMDocument per qualsiasi cosa sensibile alla sicurezza.
Per i gestori SAX correlati, vedi xml_set_element_handler() e xml_set_object().