Портативный и безопасный способ получить 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
,
Если это не работает для вас, извините, но я могу думать о чем-нибудь еще.
РЕДАКТИРОВАТЬ - Еще немного чтения для вас:
- Drupal request_uri () (почему они продолжают говорить
REQUEST_URI
Apache специфичен?) PHP_SELF
противPATH_INFO
противSCRIPT_NAME
противREQUEST_URI
Я думаю, что здесь есть хитрость, чтобы получить "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 из него.
Теперь у нас есть две четкие и сфокусированные проблемы реализации:
- Как получить URL?
- Как получить 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'];