12

我有一个应用程序,用户可以在其中将文本输入表单。

数据保存到 MySQL 数据库(排序规则:)utf8_general_ci,然后输出为 XML(编码:UTF-8)。

问题是人们倾向于从其他来源剪切和粘贴他们的信息,例如 Microsoft Word 文档或 PDF。

此输入文本通常包含不适合输出编码的字符,例如“智能引号”,这些字符来自Windows-1252 编码的文档

这显然会在转换或以其他方式处理 XML 时导致问题,因为字符是非法的。

那么,如何清理输入呢?

以前,我使用了一些相当暴力的方法,例如“de-moronize”脚本,它包含一长串搜索和替换操作。

这仍然是最好的方法吗?还有其他方法吗?

我可以在表单上设置accept-charset 属性并让浏览器为我做吗?

如果是这样,哪些浏览器会这样做并且可能会出现任何问题?

另外,我的数据库怎么会接受这些字符,它们是 UTF-8 中的保留/控制字符?

如您所见,我对编码的了解足以知道我有问题,但我现在有点超出我的深度......

TIA

4

3 回答 3

9

此输入文本通常包含不适合输出编码的字符,例如“智能引号”,这些字符来自 Windows-1252 编码的文档

“智能引号”(cp1252 中的字节 147 和 148)是完全有效的 Unicode 字符,U+201C 和 U+201D。您的应用程序应该能够无缝地处理它们;如果没有,你做错了什么,很可能所有非 ASCII 字符都会失败。

无论字符是来自输入它们的人还是来自 Word 粘贴的人,浏览器都应该将 UTF-8 编码的字符提交给您的应用程序,该应用程序应该将相同的 UTF-8 字节存储到数据库中。

如果浏览器未以 UTF-8 格式提交,您可能无法设置包含表单的 HTML 页面的字符集。这可以使用以下方法完成:

Content-Type: text/html;charset=utf-8

HTTP 标头和/或:

<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

<head> 中的元素。

我可以在表单上设置 accept-charset 属性并让浏览器为我做吗?

不,由于 IE,accept-charset 基本上没有用,IE 将其误解为“如果页面上的字符集无法编码我们想要的字符,请尝试使用此字符集”,而不是“始终使用此字符集”。这意味着如果您使用 accept-charset ,您最终可能会同时提交多种编码,而无法确定哪个是哪个。好的!

我的数据库怎么会接受这些字符,它们是 UTF-8 中的保留/控制字符?

在 MySQL 中,UTF-8 只是一个排序规则,用于比较和排序。它仍然将数据存储为字节,并不真正关心它们是否不是有效的 UTF-8 序列。

无论如何,最好在您的应用程序中解码和检查传入的 UTF-8 序列,因为在现代 Unicode 中无效的“短序列”可以隐藏“<” 旧浏览器仍可识别的字符(至少 IE6 pre-SP2、Opera 7)。

预计到达时间:

所以,我输入了一个包含字节 146 的字符串

不,您输入了一个 Unicode 字符 U+201B。浏览器处理 Unicode 字符,而不是字节,直到它必须将序列化的表单提交给服务器。然后它决定如何将字符转换为字节,如果页面被处理为 UTF-8,它将始终选择 UTF-8。

(如果不是 UTF-8,浏览器往往会以不符合标准的方式作弊:对于所有不适合编码的字符,它会将它们编码为 HTML 字符引用,例如 '&#8217;' . 这是错误的,因为您现在无法区分浏览器转义的 '&' 和真实的、用户键入的 '&',而且这是非常错误的,因为如果您随后将引用作为未转义的 HTML 回显,它看起来就像您做对了一样,实际上您只是制造了一个很大的旧安全漏洞。)

它作为 146 进入数据库

真的,一个 '\x92' 字节,而不是 '\xC2\x92'、'\xE2\x80\x99' 或 '&#146;'?

它是在我生成(UTF-8 编码的)XML 时出现的,为 146。浏览器没有抱怨

然后它没有作为单个 146 字节出现。当在 XML 文件中给出一个裸露的 '\x92' 时,浏览器会报错。(不是 HTML 文件,其中无效的 UTF-8 序列作为缺失字符字形出现。)

我怀疑它会以“&#146;”的形式出现 字符引用,格式正确(尽管字符 U+0092 是 C1 控件集的一部分,因此不会呈现任何有用的内容)。如果这是正在发生的事情,那么您的表单页面毕竟没有被选择为 UTF-8,并且您正在遭受上述浏览器自动转义提交问题。

于 2009-04-15T12:32:22.263 回答
2

你可以试试 Perl Encode模块。它支持许多字符集之间的转换,当然包括 UTF-8。我刚刚检查了我的 Perl 安装,它还支持“cp1252”,根据 Wikipedia,这只是 Windows-1252 的另一个名称。您可以使用以下一种衬垫检查您自己的安装:

perl -MEncode -e 'print map {"$_\n"} Encode->encodings(":all");'
于 2009-04-15T03:01:40.870 回答
1

“我可以在表单上设置 accept-charset 属性并让浏览器为我做这件事吗?”

仅当您准备好信任“浏览器”时-这可能适用于某些应用程序,但总的来说,它会让您对恶作剧敞开心扉(或更糟)。

(另见 bobince 关于 IE 的警告......)

伊恩

于 2009-04-16T02:48:17.510 回答