これらのUnicode結合文字はどうなっているのですか、またどのようにフィルタリングできますか?


91

กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้

これらは最近、Facebookのコメントセクションに表示されました。

どうすればこれを消毒できますか?


5
これまでにこの質問をしたことはありませんか?(正直な質問。)
Ry-

5
間違いなくアスキーではありません
Chris Eberle

31
なぜ最終投票ですか?私のWebサイトのコメントセクションが13歳の遊び場にならないように、このタイプの入力をサニタイズする方法を知りたいので、これはプログラミング関連の質問です...
XCS

17
soก้้้้้้้้้้้้้้้้้้้้ก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้กิิิิิิิิิิิิิิิิิิิิก้้้้้้้้้้้้้้้้้้้้ก็็็็็็็็็็็็็็็็็็็็ก็็็็็็็็็็็็็็็็็็็็กิิิิิิิิิิิิิิิิิิิิ「私のウェブサイトのコメントセクションは13歳の遊び場にはなりません。」実際にサニタイズを行わないと、これらの文字を投稿すると、上のコメントが判読できなくなる可能性があります。
XCS

14
@pjotr明らかにブラウザのバグではありません。文字が含まれているボックスからオーバーフローしないようにしたい場合は、CSSで簡単に解決できます(overflow:hidden;)...
XCS

回答:


80

これらのユニコード文字はどうなっていますか?

それは、一連の結合文字を持つ文字です。問題の結合文字はベース文字の上に行きたいので、それらは(文字通り)積み上げられます。たとえば、

ก้้้้้้้้้้้้้้้้้้้้

...それはก(Thai character ko kai)(U + 0E01)で、その後にタイ語の結合文字mai thoU + 0E49)が20コピー続きます。

どうすればこれを消毒できますか?

あなたは可能性があり、事前に処理したテキストを単一の文字に適用することができます結合文字の数を制限しますが、努力は価値が報酬ではないかもしれません。現在のすべての文字のデータシートが必要になるので、それらが組み合わされているか、または何であるかがわかります。一部の言語は単一のベースで複数の発音区別符号を使用して記述されているため、少なくともいくつかを許可する必要があります。これで、コメントをラテン文字セットに制限したい場合は、範囲チェックが簡単になりますが、コメントをいくつかの言語のみに制限したい場合は、これが唯一の選択肢です。unicode.orgの詳細情報、コードシートなど。

