В одной из задач мне требовалось сделать поле ввода домена для пользователя, а затем проверить насколько корректно он его ввел. Вроде задача простая, но как оказалось с ней пришлось повозиться полдня. Так как пользователь мог ввести домен совершенно разных форматах как с ошибкой, так и без нее.С каким сложностями может возникнуть проверка домена на корректность?
За истину я взял чистый домен формата: domen.ru
Пользователь может ввести домен так:
- с приставкой: http:// https:// //
- в нем может быть www, а может отсутствовать
- на конце домена может быть остаток пути /ssilka
Начнем с очевидного. Пусть домен передается в переменной $_POST["domen"] с формы:
//Сначала убираем http https //, если пользователь его вводил
$domen = preg_replace('/(http\:\/\/|https\:\/\/|\/\/)/', '', trim($_POST["domen"]));
//Теперь заменяем множество точек на одну sait..5.....ru => sait.5.ru - это пригодится в дальнейшем
$domen = preg_replace('/\.+/', '.', $domen);
/*Принудительно добавляем к домену http, чтобы выделить из ссылки домен за счет функции parse_url().
http://sa.ru/page => sa.ru
еда.рф/index.php?template=access => еда.рф*/
if(parse_url('http://'.$domen)) {$domen_ar = parse_url('http://'.$domen); $domen = $domen_ar['host']; }
//удаляем www, если оно есть в домене
$domen = str_replace('www.', '', $domen);
//После всех этих преобразований мы можем вывести наш очищенный домен
echo 'Домен: '.$domen;
Теперь, рассмотрим как будет обрабатывать скрипт домен при вводе различных форматов:
http://ya.ru => ya.ru
https://ya.ru => ya.ru
//ya.ru => ya.ru
ya.ru => ya.ru
www.ya.ru => ya.ru
http://www.ya.ru => ya.ru
https://www.ya.ru => ya.ru
//www.ya.ru => ya.ru
http://ya.ru/page => ya.ru
http://ya.ru?page => ya.ru
yait...5...ru => yait.5.ru
http://poddomen.ya.ru/page => poddomen.ya.ru
еда.рф => еда.рф
www.еда.рф#ok => еда.рф
http:/./ya.ru => http (намеренная ошибка)
www.ya.ru 23 => ya.ru 23 (намеренная ошибка)
В целом все хорошо, за исключением последних 2-х примеров, где есть намеренная ошибка. Давайте теперь проферим домен на корректность с помощью FILTER_VALIDATE_URL. И пару моментов для него:
- для FILTER_VALIDATE_URL обязателен http - поэтому подставляем его
- домены типа: еда.рф надо преобразовывать в xn--80ahc.xn--p1ai иначе проверку не пройдут
- FILTER_VALIDATE_URL считает любой URL верным, если в нем нет точки. http, sait - будет верным при проверке (а в любом домене должны быть 1 точка). Исправляем это так: считаем есть ли точка в домене, если нет, то добавляем в конец, за счет чего будут идти такие преобразования:
host => host.
bad => bad.
sa.ru => sa.ru
xn--80ahc.xn--p1ai => xn--80ahc.xn--p1ai
выражения типа host. и bad. уже не пройдут проверку
//если в домене нет ни 1 точки, то он уже не корректен - добавим точку в конец домена, чтобы FILTER_VALIDATE_URL пометил его как не верный
$domen_to = substr_count($domen,'.');
$domen = ($domen_to == 0) ? $domen.'.' : $domen;
if(filter_var('http://'.$domen, FILTER_VALIDATE_URL)) { echo ' <i>корректен</i>';
}
else echo ' введен не корректно!';
Теперь осталось сделать последнюю проверку на корректность ввода доменного расширения, для этого вставьте внутрь условия, где написано, что домен введен корректно код:
/*доппроверка на разрешенные доменные расширения
если в домене на конце есть разрешенное расшерение, заменяем все выражение на yes - корректно*/
$domen_ra = preg_replace('/.*\.(ru|com|xn--p1ai)$/i', 'yes', $domen);
if($domen_ra == 'yes') {
echo ' и имеет <i>разрешенное</i> расширение'; //Здесь уже делаем нужные действия, например, запись в БД
} else {
echo ' и имеет запрещенное расширение!';
}
Вот такой получился у меня замысловатый код проверки домена на корректность. Лучшего решения в сети не видел, поэтому пришлось сделать самому.
Добавить комментарий