我将如何处理需要具有特殊字符的网址?

How would I go about urls that need to have special characters?

所以最初我有某些页面无法加载的问题,因为 url 有特殊字符,如 '、! 等,但 url 是从文件夹名称创建的。如果用户上传的文件夹包含回显时需要显示的特殊字符,如何将其从文件夹中删除但在显示链接时保留它?我在想,也许我不会让用户有机会命名文件夹并直接使用 mkdir 创建文件夹,而是将他们选择的文件夹名称上传到数据库并创建一个仅具有递增值的文件夹。我不知道这是否是一个好主意,或者我编写的代码是否有任何好处,所以我希望你们能给我一些建议,也许还能给我一个解决方案?

<?php 
# Get Variables
$seriesGet = $_GET['series'] ?? "";
$chapterGet = $_GET['chapter'] ?? "";


$seriesDir = scandir("series/");

print_r($seriesDir);


echo "<br>";

# Display Series folders

if (!$_GET) {
    $arrayStart = 0;

    foreach ($seriesDir as $series => $value) {
        if ($seriesDir[$arrayStart] != "." && $seriesDir[$arrayStart] != "..") {
            echo "<a href='testScript.php?series=". $seriesDir[$arrayStart] ."'>". $seriesDir[$arrayStart] ."</a>";
        }
        echo "<br>";
        $arrayStart = $arrayStart + 1;
    }
}
echo "<br>";

# Display chapters in series folder

if ($seriesGet && !$chapterGet) {

    $chapterDir = scandir("series/" . $seriesGet . "/");
    $seriesPath = "series/$seriesGet";

    echo "<img src='$seriesPath/cover.jpg'>";
    readfile("$seriesPath/description.txt");

    echo "<br>";
    $array2Start = 0;
    foreach ($chapterDir as $series => $value) {
        if ($chapterDir[$array2Start] != "." && $chapterDir[$array2Start] != ".." && $chapterDir[$array2Start] != "cover.jpg" && $chapterDir[$array2Start] != "description.txt") {
            echo "<a href='testScript.php?series=". $seriesGet . "&chapter=" . $chapterDir[$array2Start] ."'>". $chapterDir[$array2Start] ."</a>";
        }
        echo "<br>";
        $array2Start = $array2Start + 1;
    }
}

# Display Images

if ($seriesGet && $chapterGet) {
    $dirname = "series/" . $seriesGet. "/" . $chapterGet . "/";

    print_r($dirname);

    $images = glob($dirname."*.{jpg,png}", GLOB_BRACE);

    foreach($images as $image) {
        echo '<img src="'.$image.'" /><br />';
    }
}

一个好的文件名约定对你将来有好处。不要给用户太多的自由,也可以按照Window的电脑的命名习惯命名文件和文件夹。

看到这个link:

https://libguides.princeton.edu/c.php?g=102546&p=930626

要在 URL 中对保留实体(特殊字符)进行编码,您可以使用 percent-encoding

例如,感叹号 ! 编码为 %21。对于您提到的字符,您可以查阅 ASCII table 以查看值应该是什么。

I was thinking that maybe Instead of giving the user a chance to name the folder and it be created directly with mkdir, I would upload the folder name that they chose to a database and create a folder with just an incrementing value.

是的,您永远不应该让您的用户选择磁盘上文件的名称。如果您这样做并且不太小心,则可能会发生一系列攻击。最常见的情况是用户上传 executable 内容,或者使用相对路径写入其他位置。例如,他们可能会上传 something-evil.php,并且您的 Web 服务器可能配置错误,并且在转到 https://example.com/uploads/something-evil.php 时实际上运行了他们的代码。或者,也许他们像 ../../../../etc/init.d/evil-script 一样上传并在您的服务器上运行。

像您提议的那样,通过不允许用户控制文件名更容易完全避免该问题。只要确保它们不能覆盖其他文件,或者根本无法命名文件,即使它们位于另一个文件夹中。

现在,让我们检查一下您的代码...

$chapterDir = scandir("series/" . $seriesGet . "/");

这很危险!用户正在指定要读取的路径。就像我上面说的,你实际上允许他们插入相对路径并读取 PHP 可以读取的任何内容。错误配置的 Web 服务器很常见,您不希望它们从存储中读取它们不应该读取的内容。

echo "<a href='testScript.php?series=". $seriesDir[$arrayStart] ."'>"...

切勿将任意数据连接到 HTML 的上下文中!这里实际上存在多个问题。首先是你必须 URL-encode 在 URL 中使用任何东西。使用 urlencode()。其次是您的数据没有为 HTML 转义,因此某些数据可能会在某些脚本标记或其他内容中泄漏,甚至只会使您的 HTML 无效。使用 htmlspecialchars() 围绕您注入 HTML 的任意数据,即使它是您自己的可信数据。您正在将数据从一个上下文移动到另一个上下文,它需要正确转义。

我强烈推荐阅读 OWASP 前 10 名:https://owasp.org/www-project-top-ten/