代码之家  ›  专栏  ›  技术社区  ›  rg88

当htmlentities设置为“utf-8”时,图像不上载

php
  •  1
  • rg88  · 技术社区  · 14 年前

    我有一个表单,除其他外,它接受上传图像并将其粘贴到数据库中。以前我有一个函数过滤发布的数据,基本上是:

    function processInput($stuff) {
        $formdata = $stuff;
        $formdata = htmlentities($formdata, ENT_QUOTES);
        return "'" . mysql_real_escape_string(stripslashes($formdata)) . "'";
    }
    

    当为了修复一些未正确转换的奇怪实体,我将函数更改为(所有更改都是在htmlentities中添加了“utf-8”位):

    function processInput($stuff) {
            $formdata = $stuff;
            $formdata = htmlentities($formdata, ENT_QUOTES, 'UTF-8'); //added UTF-8
            return "'" . mysql_real_escape_string(stripslashes($formdata)) . "'";
        }
    

    现在图像无法上传。

    这是什么原因造成的?只需删除“utf-8”位,图像就可以正确上传,但用户输入系统的一些MS Word实体就会显示为胡言乱语。怎么回事?

    **edit:由于我无法对这个野兽的代码做太多更改,所以我可以使用htmlspecialchars()而不是htmlentities()来创建一个创可贴,这样至少在转换引号、尖括号等内容时,图像数据不会受到影响。 Bobince的建议非常好,但在这种情况下,我现在不能花时间来修复这个项目中混乱的遗留代码。我处理的大多数东西都是面向对象和基于框架的,但现在我第一手看到人们在PHP中谈论“意大利面代码”时的意思。

    1 回复  |  直到 14 年前
        1
  •  6
  •   bobince    14 年前
    function processInput($stuff) {
        $formdata = $stuff;
        $formdata = htmlentities($formdata, ENT_QUOTES);
        return "'" . mysql_real_escape_string(stripslashes($formdata)) . "'";
    }
    

    此函数表示对字符串处理的基本误解,这是PHP程序员常见的一种误解。

    SQL转义、HTML转义和输入验证是三个独立的函数,将在脚本的不同阶段使用。尝试一次完成所有任务是没有意义的;它只会导致在脚本的其他部分中使用的任何一个进程中出现__special_。你可以尝试修补这个功能来修复应用程序的某个部分的损坏,但是你会破坏其他功能。

    为什么图像会被破坏?好吧,还不清楚图像数据来自哪个路径 $_FILES 临时上载文件到数据库。但是,如果在任何时候涉及到这个函数,它都会彻底破坏图像文件的二进制内容。反斜线删除,HTML转义…没有任何图像能保存下来。

    1. mysql_real_escape_string 用于转义某些文本以包含在MySQL字符串文本中。只有在使用插入的文本生成SQL字符串文本时,才应始终使用它,并且 全局应用于输入。因为输入中的某些内容不会立即或单独进入数据库。例如,如果您 echo 作为HTML页面的输入值之一,当它包含如下字符时,您会发现其中有一堆不需要的反斜杠 ' . 这就是为什么你会以满页失控的反斜杠结尾。

      (即便如此,参数化查询通常比手动字符串黑客攻击更可取,并且 mysql_real_escape_字符串 . 它们隐藏了从您身上逃脱的字符串的细节,这样您就不会被它们迷惑。)

    2. htmlentities 用于转义要包含在HTML页中的文本。它应该只在PHP的输出模板位中使用。在所有输入上全局运行它是不合适的,因为并不是所有内容都将以HTML页或HTML页结尾,而且最可能的情况是,它将首先转到数据库,在那里您绝对不希望加载 < & 垃圾使您的文本无法可靠地搜索或子字符串。

      (即便如此, htmlspecialchars 通常比 HTML实体 因为它只编码真正需要它的字符。 HTML实体 将添加不必要的转义,并且除非您告诉它正确的编码,否则它也将完全弄乱所有非ASCII字符。 HTML实体 几乎不应该使用。)

    3. 至于 stripslashes …好吧,你 有时 需要将其应用于输入,但仅当白痴 magic_quotes_gpc 选项已打开。你当然不应该一直使用它,只有当你发现 魔力语录 开始了。它长期以来一直被弃用,谢天谢地逐渐消失,所以如果你检测到它被打开了,用一条错误消息进行轰炸可能同样好。然后你就可以扔掉整个 processInput 事情消失了。

    总结:

    • 在开始时间,做 全局输入处理。如果需要,您可以在此处执行特定于应用程序的验证,例如检查电话号码是否只是数字,或者从文本或其他内容中删除控制字符,但此处不应发生转义。

    • 在生成包含字符串文字的SQL查询时,在值进入字符串时对其使用SQL转义: $query= "SELECT * FROM t WHERE name='".mysql_real_escape_string($name)."'"; . 您可以用较短的名称定义一个函数来进行转义以保存一些输入。或者,更清楚地说,参数化。

    • 使用输入、数据库或其他地方的字符串进行HTML输出时,请使用HTML转义,例如: <p>Hello, <?php echo htmlspecialchars($name); ?>!</p> . 同样,您可以用短名称定义一个函数 echo htmlspecialchars 输入时保存。