гадгие ссылки 2 вида /path/qwe

12
Коля Дубр
На сайте с 02.03.2005
Offline
153
#11

Примерчик кода сегодня нарою, когда обед будет. Базовый УРИ - адрес, относительно которого рассчитываются все относительные адреса в документе.

По сути это адрес директории, в которой лежит документ. Например, конструкция ../index.php имеет смысл только в контексте известного базового адреса, например root.ru/dir/subdir/ - такая конструкция будет указывать на root.ru/dir/index.php, фактически сообщая браузеру, что надо взять базовый адрес, откусить от него последнюю папку и прилепить имя файла. Вот этому и надо научить робота. Но для этого он ДОЛЖЕН знать абсолютный адрес текущей страницы.

Разрабатываю общую шину (http://habrahabr.ru/company/floxim/blog/268467/) помаленьку. ...а еще у меня есть бложек (http://www.blogovo.ru/).
Коля Дубр
На сайте с 02.03.2005
Offline
153
#12

Так. Не нашел я старый вариант. Вот так приблизительно оно было:

function url_rel_to_abs($url, $base) {

$urltemplate = "/(http:\/\/(?:www.)*[^\/]+)((?:[\/]\w+)+[\/](?![\/]))(.*)$/i";
preg_match_all($urltemplate, $base, $parts);
/*
В этом регэкспе делим УРЛ на 3 части:
1 - домен, без слеша на конце;
2 - путь, с обоих сторон слеши
3 - имя файла, т.е. все, что после последнего слеша
*/
$host = $parts[1][0];
$path = $parts[2][0];
$file = $parts[3][0];
if (!preg_match("/\.|\?/", $file) && !empty($file)) {
//Если в имени файла нет точки или знака вопроса,
//то это вероятно директория без завершающего слаша.
//прилепляем к пути
$path .= $file."/";
}
if (preg_match("/^[\/]/", $url)) {
//Если ссылка начинается со слеша, считаем от корня,
//т.е. просто добавляем эту ссылку к хосту
return $host.$url;
} elseif (preg_match("/^\.\.\//", $url)) {
//Если ссылка начинается с ../ - считаем сколько раз такая конструкция
//встречается, и отрезаем от пути соответствующее кол-во директорий
//(переходим на столько директорий вверх в иерархии)
preg_match_all("/\.\.\//", $url, $levels);
foreach ($levels[0] as $lev) {
$path = preg_replace("/(?<=[\/])\w+[\/]$/", "", $path);
}
return $host.$path.(preg_replace("/\.\.\//", "",$url));
} elseif (preg_match("/^\.\//", $url) || preg_match("/^\w/", $url)) {
//Если ссылка начинается с ./ (значит "текущий уровень иерархии") или
//не с управляющей конструкции, удаляем из нее ./ и добавляем в конец базового УРЛ
return $host.$path.(preg_replace("/\.\//", "", $url));
}
}

Эта функция берет относительную ссылку и абсолютный адрес страницы, на которой эта ссылка находится, возвращает ссылку в абсолютном формате.

Нет нормальной проверки валидности УРЛов, и вообще это все чисто схематически. Как-то так.

Коля Дубр
На сайте с 02.03.2005
Offline
153
#13

Ух, че-то я заморочился)

Вместо шаблона $urltemplate надо использовать вот такой:

$urltemplate = "/(http:\/\/(?:www.)*[^\/]+)((?:[\/]\w*)*[\/](?![\/]))*(.*)$/i";

А еще добавить вот так:

if (empty($path)) {$path = "/";}

после склеивания $path и $file, если $file не похож на файл или на query (для этого как раз там в шаблоне знак вопроса фигурирует, чтоб работать со ссылками вида root.ru/dir/?var=val

4F
На сайте с 25.04.2005
Offline
20
4LF
#14
Нет нормальной проверки валидности УРЛов

жаль...

скрипт написал, потом стал становится на такие вот грабли... начал рыть, потом верить в чудеса :)....

я немного подругому сделал...

я подавал на вход урл без базового... (ваша мысль с $base мне ольше нравится)

$host->{name} = например site.ru

$host->{www} = некоторый сайты не отвечают без www = поэтому приходится смотреть вдруг ссылка указана абсолютная да еще и с www


#
# analyseURL($url)
#
sub analyseURL
{
$_[0] =~ s/\n//;
my $url = $_[0];
if ( substr($url, 0, 1) eq '#' || $url =~ /mailto:|javascript:/i )
{
return 0;
}

# search http:// or www. or http://www.
if ( $_[0] =~ /^http:\/\/www\.|^http:\/\/|^www\./i )
{
if ( $_[0] =~ /^http:\/\/(www\.$host->{name})|(^http:\/\/$host->{name})|(^www\.$host->{name})/i )
{
if ( defined($1) || defined($3) ) # http://www.$host or www.$host
{
$host->{www} = "www.";
}
elsif ( defined($2) ) # http://$host
{
$host->{www} = "";
}
$_[0] =~ s/http:\/\///i;
$_[0] =~ s/www\.//i;
}
else
{
return 2;
}
}
# replace 'server' from url
$_[0] =~ s/^$host->{name}//i;

# if page not absolute
if ( substr($_[0], 0, 1) ne '/' )
{
$query =~ /(.*\/)/i;
$_[0] = $1.$_[0];
}

#if url contain ../
$_[0] =~ s/[^\/]*?\/\.\.\//\//g;

#if url contain ./
$_[0] =~ s/\.\///g;
#if url contain ////
$_[0] =~ s/\/+/\//g;

# replace SESSIONID
$_[0] =~ s/\&amp;/&/g;

# replace navigate on page #name
if ( $_[0] =~ /\#/ )
{
$_[0] =~ s/\#[0-9a-z_\-]+$//i;
$_[0] =~ s/\#[0-9a-z_\-]+\?/?/i;
$_[0] =~ s/\#[0-9a-z_\-]+\&/&/i;
}
$_[0] =~ s/\?$|\&$//;
return 1;
}
12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий