我正在使用preg_replace
函数来过滤掉一些用户输入。下面的函数应该过滤掉Unicode中的控制字符,但似乎这些字符中的一些被归类为其他一些类别(标点符号,空格等),允许它们通过过滤。为什么会这样?
preg_replace("/[^\p{L}\p{M}\p{N}\p{P}\p{S}]/u", "", $message);
以下是使用上述方法
传递过滤的一些Unicode control charactersU+0085 NEXT LINE (NEL) …
U+008C PARTIAL LINE BACKWARD Œ
U+0095 MESSAGE WAITING •
preg_replace
的安全性如何?还有更好的方法吗?
答案 0 :(得分:3)
在您的代码中,您有:
"a…Œ•a"
其中包含:
…
U + 2026水平省略号Œ
U + 0152 Latin capital ligature OE •
U + 2022 Bullet 正如您所料,Œ
是一封信\p{L}
,另外两封是标点符号\p{P}
,所以都允许这样做。
你被一个资源误导,有人说…
是U + 0085,依此类推;不是这种情况。发生这种情况的可能原因是他们写了一个HTML文件,其中包含数字字符引用…
。
在HTML中,字符引用€
到Ÿ
(又名€
到Ÿ
)实际上并不代表具有代码点U + 0080到U + 009F的Unicode字符。相反,它们表示Windows代码页1252(西欧)编码中的编码形式位于0x80和0x9F之间的字符。代码页1252中的字节0x85是省略号,因此…
表示U + 2026而不是U + 0085。
这是由于历史原因:古代浏览器中的错误早于现代对Unicode的理解,被其他人复制并最终被standardised by HTML5复制。 XML并没有受到这种异常的影响:在XHTML中,…
确实是U + 0085。
您的表达式适用于代码点U + 0080-U + 009F中的真实(不可见“C1”)控制字符:
function unichr($i) { // get character from code point, in UTF-8 string form
return iconv('UCS-4LE', 'UTF-8', pack('V', $i));
}
$message = 'a'.unichr(0x85).unichr(0x8C).unichr(0x95).'a';
$filtered = preg_replace("/[^\p{L}\p{M}\p{N}\p{P}\p{S}]/u", "", $message);
var_dump($filtered);
<<< string(2) "aa"
答案 1 :(得分:0)
在使用preg_replace()
之前尝试utf8_encode()
preg_replace("/[^\p{L}\p{M}\p{N}\p{P}\p{S}]/u", "", utf8_encode($message));