Che succede con questi caratteri Unicode che combinano e come possiamo filtrarli?


91

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

Questi sono apparsi di recente nelle sezioni dei commenti di Facebook.

Come possiamo disinfettarlo?


5
Non hai mai fatto questa domanda prima? (Domanda onesta.)
Ry-

5
Quelli sono decisamente non ascii
Chris Eberle

31
Perché i voti di chiusura? È una domanda relativa alla programmazione, poiché voglio sapere come disinfettare questo tipo di input in modo che le sezioni dei commenti sul mio sito Web non siano il parco giochi dei 13 anni ...
XCS

17
กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิิิิิิ ก้้้้้้้้้้้้้้้้้้้้ ก็็็็็็็็็็็็็็็็็็็็ กิิิิิิิิิิิิิิิ "quindi le sezioni dei commenti sul mio sito web non saranno il parco giochi dei 13 anni." In realtà, senza la sanificazione, un post di questi caratteri può rendere illeggibile il commento sopra di esso, il che non è affatto un'esperienza piacevole per l'utente.
XCS

14
@pjotr Non è sicuramente un bug del browser. Se vuoi che i caratteri non superino il riquadro contenitore puoi semplicemente risolverlo con CSS (overflow: hidden;) ...
XCS

Risposte:


80

Che succede con questi personaggi Unicode?

Questo è un personaggio con una serie di caratteri combinati . Poiché i caratteri combinati in questione vogliono andare al di sopra del carattere di base, si accumulano (letteralmente). Ad esempio, il caso di

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

... è un ก (carattere tailandese ko kai ) ( U + 0E01 ) seguito da 20 copie del carattere tailandese che combina mai tho ( U + 0E49 ).

Come possiamo disinfettarlo?

Si potrebbe pre-elaborare il testo e limitare il numero di caratteri che conciliano che possono essere applicati ad un singolo carattere, ma lo sforzo non può valere la ricompensa. Avresti bisogno delle schede tecniche per tutti i caratteri correnti in modo da sapere se si stavano combinando o cosa, e dovresti essere sicuro di consentirne almeno alcuni perché alcune lingue sono scritte con diversi segni diacritici su una singola base . Ora, se vuoi limitare i commenti al set di caratteri latini, sarebbe un controllo dell'intervallo più semplice, ma ovviamente questa è solo un'opzione se vuoi limitare i commenti a poche lingue. Maggiori informazioni, fogli di codice, ecc . Su unicode.org .

A proposito, se vuoi sapere come è stato composto un personaggio, per un'altra domanda proprio di recente ho codificato una pagina "Unicode Show Me" veloce e sporca su JSBin. Devi solo copiare e incollare il testo nell'area di testo e ti mostra tutti i punti di codice (~ caratteri) di cui è composto il testo, con collegamenti come quelli sopra alla pagina che descrive ogni carattere. Funziona solo per i punti di codice nell'intervallo U + FFFF e inferiore, perché è scritto in JavaScript e per gestire i caratteri sopra U + FFFF in JavaScript devi fare più lavoro di quanto volessi fare per quella domanda (perché in JavaScript, un "carattere" è sempre 16 bit, il che significa che per alcune lingue un carattere può essere suddiviso in due "caratteri" JavaScript separati e non ne ho tenuto conto), ma è utile per la maggior parte dei testi ...


1
Non eliminereste semplicemente copie ripetute dello stesso punto di codice di combinazione in una singola copia? Quando avresti mai bisogno di combinare lo stesso punto di codice su un punto di codice base più di una volta?
Remy Lebeau

4
@ RemyLebeau: "Quando avresti mai bisogno di combinare lo stesso codepoint su un codepoint base più di una volta?" Non lo so, so molto, molto poco su come scrivi in ​​altre lingue, ad esempio il thailandese. Non sarei affatto sorpreso di scoprire che più di uno dello stesso punto di codice era valido in alcuni. Ma farlo non riduce la complessità; hai ancora bisogno di una delle tabelle Unicode per capire quali stanno combinando i caratteri.
TJ Crowder

Ho fatto in modo che la tua pagina accetti la stringa Unicode dall'URL,
ubershmekel

2
Libreria JavaScript per rimuovere facilmente i segni di combinazione Unicode dalle stringhe: mths.be/stripcombiningmarks
Mathias Bynens

