Что случилось с этими комбинированными символами Unicode и как их отфильтровать?

91

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

Они недавно появились в разделах комментариев facebook.

Как мы можем это очистить?

XCS
источник
5
Разве вы не задавали этот вопрос раньше? (Честный вопрос.)
Ry-
5
Это определенно не ascii
Крис Эберли
31
Почему заключительные голоса? Это вопрос, связанный с программированием, так как я хочу знать, как дезинфицировать этот тип ввода, чтобы разделы комментариев на моем веб-сайте не были игровой площадкой для 13-летних ...
XCS
17
กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิ, «поэтому разделы комментариев на моем веб-сайте не будут игровой площадкой для 13-летних». На самом деле, без очистки одно сообщение с этими символами может сделать комментарий над ним нечитаемым, что совсем не приятно для пользователей.
XCS
14
@pjotr Это определенно не ошибка браузера. Если вы хотите, чтобы символы не переполняли содержащееся поле, вы можете просто решить эту проблему с помощью CSS (overflow: hidden;) ...
XCS

Ответы:

80

Что случилось с этими символами Юникода?

Это персонаж с серией комбинируемых персонажей . Поскольку рассматриваемые комбинируемые символы хотят быть выше базового символа, они складываются (буквально). Например, случай

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

... это ก (тайский символ ko kai ) ( U + 0E01 ), за которым следует 20 копий тайского комбинированного символа mai tho ( U + 0E49 ).

Как мы можем это очистить?

Вы можете предварительно обработать текст и ограничить количество комбинируемых символов, которые могут быть применены к одному символу, но усилия могут не окупиться. Вам понадобятся таблицы данных для всех текущих символов, чтобы вы знали, объединяются ли они или что, и вам нужно обязательно разрешить хотя бы несколько, потому что некоторые языки написаны с несколькими диакритическими знаками на одной основе . Теперь, если вы хотите ограничить комментарии набором латинских символов, это будет более легкая проверка диапазона, но, конечно, это только вариант, если вы хотите ограничить комментарии только несколькими языками. Дополнительная информация, кодовые таблицы и т. Д. На unicode.org .

Кстати, если вы когда-нибудь захотите узнать, как был составлен какой-то символ, для другого вопроса совсем недавно я закодировал быструю и грязную страницу «Unicode Show Me» на JSBin. Вы просто копируете и вставляете текст в текстовую область, и он показывает вам все кодовые точки (~ символы), из которых состоит текст, со ссылками, такими как приведенные выше, на страницу, описывающую каждый символ. Он работает только для кодовых точек в диапазоне U + FFFF и ниже, потому что он написан на JavaScript и для обработки символов выше U + FFFF в JavaScript вам нужно выполнить больше работы, чем я хотел бы сделать для этого вопроса (потому что в JavaScript "характер" всегда 16 бит, что означает, что для некоторых языков символ может быть разделен на два отдельных «символа» JavaScript, и я не учел этого), но это удобно для большинства текстов ...

TJ Crowder
источник
1
Не могли бы вы просто удалить повторяющиеся копии одной и той же кодовой точки объединения в одну копию? Когда вам когда-нибудь понадобится объединить одну и ту же кодовую точку в базовую кодовую точку более одного раза?
Реми Лебо
4
@RemyLebeau: "Когда вам когда-нибудь понадобится объединить одну и ту же кодовую точку в базовую кодовую точку более одного раза?" Я не знаю, я очень, очень мало знаю о том, как вы пишете на других языках - например, на тайском. Я не удивлюсь, если узнаю, что в некоторых допустимо более одного и того же кода. Но это не снижает сложности; вам все еще нужна одна из таблиц Unicode, чтобы определить, какие из них объединяют символы.
TJ Crowder
Я заставил вашу страницу принимать строку Unicode из URL- адреса,
ubershmekel
2
Библиотека JavaScript для простого удаления комбинированных знаков Unicode из строк: mths.be/stripcombiningmarks
Матиас
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");

Это напечатает:

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

Nwellnhof
источник
9
Я не могу читать по-тибетски, но меня беспокоит, что этот метод грубой силы может лишить функциональность способа разработки языка. Я видел юникод, у которого есть законные варианты использования более чем одного комбинирующего знака. Арабский - хороший тому пример. Я постараюсь не забыть запустить это своими тибетскими коллегами.
FlipMcF
2
Вы правы, конечно, бывают случаи, когда несколько совмещенных знаков допустимы. Но вы можете легко изменить регулярное выражение, чтобы разрешить определенный максимум оценок.
nwellnhof
Проголосовали за, потому что он действительно отвечает на вопрос «как вы дезинфицируете это». Но я думаю, это был бы кошмар обслуживания.
FlipMcF
Кроме того, RE просто удаляет смежное дублирование. Это не будет убирать, скажем: <base><macron><overline><macron><overline>.... Итак, если вашему тексту нужно несколько разных комбинирующих символов, он пройдет нормально; и вредоносный текст все еще может быть создан.
Джесси Чизхолм
13

"Как мы можем это дезинфицировать" лучше всего ответил TJ Crowder.

Однако я думаю, что дезинфекция - это неправильный подход, и Кристи правильно overflow:hiddenиспользует элемент, содержащий css.

По крайней мере, так я это решаю.

FlipMcF
источник
6

Хорошо, это заняло у меня некоторое время, чтобы понять, у меня сложилось впечатление, что объединение символов для создания zalgo ограничивается ими . Поэтому я ожидал, что следующее регулярное выражение поймает уродов.

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

и это не сработало ...

Загвоздка в том, что список в вики не охватывает весь диапазон комбинируемых символов.

Что мне "ก้้้้้้้้้้้้้้้้้้้้".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>");
    }

Посмотрев на сгенерированную таблицу, вы сможете увидеть, какие из них складываются. Один диапазон, который отсутствует в вики, - это 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,})

Сложнее всего их идентифицировать, как только вы это сделаете - существует множество решений, в том числе некоторые хорошие.

Надеюсь, это сэкономит вам время.

Матас Вайткявичюс
источник
Я бы сказал, не спамить этот спам!
Правин Кумар Пурушотаман
@PraveenKumar Не могли бы вы уточнить, что вы имеете в виду?
Матас Вайткявичюс
Я ценю ваш ответ, но это вопрос без ответа. Так зачем добавлять новые ответы без надобности? Это всего лишь мой взгляд. Более того, ваш ответ - не JavaScript, верно?
Правин Кумар Пурушотаман
4
@PraveenKumar Он раскрывает, почему обычная проверка zalgo ([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]{2,})не работает. Вам не интересно, что укладка Unicode не ограничивается Whats on Wiki? Что вы имеете в виду под «потерянным ответом на вопрос»? РЕДАКТИРОВАТЬ : вам может показаться странным добавить ответ на вопрос трехлетней давности, но поскольку мне потребовалось время, чтобы понять, почему этот тип zalgo работает, я не мог позволить этим знаниям пропасть зря. Следующий парень сэкономит время.
Матас Вайткявичюс
7
@PraveenKumar, вопрос не указывает язык, и размещение нового ответа на старый вопрос полностью уместно, если старые ответы каким-то образом были несовершенными. К сожалению, у меня недостаточно опыта решения этой проблемы, иначе я бы получил положительный голос.
Марк Рэнсом,