Экранирование 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, и это одна из тех неприятных вещей, с которыми нам приходилось жить с тех пор!

Другие вопросы по тегам