PHP filter_var URL

Для проверки пути URL из пользовательского ввода, я использую функцию PHP filter_var.
Вход содержит только путь (/path/path/script.php).

При проверке пути я добавляю хост. Я немного поиграюсь, проверяю правильность ввода и т. Д. При этом я замечаю странное (??) поведение функции фильтра URL.

Код:

$url = "http://www.domain.nl/http://www.google.nl/modules/authorize/test/normal.php";
var_dump(filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)); //valid

Может кто-нибудь объяснить, почему это действительный URL? Спасибо!

2

Решение

Краткий ответ: PHP FILTER_VALIDATE_URL проверяет URL только по RFC 2396, и ваш URL, хотя и странный, действителен в соответствии с указанным стандартом.

Длинный ответ:

Используемый вами фильтр объявлен совместимым с RFC, поэтому давайте проверим этот стандарт (RFC 2396).

Регулярное выражение, используемое для анализа URL-адреса и перечисленное там:

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
12            3  4          5       6  7        8 9

Куда:

scheme    = $2
authority = $4
path      = $5
query     = $7
fragment  = $9

Как мы видим, символ «:» зарезервирован только в контексте схемы, и с этого момента «:» является честной игрой (это подтверждается текстом стандарта). Например, он свободно используется в схеме http: для обозначения порта. Косая черта также может появиться в любом месте, и ничто не запрещает URL иметь «//» где-то посередине. Так что «http: //» в середине должно быть допустимым.

Давайте посмотрим на ваш URL и попробуем сопоставить его с этим регулярным выражением:

$url = "http://www.domain.nl/http://www.google.nl/modules/authorize/test/normal.php";
//Escaped a couple slashes to make things work, still the same regexp
$result_rfc = preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/',$url);
echo '<p>'.$result_rfc.'</p>';

Тест возвращает «1», поэтому этот URL-адрес действителен. Этого и следовало ожидать, так как правила не объявляют недействительными, как мы видели, URL-адреса, имеющие в середине что-то вроде http: //. PHP просто отражает это поведение с помощью FILTER_VALIDATE_URL.

Если вы хотите более строгий тест, вам нужно будет написать необходимый код самостоятельно. Например, вы можете предотвратить появление «: //» более одного раза:

$url = "http://www.domain.nl/http://www.google.nl/modules/authorize/test/normal.php";
$result_rfc = preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/',$url);
if (substr_count($url,'://') != 1) {
$result_non_rfc = false;
} else {
$result_non_rfc = $result_rfc;
}

Вы также можете попробовать настроить само регулярное выражение.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]