ところで、何かの文字がどのように構成されているのかを知りたい場合は、別の質問として、最近私はJSBinの簡潔で汚れた "Unicode Show Me"ページをコーディングしました。テキストをコピーしてテキスト領域に貼り付けるだけで、テキストを構成するすべてのコードポイント(〜文字)が表示され、上記のような各文字を説明するページへのリンクが表示されます。JavaScriptで記述されており、JavaScriptでU + FFFFを超える文字を処理するには、その質問に対して私がやりたい以上の作業を行う必要があるため、これはU + FFFF以下の範囲のコードポイントでのみ機能します(JavaScriptでは、 「キャラクター」は常に 16ビット。つまり、一部の言語では、文字が2つの別々のJavaScript「文字」に分割される可能性があり、私はそれを考慮しませんでしたが、ほとんどのテキストで便利です...


1
同じ結合コードポイントの繰り返しコピーを単一のコピーに削除して削除しませんか?同じコードポイントをベースコードポイントに2回以上組み合わせる必要があるのはいつですか。
レミールボー

4
@RemyLebeau:「同じコードポイントをベースコードポイントに2回以上組み合わせる必要があるのはいつですか?」他の言語、たとえばタイ語の書き方については、ほとんどわかりません。同じコードポイントが複数有効なものがあることに気づいても、驚くことはありません。しかし、それを行っても複雑さは減りません。どのテーブルが文字を組み合わせているかを判別するには、Unicodeテーブルの1つが必要です。
TJクラウダー


2
文字列からUnicode結合マークを簡単に削除するJavaScriptライブラリ:mths.be/stripcombiningmarks
Mathias Bynens 2014年

JavaScriptは« サロゲートペア » でUTF-16を使用します
ドルメン

17

適切なUnicodeサポートを備えた正規表現エンジンを使用している場合、この種の文字列をサニタイズするのは簡単です。たとえば、Perlでは、次のように、すべての(ユーザーが認識する)文字から最初の結合マーク以外のすべてを削除できます。

#!/usr/bin/perl
use strict;
use utf8;

binmode(STDOUT, ':utf8');

my $string = "กิิ ก้้ ก็็ ก็็ กิิ ก้้ ก็็ กิิ ก้้ กิิ ก้้ ก็็ ก็็ กิิ ก้้ ก็็ กิิ ก้้";
$string =~ s/(\p{Mark})\p{Mark}+/$1/g; # Strip excess combining marks
print("$string\n");

これは印刷されます:

กิก้ก็ก็กิก้ก็กิก้กิก้ก็ก็กิก้ก็กิก้


9
私はチベット語を読むことはできませんが、このブルートフォースアプローチが言語の設計方法から機能を削除する可能性があることを心配しています。複数の組み合わせマークの正当なユースケースを持つユニコードを見てきました。アラビア語が良い例です。私はチベット人の同僚がこれを実行することを忘れないようにしようとします。
FlipMcF 2013年

2
確かに、複数の結合マークが正当な場合は確かにあります。ただし、特定の最大数のマークを許可するように正規表現を簡単に変更できます。
nwellnhof 2013年

「これをどのようにサニタイズするか」という質問に答えるため、賛成です。しかし、これはメンテナンスの悪夢になると思います。
FlipMcF 2013年

また、REは隣接する重複を削除するだけです。次のようにクリーンアップしません<base><macron><overline><macron><overline>...。したがって、テキストに複数の異なる結合文字が必要な場合は、問題なく通過します。悪意のあるテキストが作成される可能性があります。
ジェシーチザム2018

13

「これをどのように消毒できるか」は、TJ Crowderによって上記で最もよく回答されています。

しかし、サニタイズは間違ったアプローチであり、Cristyoverflow:hiddencssを含む要素でそれを正しくしています。

少なくとも、それは私がそれを解決している方法です。


6

わかりました。これ理解するのに少し時間がかかりましたが、キャラクターを組み合わせてザルゴを作成することはこれらに限定されているという印象を受けました。だから私はフリークを捕まえるために正規表現従うことを期待しました。

([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]{2,})

そしてそれはうまくいきませんでした...

問題は、wikiのリストが結合文字の全範囲をカバーしていないことです。

ヒントになったのは"ก้้้้้้้้้้้้้้้้้้้้".charCodeAt(2).toString(16)=「e49」で、組み合わせの範囲ではなく「私用」に該当します。

C#ではそれらは該当しUnicodeCategory.NonSpacingMark、次のスクリプトはそれらをフラッシュします。

    [Test]
    public void IsZalgo()
    {
        var zalgo = new[] { UnicodeCategory.NonSpacingMark };

        File.Delete("IsModifyLike.html");
        File.AppendAllText("IsModifyLike.html", "<table>");
        for (var i = 0; i < 65535; i++)
        {
            var c = (char)i;
            if (zalgo.Contains(Char.GetUnicodeCategory(c)))
            {


                File.AppendAllText("IsModifyLike.html", string.Format("<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>A&#{3};&#{3};&#{3}</td></tr>\n",  i.ToString("X"), c, Char.GetUnicodeCategory(c), i));

            }
        }
        File.AppendAllText("IsModifyLike.html", "</table>");
    }

生成されたテーブルを見ると、どのテーブルがスタックしているかを確認できるはずです。Wikiで欠落している範囲の1つが06D6-06DC別の範囲です0730-0749

更新:

ここでは、「通常の」範囲でバイパスされたものを含むすべての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,})

最も難しいのは、いったんそれを実行したら、それらを識別することです-上記のいくつかの優れたものを含む多数のソリューションがあります。

これにより時間を節約できることを願っています。


私は、このスパムをスパムしないように言うでしょう!
Praveen Kumar Purushothaman

@PraveenKumarどういう意味ですか?
Matas Vaitkevicius

私はあなたの答えに感謝しますが、これは答えられない質問です。では、なぜ不必要に新しい答えを追加するのでしょうか?それは私の見解です。さらに、あなたの答えはJavaScriptではありませんよね?
Praveen Kumar Purushothaman

4
@PraveenKumar通常のzalgo検証([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]{2,})が機能しない理由を明らかにします。ユニコードのスタッキングがwikiにあるものに限定されないのは面白いと思いませんか?「回答がなくなった質問」とはどういう意味ですか?編集:3年前の質問に答えを追加するのは奇妙に思えるかもしれませんが、このタイプのzalgoが機能する理由を理解するのにしばらく時間がかかったので、そのような知識を無駄にすることはできませんでした。次の男は時間を節約します。
Matas Vaitkevicius

7
@PraveenKumar質問は言語を述べておらず、古い回答が何らかの形で不十分だった場合、古い質問に新しい回答を投稿することは完全に適切です。残念ながら、この問題については十分な経験がありません。
Mark Ransom
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.