JavaScript utilizza UTF-16 con « coppie surrogate »
dolmen

17

Se hai un motore regex con un discreto supporto Unicode, è banale disinfettare questo tipo di stringhe. In Perl, ad esempio, puoi rimuovere tutto tranne il primo segno di combinazione da ogni carattere (percepito dall'utente) in questo modo:

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

Questo stamperà:

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


9
Non so leggere il tibetano, ma sono preoccupato che questo approccio di forza bruta possa rimuovere la funzionalità dal modo in cui il linguaggio è progettato. Ho visto unicode che ha casi d'uso legittimi di più di un segno di combinazione. L'arabo è un buon esempio. Cercherò di ricordarmi di farlo funzionare dai miei colleghi tibetani.
FlipMcF

2
Hai ragione, ci sono certamente casi in cui più segni di combinazione sono legittimi. Ma puoi facilmente cambiare la regex per consentire un certo numero massimo di voti.
nwellnhof

Votato perché risponde alla domanda "come disinfettare questa". Ma penso che questo sarebbe un incubo di manutenzione.
FlipMcF

Inoltre, la RE rimuove solo la duplicazione adiacente . Non sarebbe ripulire, dire: <base><macron><overline><macron><overline>.... Quindi, se il tuo testo necessita di più caratteri combinati diversi , passerà bene; e il testo dannoso potrebbe ancora essere creato.
Jesse Chisholm

13

"Come possiamo disinfettare questo" è la risposta migliore sopra TJ Crowder

Tuttavia, penso che la sanificazione sia l'approccio sbagliato e Cristy ha ragione overflow:hiddensull'elemento che contiene CSS.

Almeno, è così che lo sto risolvendo.


6

Ok, questo mi ci è voluto un po 'per capirlo, avevo l'impressione che combinare i personaggi per produrre zalgo si limitasse a questi . Quindi mi aspettavo che seguendo regex per catturare i mostri.

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

e non ha funzionato ...

Il problema è che l' elenco in wiki non copre l'intera gamma di caratteri combinati.

Ciò che mi ha dato un suggerimento è "ก้้้้้้้้้้้้้้้้้้้้".charCodeAt(2).toString(16)= "e49" che, non all'interno di un intervallo di combinazione, rientra in "Uso privato".

In C # rientrano UnicodeCategory.NonSpacingMarke il seguente script li 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>");
    }

Guardando la tabella generata dovresti essere in grado di vedere quali sono in pila. Un intervallo che manca su wiki è 06D6-06DCun altro 0730-0749.

AGGIORNARE:

Ecco un'espressione regolare aggiornata che dovrebbe ripescare tutto lo zalgo, compresi quelli bypassati nell'intervallo "normale".

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

La parte più difficile è identificarli, una volta che lo hai fatto: ci sono moltissime soluzioni tra cui alcune buone sopra.

Spero che questo ti faccia risparmiare tempo.


Direi di non spammare questo spam!
Praveen Kumar Purushothaman

@PraveenKumar Ti andrebbe di approfondire cosa intendi?
Matas Vaitkevicius

Apprezzo la tua risposta, ma questa è una domanda persa. Allora perché aggiungere nuove risposte inutilmente? È solo il mio punto di vista. Inoltre, la tua risposta non è JavaScript, giusto?
Praveen Kumar Purushothaman

4
@PraveenKumar Scopre perché la normale convalida zalgo ([\u0300–\u036F\u1AB0–\u1AFF\u1DC0–\u1DFF\u20D0–\u20FF\uFE20–\uFE2F]{2,})non funziona. Non trovi interessante il fatto che l'impilamento di unicode non sia limitato a ciò che è su wiki? Cosa intendi per "domanda con risposta persa"? EDIT : Potresti trovare strano aggiungere una risposta alla domanda di 3 anni, ma poiché mi ci è voluto un po 'per capire perché questo tipo di zalgo funzionasse, non potevo lasciare che tale conoscenza andasse sprecata. Il prossimo ragazzo farà risparmiare un po 'di tempo.
Matas Vaitkevicius

7
@PraveenKumar la domanda non indica una lingua e pubblicare una nuova risposta su una vecchia domanda è del tutto appropriato se le vecchie risposte erano in qualche modo carenti. Purtroppo non ho abbastanza esperienza con questo problema, altrimenti otterrei un voto positivo da parte mia.
Mark Ransom
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.