W3docs

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): bool

Parametri

ParametroDescrizione
$parserLa risorsa del parser XML creata con xml_parser_create(). Il gestore viene associato a questo specifico parser.
$handlerIl 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'URI SYSTEM "...") dell'entità esterna.
  • $public_id — l'identificatore pubblico, o null se 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.xml

Poiché 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_id per recuperare URI arbitrari o percorsi locali da input non attendibili. Per l'analisi con requisiti di sicurezza, preferisci librerie moderne come DOMDocument o XMLReader con 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 Closure o un array [$object, 'method']. L'estensione SAX Expat legacy nel suo insieme è in modalità di manutenzione — il nuovo codice dovrebbe preferire XMLReader o DOMDocument.

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().

Pratica

Pratica
Quale funzione in PHP viene utilizzata per creare un riferimento a entità esterne per i file XML?
Quale funzione in PHP viene utilizzata per creare un riferimento a entità esterne per i file XML?
Was this page helpful?