Как определить требуемую страницу в PHP

Судя по формулировке вашего вопроса (вы использовали слово «скрыть»), вы уже знаете, что здесь происходит. Это явление называется «сокрытие имени». По какой-то причине каждый раз, когда кто-то задает вопрос о , почему происходит скрытие имени , люди, которые отвечают, говорят, что это называется «скрытие имени» и объясняют, как это работает (что вы, вероятно, уже знаете), или объясните как его переопределить (о котором вы никогда не спрашивали), но, похоже, никто не заботится об актуальном вопросе «почему».

Решение, обоснование скрытия имени, т.е. , почему , он фактически был разработан в C ++, заключается в том, чтобы избежать определенного противоречивого, непредвиденного и потенциально опасного поведения, которое может иметь место, если унаследованный набор перегруженных функций был позволен смешиваться с текущим набором перегрузок в данном классе. Вероятно, вы знаете, что в C + + перегрузка разрешает работу, выбирая наилучшую функцию из набора кандидатов. Это делается путем сопоставления типов аргументов с типами параметров. Правила сопоставления иногда могут быть сложными и часто приводят к результатам, которые могут быть восприняты нелогично неподготовленным пользователем. Добавление новых функций в набор ранее существующих может привести к довольно резкому сдвигу результатов разрешения перегрузки.

Например, предположим, что базовый класс B имеет функцию-член foo, которая принимает параметр типа void *, и все вызовы foo(NULL) разрешены B::foo(void *). Предположим, что скрытие имени отсутствует, и этот B::foo(void *) отображается во многих разных классах, спускающихся с B. Однако, скажем, в некотором [косвенном, удаленном] потомке D класса B определена функция foo(int). Теперь, без скрытия имени D, оба foo(void *) и foo(int) видны и участвуют в разрешении перегрузки. Какую функцию будут выполнять вызовы foo(NULL), если они сделаны через объект типа D? Они разрешат D::foo(int), поскольку int является лучшим совпадением для интегрального нуля (т. Е. NULL), чем любой тип указателя. Таким образом, по всей иерархии обращается к foo(NULL) к одной функции, а в D (и под) они внезапно решаются на другую.

Другой пример приведен в . Дизайн и эволюция C ++ , стр. 77:

class Base {
    int x;
public:
    virtual void copy(Base* p) { x = p-> x; }
};

class Derived{
    int xx;
public:
    virtual void copy(Derived* p) { xx = p->xx; Base::copy(p); }
};

void f(Base a, Derived b)
{
    a.copy(&b); // ok: copy Base part of b
    b.copy(&a); // error: copy(Base*) is hidden by copy(Derived*)
}

Без этого правила состояние b будет частично обновлено, что приводит к разрезанию.

Такое поведение считалось нежелательным при разработке языка. В качестве лучшего подхода было решено следовать спецификации «сокрытие имени», что означает, что каждый класс начинается с «чистого листа» в отношении каждого имени метода, которое он объявляет. Чтобы переопределить это поведение, пользователю необходимо выполнить явное действие: изначально переобучение унаследованных методов (в настоящее время устарело), ​​теперь явное использование использования-объявления.

Как вы правильно заметили в вашем исходном сообщении (я имею в виду замечание «Не полиморфное»), это поведение можно рассматривать как нарушение отношений IS-A между классами. Это правда, но, видимо, тогда было решено, что в конечном итоге сокрытие имен окажется меньшим злом.

17
задан dimo414 29 April 2013 в 20:36
поделиться

3 ответа

Я решил проверить это сам. Переменная $ _ SERVER ['SCRIPT_NAME'] обслуживает путь к запрошенному файлу, даже если это индексный файл, без параметров получения или чего-либо еще. В документации PHP указано, что он содержит путь файла, но, похоже, он относится к корню документа, как и PHP_SELF , но без уязвимости безопасности.

Вот это код, который я использовал для проверки: https://gist.github.com/dimo414/5484870

Вывод при запросе example.com/?foo=bar :

__FILE__:               /var/www/index.php
PHP_SELF:               /index.php
SCRIPT_NAME:            /index.php
REQUEST_URI:            /?foo=bar
parse_url(REQUEST_URI): /


__FILE__:               /var/www/pathtest.php
PHP_SELF:               /index.php
SCRIPT_NAME:            /index.php
REQUEST_URI:            /?foo=bar
parse_url(REQUEST_URI): /

И вывод при запросе example.com/index.php/ XSS :

__FILE__:               /var/www/index.php
PHP_SELF:               /index.php/XSS # note the XSS exploit (this is bold in browser)
SCRIPT_NAME:            /index.php     # No exploit here
REQUEST_URI:            /index.php/%3Cstrong%3EXSS%3C/strong%3E
parse_url(REQUEST_URI): /index.php/%3Cstrong%3EXSS%3C/strong%3E


__FILE__:               /var/www/pathtest.php
PHP_SELF:               /index.php/XSS
SCRIPT_NAME:            /index.php
REQUEST_URI:            /index.php/%3Cstrong%3EXSS%3C/strong%3E
parse_url(REQUEST_URI): /index.php/%3Cstrong%3EXSS%3C/strong%3E

Как видите, $ _ SERVER ['SCRIPT_NAME'] всегда дает вернуть файл, который изначально обрабатывал запрос,

27
ответ дан 30 November 2019 в 12:13
поделиться
$_SERVER['PHP_SELF']

Должен возвращать фактический сценарий. Но есть различные методы .

У меня была лучшая ссылка на матрицу всех различных переменных среды, связанных с файлами, но я не могу ее найти. Я отредактирую, если он появится.

Изменить: Я нашел красивую ветку SO, в которой подробно описаны различия между ними .

6
ответ дан 30 November 2019 в 12:13
поделиться
  1. parse_url ($ _ SERVER ['REQUEST_URI']) , а затем pathinfo ($ path) для получения запрошенного имени файла
  2. $ _ SERVER ['PHP_SELF'] , чтобы получить настоящее имя файла
  3. $ _ SERVER ['SCRIPT_NAME'] , чтобы получить настоящее имя файла
-1
ответ дан 30 November 2019 в 12:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: