Экранирование DOI-ссылок в php - когда esc_url() недостаточно
Я пишу PHP-код, который генерирует HTML, который содержит ссылки на документы через их DOI. Ссылки должны указывать на https://doi.org/
сопровождаемый DOI документа.
Поскольку результаты являются URL, я подумал, что я мог бы просто использовать PHP esc_url()
функционировать как в
echo '<a href="' . esc_url('https://doi.org/' . $doi)) . '">' . esc_url('https://doi.org/' . $doi)) . '</a>';
поскольку это то, что предполагается использовать в текстовых узлах, узлах атрибутов или где-либо еще. К сожалению, все не так просто...
Проблема в том, что DOI могут содержать всевозможные специальные символы, которые, по-видимому, неправильно обрабатываются esc_url()
, Хороший пример такого DOI
10.1002/(SICI)1521-3978(199806)46:4/5<493::AID-PROP493>3.0.CO;2-P
который должен ссылаться на
https://doi.org/10.1002/(SICI)1521-3978(199806)46:4/5%3C493::AID-PROP493%3E3.0.CO;2-P
С $doi
равный этому DOI, приведенный выше код, однако, создает ссылку, которая отображается и ссылки на https://doi.org/10.1002/(SICI)1521-3978(199806)46:4/5493::AID-PROP4933.0.CO;2-P
,
Это приводит меня к вопросу: если esc_url()
Разумеется, это не единственное решение, которое не подходит для всех, чтобы избежать выхода из URL, тогда что я должен использовать? В этом случае я могу получить желаемый результат с
esc_url(htmlspecialchars('https://doi.org/' . $doi))
но так ли это правильно ™? Есть ли у этого другие нежелательные побочные эффекты? Если нет, то почему esc_url()
также не убежать <
а также >
? Было бы esc_html()
быть лучше чем htmlspecialchars()
? Если это так, я должен вложить его в esc_url()
?
Я знаю, что есть много статей по экранированию URL-адресов в php на stackru, но я не смог найти ту, которая посвящена вопросам <
а также >
приметы.
1 ответ
Я не эксперт по PHP, но я знаю, что DOI и SICI могут сильно раздражать.
URL-кодирование и HTML-кодирование - это разные вещи, поэтому имеет смысл подумать о них отдельно. Вы должны избежать угловых скобок, чтобы создать правильный HTML. Что касается экранирования URL, вы должны сделать это, потому что есть другие символы, которые могут сломать URL (такие как #
персонаж, который также всплывает время от времени).
Поэтому я бы порекомендовал:
'https://doi.org/' . htmlspecialcharacters(urlencode($doi))
Который даст вам:
<a href="https://doi.org/10.1002%2F%28SICI%291521-3978%28199806%2946%3A4%2F5%3C493%3A%3AAID-PROP493%3E3.0.CO%3B2-P">Click here</a>
Обратите внимание на порядок применения функции и тот факт, что вы не хотите кодировать https://doi.org
распознаватель!
К приведенному выше комментарию о "решающем решении"... это, конечно, неудобно. Но SICI были до DOI, и это одна из тех неприятных вещей, с которыми нам приходилось жить с тех пор!