ketmar@ljr справедливо заметил, что наши скрипты принимают только IP-адреса в формате xxx.xxx.xxx.xxx
, где xxx
— десятеричное число от 0 до 255, а IP может быть записан и в виде шестнадцатеричных, и в виде восьмеричных чисел, и даже смешано. Также IP-адрес может быть неполным. Например, адрес 4.0.0.1
можно записать как 4.1
В наших скриптах корректность IP проверялась регулярным выражением, т.к. все равно им же производился поиск IP в полях HTTP_*
, в которых IP может передаваться прокси-серверами.
Но валидацию IP можно провести и без использования регулярных выражений. Другое дело, поиск без него уже не произведешь, и это может создать определенные проблемы, если прокси-сервер, например, будет передавать IP в виде шестнадцатеричных чисел или преобразовывать, где возможно, полные адреса в неполные.
В PHP 5.2.0 появилась функция filter_var()
, которая позволяет проверять строки на соответствие разным форматам, не только IP, но и, например URL или e-mail.
Для проверки IP она вызывается так:
filter_var($ip,FILTER_VALIDATE_IP);
где:
$ip
— строка, содержащая IP-адрес
FILTER_VALIDATE_IP
— встроенный фильтр для IP-адреса
Функция возвращает TRUE
, если строка прошла проверку, и FALSE
если нет.
А не очень хорош способ тем, что валидацию проходят только IP, соответствующие формату «четыре десятеричных числа от 0 до 255, разделенных точкой», т.е. работает точно также, как и наша старая функция
Такое ощущение, что разработчики PHP пытаются избавить мир от зоопарка способов записи IP-адреса, и привести все, наконец, к единому знаменателю 🙂
Пример с использованием функции filter_var
ketmar@ljr предлагал использовать сишную функцию inet_addr()
, но где ж я ее возьму-то в PHP, подумал я, и зря подумал. 🙂 Функция ip2long($ip)
, которая использовалась для проверки попадания IP-адреса в определенный диапазон Копия ее аналог. Если переменная $ip
содержит корректный IP-адрес, то функция вернет целое число, если в IP-адресе ошибка, то функция вернет FALSE
или -1
.
Примечание: Функция ip2long()
возвратит FALSE для IP 255.255.255.255
в PHP 5 <= 5.0.2 и -1 в PHP 5 <=5.2.4 на 64-битных системах. Это было исправлено в PHP 5.2.5, теперь возвращается 4294967295. В 32-битных системах будет возвращено -1 из-за целочисленного переполнения.
Так что проверку на корректность IP можно делать в функции-обертке, добавив код-заглушку для IP 255.255.255.255
:
function IsIP($ip) { //преобразуем в нижний регистр, на случай шестнадцатиричных чисел $ip=strtoupper($ip); //ip2long в некоторых версиях php //некорректно реагирует на адрес 255.255.255.255 //делаем небольшую заглушку if ($ip == '255.255.255.255'||$ip == '0xff.0xff.0xff.0xff'|| $ip == '0377.0377.0377.0377') { return true; } $tolong=ip2long($ip); if ($tolong == -1||$tolong===FALSE) return FALSE; else return TRUE; }
В PHP есть функция long2ip()
, которая делает обратное преобразование, т.е. преобразует целое число в IP-адрес в привычном виде. Если их совместить, то можно преобразовывать неполные адреса в полные:
function fulladdr($ip) { //преобразует неполные адреса в полные //для информации $tolong=ip2long($ip); return long2ip ($tolong); }
Пример работы скрипта:
isip.php?ip=4.1
Внедрил последний метод в рабочие скрипты, залил на сервер, и оказалось, что метод не работает. Ну не то, чтобы не совсем не работает, а работает точно так же, как старая функция с регулярным выражением, т.е. возвращает TRUE
только если IP-адрес записан в виде четырех десятеричных чисел от 0 до 255, разделенных точкой. Неполные адреса, или адреса в других системах счисления IP-адресами не считаются. Функция ip2long()
возвращает FALSE
, если ей скормить такой адрес. Уж не знаю, и сходу не нагуглил, отчего такая оказия, то ли такое поведение зависит от настроек PHP, то ли от сервера. На локальном сервере работало, а на том, который в интернете — перестало. Можно сказать, зря делал, но зато сделал валидацию IP без регулярного выражения.
1. ip2long
2. Ещё раз о filter_var