Xml set external entity ref handler: примеры (PHP)
xml_set_external_entity_ref_handler(resource parser, callable handler): boolФункция xml_set_external_entity_ref_handler
Функция xml_set_external_entity_ref_handler() устанавливает обработчик для внешних ссылок на сущности в XML-парсере. Она используется при разборе XML-документов, содержащих объявления внешних сущностей, таких как внешние DTD или включения текста из других файлов.
- parser — обязательный аргумент, ссылка на XML-парсер, созданный функцией xml_parser_create().
- handler — обязательный аргумент, имя функции обратного вызова, которая будет вызвана при обнаружении внешней ссылки. Обработчик должен принимать пять параметров: парсер, открытое имя сущности, базовый идентификатор, системный идентификатор и публичный идентификатор.
Функция возвращает логическое значение: true при успешной установке обработчика, false в случае ошибки.
Примеры использования
<?php
$parser = xml_parser_create();
xml_set_external_entity_ref_handler($parser, "externalEntityHandler");
function externalEntityHandler($parser, $openEntityNames, $base, $systemId, $publicId) {
echo "Внешняя сущность: $systemId\n";
return true;
}
$xml = '<!DOCTYPE doc [<!ENTITY ext SYSTEM \"external.txt\">]>';
$xml .= '<doc>&ext;</doc>';
xml_parse($parser, $xml);
?>Внешняя сущность: external.txt
<?php
$parser = xml_parser_create();
xml_set_external_entity_ref_handler($parser, "ignoreExternalEntities");
function ignoreExternalEntities($parser, $openEntityNames, $base, $systemId, $publicId) {
return false;
}
$xml = '<!DOCTYPE doc [<!ENTITY ext SYSTEM \"http://example.com/file.xml\">]>';
$xml .= '<doc>&ext;</doc>';
if (!xml_parse($parser, $xml)) {
echo "Ошибка парсинга: " . xml_error_string(xml_get_error_code($parser));
}
?>Ошибка парсинга: External entity handling not set
Альтернативные функции в PHP
Для обработки XML в PHP существуют другие функции и расширения:
- xml_set_unparsed_entity_decl_handler() — устанавливает обработчик для неразбираемых объявлений сущностей. Отличается типом обрабатываемых сущностей.
- DOMDocument::loadXML() с настройкой LIBXML_NOENT — позволяет автоматически разрешать сущности, но требует осторожности из-за рисков безопасности.
- SimpleXML — не поддерживает установку пользовательских обработчиков для внешних сущностей, но проще в использовании для базовых задач.
Функцию xml_set_external_entity_ref_handler() предпочтительно использовать при необходимости тонкого контроля над обработкой внешних ресурсов, особенно в контексте безопасности.
Аналоги в других языках
Xml set external entity ref handler в Python
В модуле xml.sax можно установить обработчик через setEntityResolver.
import xml.sax
class MyResolver(xml.sax.handler.EntityResolver):
def resolveEntity(self, publicId, systemId):
print(f"Запрос сущности: {systemId}")
return None # Отказ от загрузки
parser = xml.sax.make_parser()
parser.setEntityResolver(MyResolver())
parser.parse("document.xml")В библиотеке sax-js можно использовать событие oncdata и отключать внешние сущности.
const sax = require('sax');
const parser = sax.parser(false, { xmlns: true });
parser.onopentag = function(node) { console.log(node.name); };
// Внешние сущности обычно отключены по умолчанию для безопасности.
parser.write('<doc>&ext;</doc>');Xml set external entity ref handler в MySQL
MySQL не имеет прямой аналогии, так как не является языком для разбора XML. Однако в SQL-запросах можно использовать функцию ExtractValue(), но она не обрабатывает внешние сущности.
Типичные ошибки
<?php
$parser = xml_parser_create();
xml_set_external_entity_ref_handler($parser, function($parser, $openEntityNames, $base, $systemId, $publicId) {
// Нет возвращаемого значения
});
// Парсинг может завершиться ошибкой
?>Предупреждение: обработчик должен возвращать логическое значение.
<?php
$parser = xml_parser_create();
xml_set_external_entity_ref_handler($parser, function($parser) {
// Только один аргумент вместо пяти
return true;
});
?>Функция обратного вызова будет вызвана с некорректными данными, что приведет к непредсказуемому поведению.
<?php
function unsafeHandler($parser, $openEntityNames, $base, $systemId, $publicId) {
// Чтение файла без проверки
$content = file_get_contents($systemId);
xml_parse($parser, $content);
return true;
}
?>Такой код уязвим для XXE-атак, если система обрабатывает непроверенные XML-документы.
Изменения в версиях PHP
В PHP 8.0 функция xml_set_external_entity_ref_handler() не претерпела значительных изменений. Однако, начиная с PHP 8.0, расширение XML по умолчанию входит в ядро и всегда доступно. Ранее в некоторых сборках его нужно было включать отдельно.
В PHP 8.1 и 8.2 не было зафиксировано изменений в поведении этой функции. Важно отметить, что современные практики безопасности рекомендуют отключать обработку внешних сущностей по умолчанию, что можно сделать через libxml_set_external_entity_loader(NULL) в контексте DOM и SimpleXML.
Расширенные примеры
<?php
$cache = [];
$parser = xml_parser_create();
xml_set_external_entity_ref_handler($parser, function($parser, $openEntityNames, $base, $systemId, $publicId) use (&$cache) {
if (isset($cache[$systemId])) {
xml_parse($parser, $cache[$systemId]);
return true;
}
if (filter_var($systemId, FILTER_VALIDATE_URL)) {
$content = file_get_contents($systemId);
$cache[$systemId] = $content;
xml_parse($parser, $content);
return true;
}
return false;
});
$xml = '<!DOCTYPE root [<!ENTITY inc SYSTEM \"https://example.com/data.xml\">]>';
$xml .= '<root>&inc;</root>';
xml_parse($parser, $xml);
?>Обработчик кеширует содержимое внешних сущностей, избегая повторных загрузок.
<?php
$parser = xml_parser_create();
xml_set_external_entity_ref_handler($parser, function($parser, $openEntityNames, $base, $systemId, $publicId) {
$allowedDomains = ['https://trusted.com/', 'file:///safe/path/'];
$allowed = false;
foreach ($allowedDomains as $domain) {
if (strpos($systemId, $domain) === 0) {
$allowed = true;
break;
}
}
if (!$allowed) {
return false;
}
$content = file_get_contents($systemId);
xml_parse($parser, $content);
return true;
});
?>Обработчик разрешает загрузку только из доверенных источников, что повышает безопасность.
<?php
$parser = xml_parser_create();
$log = [];
xml_set_external_entity_ref_handler($parser, function($parser, $openEntityNames, $base, $systemId, $publicId) use (&$log) {
$log[] = [
'timestamp' => time(),
'entity' => $openEntityNames,
'system' => $systemId,
'public' => $publicId
];
// Отказ от загрузки, только логирование
return false;
});
$xml = '<!DOCTYPE test [<!ENTITY secret SYSTEM \"file:///etc/passwd\">]><test/>';
xml_parse($parser, $xml);
print_r($log);
?>Пример фиксирует попытки обращения к внешним сущностям без их фактической загрузки.
PHP xml_set_external_entity_ref_handler function comments
- Php xml set external entity ref handler - аргументы и возвращаемое значение
- Функция php xml_set_external_entity_ref_handler - описание
- xml set external entity ref handler - примеры
- xml set external entity ref handler - похожие методы на php
- xml_set_external_entity_ref_handler на js, python, mysql
- xml set external entity ref handler изменения php
- Примеры xml_set_external_entity_ref_handler на php