<div class="linkL">STRAŠNI MIKROSKOP</div>
<?php
$chapter = "chapters/" . $_GET["ch"] . ".php";
include $chapter;
?>
JS
$(".linkL").click(function() {
var a = $(this).html();
var b = a.split(' ').join('-');
var c = b.toLowerCase();
location.href = "index.php?ch=" + c;
});
после нажатия в адресной строке у меня есть index.php?ch=strašni-mikroskop
, Это нормально, но файл chapters/strašni-mikroskop
не входит!
Если я заменю š
с s
— все работает.
Итак, как я могу использовать приведенный выше код, используя š
символ юникода?
Все файлы закодированы как utf8.
location.href = "index.php?ch=" + c;
Вам нужно encodeURIComponent(c)
Вот. В противном случае любые символы, которые являются специальными в URL, например, %
или же &
, сломаю URL. Также это гарантирует, что кодировка, используемая в URL-адресе, является UTF-8; без явного кодирования это зависит от браузера, что происходит, и вы можете получить противоречивые результаты.
$chapter = "chapters/" . $_GET["ch"] . ".php";
include $chapter;
Проблема 1: кодировка имени файла должна совпадать с кодировкой в URL. Это означает, что вам нужно настроить инструмент передачи файлов для использования UTF-8 (как вы это сделаете, зависит от инструмента). Если ваш сервер — Windows, вы не можете использовать UTF-8, поэтому вам нужно намеренно неправильно кодировать ваши имена файлов. (Например, для западноевропейского сервера он будет использовать кодовую страницу 1252, и в этом случае вам придется неправильно записать файл straÅ¡ni-mikroskop.php
.)
Вероятно, не стоит пытаться делать это, так как он хрупок и сломается при переходе на другие инструменты и серверы.
Проблема 2: это дыра в безопасности. Злоумышленник может указать произвольные относительные пути, например ../someotherdirectory/x
выполнять файлы, которые вы не ожидали. Это может сочетаться с другими функциями, такими как загрузка файлов, чтобы дать злоумышленнику возможность выполнять произвольный код на вашем сервере. Или можно просто включить index.php
Сам, чтобы получить бесконечный цикл и DoS вашего сервера.
Вы можете избежать обеих этих проблем с помощью безопасной схемы кодирования. Например с bin2hex(c)
Вы могли бы назвать свой файл 73747261c5a16e692d6d696b726f736b6f70.php
который будет работать где угодно и избегать специальных символов пути, таких как /
,
Но в общем случае лучше не позволять пользователю выбирать произвольный файл PHP. Обычно лучше иметь статический список возможностей в скрипте; тогда вы можете называть свои файлы, как вам нравится. например
switch ($_GET['ch']) {
case 'strašni-mikroskop': include 'chapters/strasni-mikroskop.php'; break;
case '☃': include 'chapters/snowman.php'; break;
...
}
Проблема 3. Разметка ссылок с помощью <div>
это очень плохо для доступности, юзабилити и SEO. Почему бы просто не использовать нормально <a>
ссылки?
Других решений пока нет …