Подтвердить что ты не робот

Что такое безопасный разделитель регулярных выражений PCRE для использования атрибута элемента ввода шаблона HTML5?

Похоже, что спецификация HTML5 (и, следовательно, ECMA262) позволяет <input type="text" pattern="[0-9]/[0-9]" /> соответствовать строке "0/0" даже хотя прямая косая черта не ускользает. Веб-приложения, такие как Drupal, хотели бы обеспечить проверку на стороне сервера для браузеров, которые не поддерживают HTML5, с чем-то вроде:

<?php
preg_match('/^(' . $pattern . ')$/', $value);
?>

К сожалению, строка '[0-9]/[0-9]' не является допустимым регулярным выражением PRCE. Похоже, что большинство, если не все браузер, поддерживающий HTML5, поддерживают как pattern="[0-9]/[0-9]" , так и pattern="[0-9]\/[0-9]", который задает вопрос - что мы можем использовать в качестве разделителя для запуска этого шаблона с регулярным выражением в стиле Perl?

Мы подали отчет об ошибке против спецификации W3C, но являются ли здесь браузеры неправильными? Нужно ли уточнять спецификацию HTML5? Есть ли способ обхода, который мы можем использовать в PHP?

4b9b3361

Ответ 1

Это действительное регулярное выражение, если вместо / для разделителя используйте #. Пример:

preg_match('#^('.$pattern.')$#', $value);

Ответ 2

Я рекомендую использовать "\xFF" byte как разделитель шаблонов, потому что он не разрешен в строке UTF-8, поэтому мы можем быть уверены, что это не произойдет в шаблоне. И поскольку preg_match не понимает UTF-8, это не вызовет никаких проблем.

Пример: preg_match("\xFF$pattern\$\xFFADmsu", $subject);

Обратите внимание на модификаторы ADmsu и добавьте $. Модификатор u требует действительных байтов UTF-8 только в шаблоне, но не в разделителях вокруг.

Ответ 3

Одна из проблем с PCRE заключается в том, что почти любой разделитель является легальным для маркеров начала и конца, в зависимости от того, что облегчает остальную реализацию. Итак, # foo # является законным,/foo/является законным,! Foo! является законным (я думаю) и т.д. Неопределенное регулярное выражение, я бы сказал, чрезвычайно опасно именно по этой причине. Это звучит как ошибка спецификации HTML5, которая не указана.

Может быть, в PHP, сканировать строку и выбрать разделитель из белого списка, которого нет в строке? (Например, если нет/использовать, если используется #, если там используются% и т.д.)

Ответ 4

Я думаю, что chr(0) будет работать нормально. Изменить: нет. Но chr(1) работает.

Ответ 5

Учитывая, что PHP-приложение (Drupal в этом случае) генерирует поле ввода, кажется, что обходным путем было бы сделать что-то по строкам:

$pattern = '[0-9]/[0-9]';
...
$cleanPattern = preg_replace('/\//', '\\/', $pattern);
preg_match('/' . $cleanPattern . '/', $subject, $matches);

Я не мог придумать случай, когда это не сработает, причем / используется как литерал в выражении.

Спецификация HTML5 отменяет ECMA262 для спецификации юридического шаблона:

Если указано, значение атрибута должно соответствовать произведению шаблона JavaScript. [ECMA262]

Поскольку существует BNF, определенный в ECMA262, полный парсер (вместо использования PCRE) кажется самым безопасным подходом.