如何防止像Zalgo文本这样的变音符号

时间:2012-08-15 23:51:05

标签: c# unicode user-input diacritics zalgo

huh?

上图所示的角色是几个月前由Mikko Hyppönen发来的,他是一位以计算机病毒和计算机安全TED talks着称的计算机安全专家。关于SO,我只会发布它的图像,但你明白了。这显然不是你想要在你的网站上传播并吓跑游客的东西。

经过进一步检查,该字符似乎是一个泰语字母和超过87个变音符号的字母(甚至有限制?!)。这让我想到了安全性,本地化以及如何处理这种输入。我的搜索引导我在Stack上this question,然后在stripping diacritics上发表Michael Kaplan的博客文章。在其中,他演示了如何将字符串分解为其“基本”字符(为简洁起见,在此简化):

StringBuilder sb = new StringBuilder();
foreach (char c in "façade".Normalize(NormalizationForm.FormD))
{
    if (char.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
        sb.Append(c);
}
Response.Write(sb.ToString()); // facade 

我可以看到这在某些情况下是如何有用的,但就用户输入而言,它将剥离所有变音符号。正如卡普兰指出的那样,删除一些语言中的变音符号可以完全改变单词的含义。这引出了一个问题:如何在用户输入/输出中允许一些变音符号,但排除其他极端情况,例如MikkoHyppönen的“超人”?

3 个答案:

答案 0 :(得分:23)

  

是否有限制?!

本质上不是Unicode。在UAX-15中存在“流安全”格式的概念,其设置了30个组合器的限制......通常不保证Unicode字符串是流安全的,但这当然可以作为Unicode的标志。不打算标准化需要比这更长的字形簇的新字符。

30仍然是一个非常糟糕的。已知时间最长的自然语言字形集群是1个基数的西藏Hakṣhmalawarayaṁ加上8个组合器,所以现在归一化为NFD并且不允许连续超过8个组合器的任何序列是合理的。

如果您只关心常见的西欧语言,您可能会将其降低到2.因此可能会在这些语言之间妥协。

答案 1 :(得分:2)

我认为我找到了使用NormalizationForm.FormC代替NormalizationForm.FormD的解决方案。根据{{​​3}}:

  

[FormC]表示使用full标准化Unicode字符串   规范分解,然后用序列替换   他们的主要复合材料,如果可能的话。

我认为它意味着它将字符分解为基本形式,然后根据一组保持一致的规则重新组合它们。我认为这对于比较目的很有用,但在我的情况下它完美无缺。 üéÄ等字符会被准确地分解/重新组合,而虚假字符无法重新组合,因此保持其基本形式:

enter image description here

答案 2 :(得分:1)

Here's regex应该消灭所有zalgo,包括在正常情况下被绕过的zalgo'范围。

([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F\u0483-\u0486\u05C7\u0610-\u061A\u0656-\u065F\u0670\u06D6-\u06ED\u0711\u0730-\u073F\u0743-\u074A\u0F18-\u0F19\u0F35\u0F37\u0F72-\u0F73\u0F7A-\u0F81\u0F84\u0e00-\u0eff\uFC5E-\uFC62]{2,})

最难的是识别它们,一旦你做到了 - 有很多解决方案。

希望这可以节省你一些时间。