¿Qué pasa con estos caracteres de combinación Unicode y cómo podemos filtrarlos?

91

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

Estos aparecieron recientemente en las secciones de comentarios de Facebook.

¿Cómo podemos desinfectar esto?

XCS
fuente
5
¿No has hecho esta pregunta antes? (Pregunta honesta.)
Ry-
5
Esos definitivamente no son ascii
Chris Eberle
31
¿Por qué las votaciones de cierre? Es una pregunta relacionada con la programación, ya que quiero saber cómo desinfectar este tipo de entrada para que las secciones de comentarios en mi sitio web no sean el patio de recreo de los niños de 13 años ...
XCS
17
กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิ "por lo que las secciones de comentarios en mi sitio web no serán el patio de recreo de los 13 años". En realidad, sin la desinfección, una publicación de estos caracteres puede hacer que el comentario anterior sea ilegible, lo que no es una experiencia agradable para el usuario.
XCS
14
@pjotr Definitivamente no es un error del navegador. Si desea que los caracteres no desborden el cuadro contenedor, simplemente puede resolverlo con CSS (desbordamiento: oculto;) ...
XCS

Respuestas:

80

¿Qué pasa con estos caracteres Unicode?

Ese es un personaje con una serie de personajes combinados . Debido a que los caracteres combinados en cuestión quieren ir por encima del carácter base, se acumulan (literalmente). Por ejemplo, el caso de

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

... es un ก (carácter tailandés ko kai ) ( U + 0E01 ) seguido de 20 copias del carácter combinado tailandés mai tho ( U + 0E49 ).

¿Cómo podemos desinfectar esto?

Usted podría pre-procesar el texto y limitar el número de caracteres de combinación que se pueden aplicar a un solo carácter, pero el esfuerzo puede no valer la pena la recompensa. Necesitaría las hojas de datos de todos los caracteres actuales para saber si se combinan o qué, y debe asegurarse de permitir al menos algunos porque algunos idiomas están escritos con varios signos diacríticos en una sola base. . Ahora, si desea limitar los comentarios al conjunto de caracteres latinos, sería una verificación de rango más fácil, pero por supuesto, esa es solo una opción si desea limitar los comentarios a solo unos pocos idiomas. Más información, hojas de códigos, etc. en unicode.org .

Por cierto, si alguna vez quieres saber cómo se compuso algún personaje, para otra pregunta, recientemente codifiqué una página rápida y sucia "Unicode Show Me" en JSBin. Simplemente copie y pegue el texto en el área de texto, y le mostrará todos los puntos de código (~ caracteres) que componen el texto, con enlaces como los de arriba a la página que describe cada carácter. Solo funciona para puntos de código en el rango U + FFFF y menores, porque está escrito en JavaScript y para manejar caracteres por encima de U + FFFF en JavaScript, tiene que hacer más trabajo del que quería hacer para esa pregunta (porque en JavaScript, un "personaje" es siempre 16 bits, lo que significa que para algunos idiomas un carácter se puede dividir en dos "caracteres" JavaScript separados y no lo tuve en cuenta), pero es útil para la mayoría de los textos ...

TJ Crowder
fuente
1
¿No eliminaría simplemente copias repetidas del mismo punto de código de combinación en una sola copia? ¿Cuándo necesitaría combinar el mismo punto de código en un punto de código base más de una vez?
Remy Lebeau
4
@RemyLebeau: "¿Cuándo necesitaría combinar el mismo punto de código en un punto de código base más de una vez?" No sé, sé muy, muy poco sobre cómo se escribe en otros idiomas, como el tailandés, por ejemplo. No me sorprendería en absoluto descubrir que más de uno del mismo punto de código fuera válido en algunos. Pero hacer eso no reduce la complejidad; todavía necesita una de las tablas Unicode para averiguar cuáles combinan caracteres.
TJ Crowder
Hice que su página aceptara la cadena Unicode de la URL, por ejemplo, jsbin.com/erajer/7/…
ubershmekel
2
Biblioteca de JavaScript para eliminar fácilmente las marcas de combinación Unicode de las cadenas: mths.be/stripcombiningmarks
Mathias Bynens
JavaScript usa UTF-16 con « pares sustitutos »
dolmen
17

