ФорумПрограммированиеПыхнуть хотите?Готовые решения → Приведение к абсолютному URI

Приведение к абсолютному URI

  • vasa_c

    Сообщения: 3131 Репутация: N Группа: в ухо

    Spritz 5 сентября 2007 г. 12:58

    Раздел: фишки для начинающих.


    /**
    * Приведение ссылки к абсолютному URI
    *
    * @param string $link ссылка (абсолютный URI, абсолютный путь на сайте, относительный путь)
    * @param string $base базовый URI (можно без "http://")
    * @return string абсолютный URI ссылки
    */
    function uri2absolute($link, $base)
    {
    if (!preg_match('~^(http://[^/?#]+)?([^?#]*)?(\?[^#]*)?(#.*)?$~i', $link.'#', $matchesLink)) {
    return false;
    }
    if (!empty($matchesLink[1])) {
    return $link;
    }
    if (!preg_match('~^(http://)?([^/?#]+)(/[^?#]*)?(\?[^#]*)?(#.*)?$~i', $base.'#', $matchesBase)) {
    return false;
    }
    if (empty($matchesLink[2])) {
    if (empty($matchesLink[3])) {
    return 'http://'.$matchesBase[2].$matchesBase[3].$matchesBase[4];;
    }
    return 'http://'.$matchesBase[2].$matchesBase[3].$matchesLink[3];
    }
    $pathLink = explode('/', $matchesLink[2]);
    if ($pathLink[0] == '') {
    return 'http://'.$matchesBase[2].$matchesLink[2].$matchesLink[3];
    }
    $pathBase = explode('/', preg_replace('~^/~', '', $matchesBase[3]));
    if (sizeOf($pathBase) > 0) {
    array_pop($pathBase);
    }
    foreach ($pathLink as $p) {
    if ($p == '.') {
    continue;
    } elseif ($p == '..') {
    if (sizeOf($pathBase) > 0) {
    array_pop($pathBase);
    }
    } else {
    array_push($pathBase, $p);
    }
    }
    return 'http://'.$matchesBase[2].'/'.implode('/', $pathBase).$matchesLink[3];
    }


    Одна из областей применения - вытаскивание ссылок из html-кода. Ссылки, как известно, могут указываться разными способами. Это может быть абсолютный URI (http[nobbc]://[/nobbc]site.ru/path), либо абсолютный путь на текущем сайте (/path/to/file.php), либо путь относительно текущего документа (./../path/to/file). Данная функция позволяет привести их все к абсолютному виду.

    Примеры (базовым URI обычно является адрес текущей страницы):

    // Путь от корня. Результат: http://site.com@user:password/path/to/file.php?x=10
    print uri2absolute('/path/to/file.php?x=10', 'http://site.com@user:password/one/two/three.html?y=20#fragment');

    print '<br />';

    // Тот же сценарий с другими параметрами. Результат: http://site.com/one/two/three.html?x=10
    print uri2absolute('?x=10', 'site.com/one/two/three.html?y=20#fragment');

    print '<br />';

    // Пустая ссылка (возможно с js-обработчиком). Результат: http://site.com/one/two/three.html?y=20
    print uri2absolute('#', 'site.com/one/two/three.html?y=20#fragment');

    print '<br />';

    // Файл в том же каталоге. Результат: http://site.com/one/two/file.php
    print uri2absolute('file.php', 'site.com/one/two/three.html?y=20#fragment');

    print '<br />';

    // Так же, но в базовом пути последний элемент - каталог. Результат: http://site.com/one/two/three/file.php
    print uri2absolute('file.php', 'site.com/one/two/three/?y=20#fragment');

    print '<br />';

    // Выход из текущего каталога. Результат: http://site.com/one/new/path/file.php?x=10
    print uri2absolute('./../../new/path/file.php?x=10', 'site.com/one/two/three/?y=20#fragment');

    print '<br />';

    // Ссылка является абсолютной. Базовый путь ни на что не влияет. Результат: http://domain.com/path
    print uri2absolute('http://domain.com/path', 'site.com');



    Так же при подобном разборе ссылок не стоит забывать о теге BASE. Обработать его можно следующим образом:

    /**
    * Получение базового пути для относительных ссылок в html-документа
    *
    * @param string $htmlCode код страницы
    * @param string $url адрес страницы
    * @return string базовый путь
    */
    function getBaseHref($htmlCode, $url)
    {
    if (!preg_match('~<base\s+href\s*=\s*[\'"]?([^\'">]+).*?>~is', $htmlCode, $matches)) {
    return $url;
    }
    return uri2absolute(htmlSpecialChars_decode($matches[1]), $url);
    }
    [/php]

    Посылаем на вход функции код html-страницы и её адрес, на выходе получаем базовый адрес для всех относительных ссылок внутри документа. Если тега <BASE> в документе нет, базовым адресом будет адрес самого документа.


    Еще uri2absolute() может быть удобна для переадресации сценария (что часто делается, после обработки формы). Обычно делается это с помощью header + exit(). В соответствии со стандартами в http-заголовке location может быть указан только aбсолютный URI. Большинство браузеров, правда, ест всё что угодно, но все равно это неправильно. Кроме того, постоянно писать header и exit, тоже надоедает:
    [php]
    /**
    * Переадресация браузера
    *
    * @param string $path [optional]
    */
    function location($path = false)
    {
    $base = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
    if ($path === false) {
    $path = $base;
    } elseif ($path === true) {
    $path = preg_replace('~\?.*$~', '', $base);
    } else {
    $path = uri2absolute($path, $base);
    }
    header('Location: '.$path);
    exit();
    }
    [/php]

    Где нужно вызываем:
    [php]
    location('http://php.net/'); // Идите почитайте мануал
    location('/script.php'); // Переадресуем на тот же сайт
    location('./../script.php'); // Используем относительную переадресацию
    location(); // На самого же себя
    location(true); // На самого себя, с отрезанием GET-параметров
    [/php]

Пожалуйста, авторизуйтесь, чтобы написать комментарий!