percent encoding, urlencode(), Apache и экранирование URI

95 views
Skip to first unread message

Arech

unread,
Oct 8, 2008, 5:36:00 AM10/8/08
to ru-zend-framework
Приветствую)

Первым делом хочу ещё раз поблагодарить всех, кто участвовал в решении
моего прошлого вопроса про регулярные выражения и роутинг. Честно
говоря, я приятно поражён профессионализмом подхода и конкретными
ответами по сути со ссылками на первоисточники. Это чертовски здорово)

У меня тут параллельно возник ещё один вопрос, относящийся к Zend
Framework вроде бы довольно косвенно, но, надеюсь, он ни у кого не
вызовет неприятных эмоций. Попробовал разузнать в сообществе более
общей webdev-направленности, но, к удивлению, - совершенно безуспешно.
Может быть опять именно здесь смогут подсказать?

Итак, суть проблемы:
В пхп требуется генерить странички с создаваемым пользователями
контентом. Я хочу, чтобы эти странички имели УРЛ в виде шаблона "Id-
title", где id - цифровой идентификатор контента, а title - некая
строчка, которая генерирится с помощью urlencode() из вводимой
пользователем информации при создании этой странички. Для краткости
будем считать, что title это urlencode() от пользовательского ввода.

Главный вопрос, который меня интересует, это как исключить возможность
формирования пользователем таких данных, которые бы вызывали
"неожиданное" поведение системы?

Поясню примером:
Вот, допустим вводит пользователь строку "тест/тест" (UTF-8), которая
содержит прямой слеш. urlencode() при формировании странички
превращает её в
%D1%82%D0%B5%D1%81%D1%82%2F%D1%82%D0%B5%D1%81%D1%82, которую можно,
вроде бы благополучно, отдавать пользователю. Всё хорошо, но когда
приходит этот или аналогичный запрос, содержащий %-кодированный прямой
слеш, мой Апач (1.3.33 из Денвера2) пытается обработать его в
раскодированном виде (уже обработанном urldecode()). Т.е. он считает,
что там есть прямой слеш и, соответственно, пытается найти ресурс по
адресу "..тест/тест". Очевидно, не находит его и выдаёт собственный
обработчки 404 not found. При этом, мой ПХП код даже не запускается.

Настройки .htaccess по части рерайта практически стандартны для ZF:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [L,QSA]

Т.е. пропускаются только обращения к существующим файлам, всё
остальное должно редиректится на index.php. Но в данном случае при
обращении к УРЛ с %2F - ничего не происходит, mod_rewrite даже не
отрабатывает, судя по всему.

Кстати, директива ErrorDocument 404 /index.php в этом случае тоже не
отрабатывает. 404 ошибка всё равно возвращается в дефолтовом виде.

Отсюда главный вопрос, как я понимаю сложившуюся ситуацию: какие ещё
символы, кроме "/" следует экранировать в исходной, полученной от
юзера, последовательности, перед передачей её в urlencode() и отправки
в канал? Другими словами, при получении каких ещё %-кодированных
символов Апач может так неожиданно реагировать?

Второй вопрос: а вообще почему Апач вдруг начинает обрабатывать %2F в
раскодированном виде "/" и выдаёт свой обработчик даже не запуская мой
код, хотя всё остальное %-кодирование URL нормально проходит в мой
index.php? Как его настроить, чтобы он этого не делал?

Спасибо.

Arech

unread,
Oct 8, 2008, 5:48:23 AM10/8/08
to ru-zend-framework
Упс, таки решили проблему.

Вкратце, это поведение Апача by design, управляется директивой
AllowEncodedSlashes начиная с версии 2.0.46 (
http://httpd.apache.org/docs/2.0/mod/core.html#allowencodedslashes ).
Получается, экранировать надо как минимум прямой и обратный слеши.

Если есть ещё какие соображения - буду рад услышать.
Всем спасибо, сорри за беспокойство)

Антон Коленков

unread,
Oct 8, 2008, 7:37:48 AM10/8/08
to ru-zend-...@googlegroups.com
Первая мысль которая посетила при прочтении задачи - предложить использовать функции

function base64_url_encode($input) {
    return strtr(base64_encode($input), '+/=', '-_,');
    }

function base64_url_decode($input) {
    return base64_decode(strtr($input, '-_,', '+/='));
    }

Взято из комментов отсюда: http://php.net/manual/en/function.base64-encode.php

Вторая мысль - просто заменять проценты на какой-то безобидный символ(точку, например), благодаря чему Апач не будет декодить.

Но приемлимость любого из этих вариантов зависит от Вашего приложения.

8 октября 2008 г. 13:48 пользователь Arech <arad...@gmail.com> написал:



--
С уважением,
    Антон

Arech

unread,
Oct 8, 2008, 10:06:37 AM10/8/08
to ru-zend-framework
> Но приемлимость любого из этих вариантов зависит от Вашего приложения.

Спасибо за идею, но главное требование (и причина, почему это всё
затевается) - SEO. Понимание поисковиками того, что написано в титле.
Ну и юзеру читать приятнее и понятнее, опять же. В случае %-
кодирования это всё работает отлично, в остальных - вряд ли.

Задачу решил заменой на точку по шаблону /[\x5C\/\$\?&\#@\:\=\pP\pM\pS]
+/u перед urlencode(). Пунктуация и спецсимволы мне преимущественно
пофиг..

Vlad Thepesh

unread,
Oct 9, 2008, 5:32:02 AM10/9/08
to ru-zend-...@googlegroups.com
Используйте транслит.

2008/10/8 Arech <arad...@gmail.com>:

Arech

unread,
Oct 9, 2008, 6:45:16 AM10/9/08
to ru-zend-framework
On 9 окт, 13:32, "Vlad Thepesh" <vlad.thep...@gmail.com> wrote:
> Используйте транслит.

Не, транслит тоже не интересно. Во первых, не все слова поисковики
понимают, как мне кажется, во вторых - практически все нормальные
браузеры уже поддерживают UTF-8 в УРЛ и видеть в статусной строке
vsyakie-krakozybry-uje-otkrovenno-zadalbyvaet ))
MediaWiki - хороший пример. Очень приятно работать с ней.
Reply all
Reply to author
Forward
0 new messages