Si tiene un motor de expresiones regulares con soporte Unicode decente, es trivial desinfectar este tipo de cadenas. En Perl, por ejemplo, puede eliminar todas las marcas de combinación excepto la primera de cada carácter (percibido por el usuario) de esta manera:

#!/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");

Esto imprimirá:

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

Nwellnhof
fuente
9
No puedo leer tibetano, pero me preocupa que este enfoque de fuerza bruta pueda eliminar la funcionalidad de la forma en que está diseñado el lenguaje. He visto unicode que tiene casos de uso legítimos de más de una marca de combinación. El árabe es un buen ejemplo. Intentaré recordar que mis compañeros de trabajo tibetanos lo dirigen.
FlipMcF
2
Tiene razón, ciertamente hay casos en los que varias marcas de combinación son legítimas. Pero puede cambiar fácilmente la expresión regular para permitir un cierto máximo de marcas.
nwellnhof
Votado a favor porque responde a la pregunta de "cómo desinfectar esto". Pero creo que esto sería una pesadilla de mantenimiento.
FlipMcF
Además, el RE simplemente elimina la duplicación adyacente . No sería limpiar, por ejemplo: <base><macron><overline><macron><overline>.... Por lo tanto, si su texto necesita varios caracteres de combinación diferentes , pasará bien; y todavía se podría crear texto malicioso.
Jesse Chisholm
13

"¿Cómo podemos desinfectar esto?" Se responde mejor arriba por TJ Crowder

Sin embargo, creo que la desinfección es el enfoque incorrecto, y Cristy lo tiene bien con overflow:hiddenel elemento que contiene css.

Al menos, así es como lo estoy resolviendo.

FlipMcF
fuente
6

Ok, este me tomó un tiempo darme cuenta, tenía la impresión de que la combinación de personajes para producir zalgo se limita a estos . Así que esperaba que la siguiente expresión regular atrapara a los monstruos.

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

y no funcionó ...

El problema es que la lista en wiki no cubre la gama completa de caracteres combinados.

Lo que me dio una pista es "ก้้้้้้้้้้้้้้้้้้้้".charCodeAt(2).toString(16)= "e49" que, al no estar dentro de un rango de combinación, cae en 'Uso privado'.

En C # caen bajo UnicodeCategory.NonSpacingMarky el siguiente script los elimina:

    [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>");
    }

Al mirar la tabla generada, debería poder ver cuáles se apilan. Un rango que falta en wiki es 06D6-06DCotro 0730-0749.

ACTUALIZAR:

Aquí está la expresión regular actualizada que debería eliminar todo el zalgo, incluidos los omitidos en el rango 'normal'.

([\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,})

Lo más difícil es identificarlos, una vez que haya hecho eso, hay una multitud de soluciones, incluidas algunas buenas anteriores.

Espero que esto te ahorre algo de tiempo.

Matas Vaitkevicius
fuente
Yo diría, ¡no enviar spam a este spam!
Praveen Kumar Purushothaman
@PraveenKumar ¿Le importaría explicar lo que quiere decir?
Matas Vaitkevicius
Agradezco tu respuesta, pero esta es una pregunta perdida. Entonces, ¿por qué agregar nuevas respuestas innecesariamente? Es solo mi punto de vista. Además, tu respuesta no es JavaScript, ¿verdad?
Praveen Kumar Purushothaman
4
@PraveenKumar Revela por qué ([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]{2,})no funciona la validación normal de zalgo . ¿No le parece interesante que apilar Unicode no se limite a lo que hay en wiki? ¿Qué quiere decir con "pregunta perdida contestada"? EDITAR : Puede que le resulte extraño agregar la respuesta a la pregunta de 3 años, pero como me tomó un tiempo descubrir por qué este tipo de zalgo funcionaba, no podía dejar que ese conocimiento se desperdiciara. El próximo chico ahorrará algo de tiempo.
Matas Vaitkevicius
7
@PraveenKumar la pregunta no indica un idioma, y ​​publicar una nueva respuesta en una pregunta anterior es completamente apropiado si las respuestas anteriores eran deficientes de alguna manera. Desafortunadamente, no tengo suficiente experiencia con este problema, o obtendría un voto a favor de mí.
Mark Ransom