Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Проверка валидности IP адреса

Дмитрий Рассанов
Источник: rassanov.ru
15 июня 2009 года.

Подпрограммы на Perl.

В качестве предварительной проверки и отделения IP адреса от предположим URL, выполним такую проверку:

#!/usr/bin/perl
...
if ( $host_IP =~ m/^[\d\.]+$/ ) { # разрешенные символы – цифра и точка
   # это может быть IP адрес, нужна дополнительная проверка
} else { # $host_IP не является IP адресом }
...

Классическая проверка IP адреса на валидность:

if ( $ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ ) {
   # $ip – правильный ? IP адрес
} else { # $ip – неверный IP адрес}
Однако такая проверка совершенно недостаточна, поскольку отдельные части (октеты) в IP адресе могут быть больше 255. Поэтому дополним предыдущий код:
if ( $ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
   && ($1 < 256 && $2 < 256  && $3 < 256  && $4 < 256 ) ) {
   # $ip – правильный IP адрес
} else { # $ip – неверный IP адрес}
Проверка предположим $1 >= 0 не нужна, поскольку конструкция \d в шаблоне пропустит только 0 и положительные числа.
Для удобства использования отдельных фрагментов кода в дальнейшем, оформим их в виде подпрограмм.
Можно разбить IP адрес на части и проверить каждую часть в цикле:
# подпрограмма valid_ip возвращает IP адрес в случае успешной проверки и undef в противоположном # случае
sub valid_ip {
    my @oct = grep { $_ >= 0 && $_ <= 255 && $_ !~ /^0\d{1,2}$/ } split /\./, shift;
    return unless @oct == 4;
    return join('.', @oct);
}
Для случая, когда часть IP адреса может начинаться с нуля, например 012, проверка ($_ >= 0 && $_ <= 255) дополнена кодом && $_ !~ /^0\d{1,2}$/
Мне очень нравится Perl именно из-за подобных конструкций в духе Unix, поэтому хочется рассмотреть основную строчку подпрограммы valid_ip подробнее:
1. Получаем переданное значение подпрограмме в переменную $_ , а именно shift .
2. Разбиваем (превращаем в массив) оператором split значение в переменной $_ в данном случае по точкам. Хотя явным способом переменная $_ здесь не фигурирует (не обозначена).
3. Полученный массив передаем оператору grep , который каждый элемент массива поочередно помещает в свою собственную переменную $_ для выполнения операций сравнения в блоке (обозначенном фигурными скобками). На "выходе" оператора grep получаем массив, состоящий из элементов входного массива, если для этого элемента массива операция сравнения имеет истинное значение. В скалярном контексте возвращаемое оператором grep – это количество успешных сравнений.
Поэтому подпрограмму valid_ip можно переписать:
# valid_ip возвращает 1 в случае валидности IP адреса и undef в противоположном случае
sub valid_ip {
    4 == grep { $_ >= 0 && $_ <= 255 && $_ !~ /^0\d{1,2}$/ } split /\./, shift;
}
Здесь используется то, что возвращаемое подпрограммой значение – это последнее вычисленное. В данном случае это результат операции сравнения с числом 4.
До этого мы рассматривали проверки IP адреса, исходя из количества октетов – 4. Однако для пользователя (посетителя), вводящего данные вручную, удобнее, если мы будем дополнять (заполнять) недостающие октеты нулями. Т.е. IP адрес вида 192.2 превратим в 192.2.0.0
# valid_ip возвращает IP адрес в случае его валидности и undef в противоположном случае
sub valid_ip {
    my @octets = split /\./, shift;
    for ( my $i = 0; $i <= 3; $i++ ) {
        if ( defined $octets[$i] ) {
           return unless ($octets[$i] >= 0 && $octets[$i] <= 255 && $octets[$i] !~ /^0\d{1,2}$/);
        } else { $octets[$i] = 0; }
    }
    return join('.', @octets);
}
Если мы хотим сообщить пользователю об ошибке(ошибках) в IP адресе, например "подсветить" ошибочный октет(ы) в CGI скрипте, тогда:
# valid_ip возвращает true и валидный IP адрес или false и IP адрес с "подсвеченными" ошибочными # октетами
sub valid_ip {
    my @octets = split /\./, shift;
    my $osh = 0;
    for ( my $i = 0; $i <= 3; $i++ ) {
        if ( defined $octets[$i] ) {
           unless ($octets[$i] >= 0 && $octets[$i] <= 255 && $octets[$i] !~ /^0\d{1,2}$/) {
                  $octets[$i] = "<font color='#FF0000'> $octets[$i] </font>";
                  $osh++;
           }
        } else { $octets[$i] = 0; }
    }
    return('true', join('.', @octets)) unless ( $osh );
    return('false', join('.', @octets));
}
Можно сообщить пользователю детально о каждой ошибке в IP адресе:
# valid_ip возвращает тескт ошибки либо 0 в случае валидности IP
sub valid_ip {
    my $ip = shift;
    return "Не указан IP" unless ( $ip );
    return "Недопустимые символы в IP $ip" unless ( $ip =~ m/^[\d\.]+$/ );
    return "Недопустимый IP $ip - начинается с точки" if ($ip =~ m/^\./);
    return "Недопустимый IP $ip - заканчивается точкой" if ($ip =~ m/\.$/);
# Число октетов
      return "Ошибка - IP адрес должен содержать 4 октета" unless ( 3 == ($ip =~ tr/\./\./) );
# Проверка пустых октетов
      return "Не указана часть IP - две точки подряд" if ($ip =~ m/\.\./);
# Проверка на допустимый диапазон значений в октете
      foreach (split /\./, $ip) {
              return "Недопустимое значение в IP адресе $ip - $_" unless ($_ >= 0 && $_ < 256 && $_ !~ /^0\d{1,2}$/ );
      }
      return 0;
}

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
12K
08 августа 2006 года
Dipish
33 / / 08.08.2006
Мне нравитсяМне не нравится
8 июля 2009, 01:14:01
Очень часто еще требуется проверка на класс сети, чтобы отсечь, например, диапазоны локальных адресов.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог