Портативный и безопасный способ получить PATH_INFO

Я ищу портативный способ получить (удобно) $_SERVER['PATH_INFO'] переменная.

Прочитав некоторое время, получается PATH_INFO происходит от CGI/1.1, и мой не всегда присутствует во всех конфигурациях.

Каков наилучший (в основном в плане безопасности) способ получения этой переменной - кроме ее извлечения вручную (проблема безопасности).

6 ответов

Решение

Ну, я (почти) уверен, что без использования $_SERVER суперглобальные ключи, обеспечивающие альтернативный способ выяснить PATH_INFO просто невозможно, сказанное позволяет сначала перечислить все ключи $_SERVER, которые мы можем использовать:

  • 'PHP_SELF'
  • 'СТРОКА ЗАПРОСА'
  • 'SCRIPT_FILENAME'
  • 'PATH_TRANSLATED'
  • 'SCRIPT_NAME'
  • 'REQUEST_URI'
  • 'PATH_INFO'
  • 'ORIG_PATH_INFO'

Мы, очевидно, должны игнорировать последние два. Теперь мы должны (я не знаю это на самом деле, я просто предполагаю, потому что вы так сказали) отфильтровать все ключи, которые существуют в предоставленной вами ссылке ( что, кстати, является автономным банкоматом), что оставляет нам следующие ключи:

  • 'PHP_SELF'
  • 'SCRIPT_FILENAME'
  • 'REQUEST_URI'

Что касается вашего комментария к ответу Anthonys:

Вы просто манипулируете переменными сейчас. SCRIPT_FILENAME является частью спецификации CGI. Это не будет доступно, если PATH_INFO недоступен. Что касается REQUEST_URI Это специфичный для Apache mod_rewrite. - ЛираНуна

Я использую LightTPD/1.4.20-1 (Win32) с PHP 5.3.0 в качестве CGI, cgi.fix_pathinfo = 1 а также $_SERVER['REQUEST_URI'] очень доступно для меня, я также помню, как использовал ту же самую переменную в те времена, когда никто не использовал mod_rewrite так что мое честное скромное предположение, что вы в этом ошибаетесь. Учитывая SCRIPT_FILENAME ключ Я не могу проверить этот банкомат. Тем не менее, если мы действительно сильно закрываем глаза и считаем, что вы правы, у нас остается только одна переменная:

  • 'PHP_SELF'

Я не пытаюсь быть резким здесь (и я все еще верю, что есть больше решений), но если PHP_SELF это единственный ключ, с которым вы хотите, чтобы мы работали (при условии, что PHP_SELF сам) осталось только одно решение:

function PATH_INFO()
{
 if (array_key_exists('PATH_INFO', $_SERVER) === true)
 {
  return $_SERVER['PATH_INFO'];
 }

 $whatToUse = basename(__FILE__); // see below

 return substr($_SERVER['PHP_SELF'], strpos($_SERVER['PHP_SELF'], $whatToUse) + strlen($whatToUse));
}

Эта функция должна работать, однако при использовании __FILE__ константа, так как возвращает путь к файлу, где __FILE__ объявлена ​​константа, а не путь к запрашиваемому PHP-скрипту, поэтому $ whatToUse предназначен для: sou, вы можете заменить его на 'SCRIPT_FILENAME' или если вы действительно верите в то, что говорите, просто используйте '.php',

Вы должны также прочитать это относительно того, почему не использовать PHP_SELF ,

Если это не работает для вас, извините, но я могу думать о чем-нибудь еще.

РЕДАКТИРОВАТЬ - Еще немного чтения для вас:

Я думаю, что здесь есть хитрость, чтобы получить "path_info" другим способом:

$path_info = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['PHP_SELF']);

Например, доступ к URL-адресу, например: http://somehost.com/index.php/some/path/here, значение $path_info было бы: "/some/path/here"

У меня это работало на разных серверах Apache, работающих на Windows и Linux, но я не уверен на 100%, если это "безопасно" и "переносимо", очевидно, я не тестирую его в конфигурациях "ВСЕХ" серверов, но, похоже, работает...

Это зависит от определений "портативный" и "безопасный".

Дай мне посмотреть, понял ли я:

1) Вы не заинтересованы в CLI:

  • Вы упомянули PHP / CGI
  • PATH_INFO - это часть URL; поэтому имеет смысл обсуждать PATH_INFO только тогда, когда к скрипту обращаются по URL-адресу (то есть по HTTP-соединению, обычно запрашиваемому браузером)

2) Вы хотите иметь PATH_INFO во всех комбинациях ОС + HTTP сервер + PHP:

  • ОС может быть Windows, Linux и т. Д.
  • HTTP-сервер может быть Apache 1, Apache 2, NginX, Lighttpd и т. Д.
  • PHP может быть версии 4, 5, 6 или любой версии

Хммм... PHP_INFO в массиве $_SERVER предоставляется PHP для сценария, который выполняется только при определенных условиях, в зависимости от программного обеспечения, упомянутого выше. Это не всегда доступно. То же самое верно для всего массива $_SERVER!

Вкратце: "$_SERVER зависит от сервера"... поэтому переносимое решение не может ретранслировать $_SERVER... (приведу только один пример: у нас есть учебник по настройке переменных PHP/CGI $_SERVER для NginX HTTP-сервер на kbeezie.com/view/php-self-path-nginx/)

3) Несмотря на то, что было упомянуто выше, стоит упомянуть, что если у нас каким-то образом будет полный запрошенный URL-адрес, доступный в виде строки, то можно получить PATH_INFO из него, безопасно применяя регулярные выражения и другие строковые функции PHP (также проверяя входная строка в качестве действительного URI).

Итак, при условии, что у нас есть строка URL-адреса... тогда ДА, У нас есть портативный и безопасный способ определить PATH_INFO из него.


Теперь у нас есть две четкие и сфокусированные проблемы реализации:

  1. Как получить URL?
  2. Как получить PATH_INFO из URL?

Среди нескольких возможностей здесь возможный подход:

Как получить URL?

1) Обладая глубокими и всесторонними знаниями о каждой комбинации версий HTTP-сервер + ОС + PHP, проверьте и попробуйте каждую возможность получить URL-адрес из массива $_SERVER (проверьте "PHP_SELF", "QUERY_STRING", "SCRIPT_FILENAME", "PATH_TRANSLATED")., "SCRIPT_NAME", "REQUEST_URI", "PATH_INFO", "ORIG_PATH_INFO", "HTTP_HOST", "DOCUMENT_ROOT" или что-либо еще)

2) Если предыдущий шаг не удался, заставьте скрипт PHP вернуть код JavaScript, который отправляет информацию "document.URL" обратно. (Проблема переносимости передана на сторону клиента.)

Как получить PATH_INFO из URL?

Этот код, связанный здесь, делает это.

Это мое скромное мнение и подход к проблеме.

Как вы думаете?

function getPathInfo() {
    if (isset($_SERVER['PATH_INFO'])) {
        return $_SERVER['PATH_INFO'];
    }  
    $scriptname = preg_quote($_SERVER["SCRIPT_NAME"], '/');
    $pathinfo = preg_replace("/^$scriptname/", "", $_SERVER["PHP_SELF"]);
    return $pathinfo;
}

Изменить: без SCRIPT_NAME, при условии, что у вас есть DOCUMENT_ROOT (или вы можете определить / обнаружить его самостоятельно), и при условии, что у вас есть SCRIPT_FILENAME, затем:

function getPathInfo() {
    if (isset($_SERVER['PATH_INFO'])) {
        return $_SERVER['PATH_INFO'];
    }  
    $docroot = preg_quote($_SERVER["DOCUMENT_ROOT"], "/");
    $scriptname = preg_replace("/^$docroot/", "", $_SERVER["SCRIPT_FILENAME"]);
    $scriptname = preg_quote($scriptname, "/");
    $pathinfo = preg_replace("/^$scriptname/", "", $_SERVER["PHP_SELF"]);
    return $pathinfo;
}

Также @ Anthony (недостаточно комментариев, извините): использование str_replace() будет соответствовать в любом месте строки. Работать не гарантируется, вы хотите сопоставить его только в начале. Кроме того, ваш метод возврата всего 1 косой черты (через strrpos) для определения SCRIPT_NAME будет работать только в том случае, если скрипт находится в корневом каталоге, поэтому вам лучше не использовать скрипт script_filename для docroot.

Я не видел комментарии или ссылку перед публикацией. Вот кое-что, что может сработать, основываясь на том, что на странице, указанной выше, в качестве переменных, производных от CGI:

function getPathInfo() {
    if (isset($_SERVER['PATH_INFO'])) {
        return $_SERVER['PATH_INFO'];
    }  

    $script_filename = $_SERVER["SCRIPT_FILENAME"];
    $script_name_start = strrpos($script_filename, "/");
    $script_name = substr($script_filename, $script_name_start);

    //With the above you should have the plain file name of script without path        

    $script_uri = $_SERVER["REQUEST_URI"];
    $script_name_length = strlen($script_name);
    $path_start = $script_name_length + strpos($script_name, $script_uri);

    //You now have the position of where the script name ends in REQUEST_URI

    $pathinfo = substr($script_uri, $path_start);
    return $pathinfo;
}

Ты можешь попробовать

$_ENV['PATH_INFO']; or
getenv('PATH_INFO']; 
Другие вопросы по тегам