2012-03-09 88 views
8

我使用的是用户输入下面的代码有一些问题:删除无效/不完整的多字节字符

htmlentities($string, ENT_COMPAT, 'UTF-8'); 

当检测PHP无效的多字节字符抛出一个通知:

PHP的警告:htmlentities():无效的多字节序列在123行/path/to/file.php参数

我的第一个想法是抑制错误,但这是sl流差的做法: http://derickrethans.nl/five-reasons-why-the-shutop-operator-should-be-avoided.html

我的第二个想法是使用ENT_IGNORE标志,但即使PHP手册建议不要使用此:

静静地舍弃无效代码单元序列而不是返回一个空字符串。使用这个标志是不鼓励的,因为它»may have security implications

的另一个原因有点使我对下面的一段代码:

// detect encoding 
$encoding = mb_detect_encoding($query); 
if($encoding != 'UTF-8') { 
    $query = mb_convert_encoding($query, 'UTF-8', $encoding); 
} else { 
    // strip out invalid utf8 sequences 
    $query = iconv('UTF-8', 'UTF-8//IGNORE', $query); 
} 

不幸的iconv 抛出E_NOTICE时,它会删除/忽略无效字符:

如果您将字符串// TRANSLIT附加到out_charset音译被激活。这意味着当字符不能在目标字符集中表示时,它可以通过一个或几个相似的字符来近似。如果追加字符串// IGNORE,那么无法在目标字符集中表示的字符会被丢弃。否则,从第一个非法字符中删除str,并生成E_NOTICE。

所以我基本上没有这里的选项。我宁愿使用一个久经考验的库来处理这类东西,而不是尝试使用我见过的一些基于正则表达式的解决方案。

因此,这导致我到我的最后一个问题: 如何可以有效,安全地删除无效的多字节字符,没有通知/警告/错误?

+4

如果你不想使用'ENT_IGNORE',你也不想使用'// IGNORE'。他们做同样的事情,并具有相同的安全影响。这可能是一个明显的观点和懒惰的方法,但是...... *不应该在生产中隐藏这些错误*?这些情况抛出E_NOTICE是为了让服务器管理员意识到服务器可能存在的问题 - 只有当有人恶意发送它们或者某些数据被破坏时才会出现无效字符,这两个都需要管理员注意。无论如何,这是一个极端的边缘案例。 – DaveRandom 2012-03-09 10:40:48

+0

是*拒绝*无效编码UTF-8的一个选项?如果它坏了,你可能不应该用它开始。 – deceze 2012-03-09 12:36:31

+0

戴夫,是的错误隐藏,但我们正在日志中看着他们。这是一个边缘情况,有人因为某种原因发送了坏的参数。 – Dean 2012-03-09 14:03:19

回答

2

如何在不发出通知/警告/错误的情况下有效,安全地删除无效的多字节字符?

那么,正如你已经在你自己的问题中概述的那样(or at least linked),删除无效字节序列不是一个选项。

相反,它应与替换字符U + FFFD来替换可能。从PHP 5.4.0开始,您可以使用ENT_SUBSTITUTE标志作为htmlentities。如果你不想拒绝字符串,这可能是最安全的。

iconv总会给你在最近的PHP版本警告如果连不删除整个字符串。所以它不适合你。

4

iconv('UTF-8', "ISO-8859-1//IGNORE", $string);

对我来说工作得非常好。似乎没有产生任何通知。

+1

+1我正在使用:'iconv('UTF-8','ASCII // TRANSLIT',$ var)'和IGNORE而不是TRANSLIT修复了'无效字符'的通知,并从不需要的表情符号图标串。 – 2015-08-22 12:35:50

相关问题