Autor Zpráva
ShiraNai7
Profil
Existují v UTF-8 (tj mimo ASCII) nějaké znaky, které můžou být nějakým způsobem "škodlivé"? Tím myslím, že by kvůli nim prohlížeč nezobrazil celou stránku nebo by se onen znak zobrazil nějakým šíleným způsobem a narušil design. Chci povolit v uživatelských jménech jakékoliv UTF-8 znaky (čeština, ruština, japonština... prostě cokoliv) a zakázat jen řídící ASCII znaky a HTML symboly. Je třeba se něčeho obávat?

edit: validace pomocí mb_check_encoding() je samozřejmostí
Kajman_
Profil *
Problémem mohou být téměř stejné zobrazení různých znaků. Kdy se pak budou běžným návštěvníkům jevit dva různé loginy naprosto stejné.
ShiraNai7
Profil
To mě nenapadlo. Existuje nějaký seznam běžných UTF-8 rozsahů, abych umožnil zadání jména ve všech nebo alespoň většině světových jazyků?
Joker
Profil
ShiraNai7:
Existuje nějaký seznam běžných UTF-8 rozsahů, abych umožnil zadání jména ve všech nebo alespoň většině světových jazyků?
Tohle je řešení jen pokud to bude omezené na jazyky psané latinkou.
Například cyrilice má spoustu znaků vypadajících stejně jako znaky z latinky a přitom je nezbytná třeba pro ruštinu a další jazyky.

Možná by bylo řešení zakázat kombinovat různé abecedy (např. jméno by mohlo být buď latinkou, nebo azbukou, ale ne kombinací obojího).
Ani to ale nemusí být dokonalé, viz třeba: Pepa - Рера
ShiraNai7
Profil
Třeba zakázat kombinace, ale nějak to umožnit. Neznáte nějakou stránku, kde jsou popsány rozsahy jednotlivých abeced?
DoubleThink
Profil *
Kajman:
Kdy se pak budou běžným návštěvníkům jevit dva různé loginy naprosto stejné.
Otázka je, jestli to tak moc vadí. V moderované diskusi takové konflikty řeší moderátoři a jinde je to podle mě jedno.
Kajman_
Profil *
ShiraNai7:
Neznáte nějakou stránku, kde jsou popsány rozsahy jednotlivých abeced?
http://en.wikipedia.org/wiki/Unicode#Standardized_subsets

DoubleThink:
Otázka je, jestli to tak moc vadí.
Jo, to si musí ShiraNai7 rozhodnout sám.

Kdyby to vadilo, tak bych na to možná nešel jako Joker, klidně bych povolil v registraci kombinaci azbuky a latinky, spíše bych se snažil nepovolit takové kombinace, které jsou příliš podobné již existujícímu loginu (ale jak tohoto dosáhnout netuším).
ShiraNai7
Profil
Ok, díky za ty rozsahy. Jak vypadá UTF-8 znak v hexadecimální podobě vím a jsem schopný s tím pracovat. Akorát jsem nějak nepobral co znamená to U+ před kódem daného znaku. Například znak "Л" má kód U+041B, ale v praxi vypadá hexadecimálně takto - "D09B". Jaký je vztah mezi kódem a reálnou binární podobou znaku?

edit: tak jsem trochu pohledal, zkusím to rozlousknout sám, nicméně kdyby měl někdo superjasné vysvětlení - sem s ním :P
DJ Miky
Profil
Znak Л má Unicode číslo U+041B (U+ je označení Unicode), D09B je jeho kódování v UTF-8. Např. v UTF-16 by se uložil jako 041B. Unicode je znaková sada, UTF-8 je jeden ze způsobů jejího uložení, viz:
http://cs.wikipedia.org/wiki/Unicode
http://cs.wikipedia.org/wiki/UTF-8
ShiraNai7
Profil
Díky, to jsem právě našel a tam to po čase i pochopil. Zde je výsledek - funkce, která vrátí unicode kód předaného UTF-8 znaku. Nenechte se zmást angličtinou, nikde jsem to neokopíroval, prostě jsem tak zvyklý psát :P Funkce by se možná měla přejmenovat na něco jako get_unicode_from_utf8, get_unicode je pracovní název..

A díky za spolupráci, teď mi již snad nic nebrání v analýze vstupního UTF-8 řetězce a povolení jen určitých unicode rozsahů.

function get_unicode($utfchar)
{

    // determine size
    $byte = ord($utfchar[0]);
    if(($byte & 128) === 0) return $byte;
    if(($byte >> 5) === 6) {
        $bytes = 1;
        $data = $byte & 31;
    } elseif(($byte >> 4) === 14) {
        $bytes = 2;
        $data = $byte & 15;
    } elseif(($byte >> 3) === 30) {
        $bytes = 3;
        $data = $byte & 7;
    } elseif(($byte >> 2) === 62) {
        $bytes = 4;
        $data = $byte & 3;
    } elseif(($byte >> 1) === 126) {
        $bytes = 5;
        $data = $byte & 1;
    } else  throw new OutOfRangeException(__method__.': Invalid unicode!');

    // add data from extra bytes
    for($i = 1; $i <= $bytes; ++$i) {
        $data <<= 6;
        $data |= (ord($utfchar[$i]) & 63);
    }
    return $data;

}


Samozřejmě jsem to i otestoval - vybral jsem postupně namátkou ze seznamu unicode znaků 28 náhodných symbolů a jejich uvedený unicode kód a srovnal ho s výstupem mé funkce. Kupodivu a mému nadšení se povedlo - žádné chyby. Uvedené symboly jsou dlouhé 2 nebo 3 bajty.

Test:
$test = array(array('Ɖ', '0189'), array('ƪ', '01AA'), array('ɧ', '0267'), array('˽', '02FD'), array('ψ', '03C8'), array('Щ', '0429'), array('Ѿ', '047E'), array('Ջ', '054B'), array('ש', '05E9'), array('ي', '064A'), array('۞', '06DE'), array('ܮ', '072E'), array('ޟ', '079F'), array('߷', '07F7'), array('न', '0928'), array('ਿ', '0A3F'), array('௵', '0BF5'), array('ൿ', '0D7F'), array('࿏', '0FCF'), array('ᄫ', '112B'), array('ᕰ', '1570'), array('ᚙ', '1699'), array('ᢇ', '1887'), array('ᦿ', '19BF'), array('Ắ', '1EAE'), array('※', '203B'), array('▓', '2593'), array('✰', '2730'), );
for($i = 0; isset($test[$i]); ++$i) {
    $code = str_pad(strtoupper(dechex(get_unicode($test[$i][0]))), 4, '0', STR_PAD_LEFT);
    echo 'Char: '.$test[$i][0].' - Computed code: U+'.$code.' - Valid code: '.'U+'.$test[$i][1].' - Result: ';
    if($code === $test[$i][1]) echo 'OK!';
    else echo '*** CHYBA ***';
    echo "\n";
}


Výsledek:
Char: Ɖ - Computed code: U+0189 - Valid code: U+0189 - Result: OK!
Char: ƪ - Computed code: U+01AA - Valid code: U+01AA - Result: OK!
Char: ɧ - Computed code: U+0267 - Valid code: U+0267 - Result: OK!
Char: ˽ - Computed code: U+02FD - Valid code: U+02FD - Result: OK!
Char: ψ - Computed code: U+03C8 - Valid code: U+03C8 - Result: OK!
Char: Щ - Computed code: U+0429 - Valid code: U+0429 - Result: OK!
Char: Ѿ - Computed code: U+047E - Valid code: U+047E - Result: OK!
Char: Ջ - Computed code: U+054B - Valid code: U+054B - Result: OK!
Char: ש - Computed code: U+05E9 - Valid code: U+05E9 - Result: OK!
Char: ي - Computed code: U+064A - Valid code: U+064A - Result: OK!
Char: ۞ - Computed code: U+06DE - Valid code: U+06DE - Result: OK!
Char: ܮ - Computed code: U+072E - Valid code: U+072E - Result: OK!
Char: ޟ - Computed code: U+079F - Valid code: U+079F - Result: OK!
Char: ߷ - Computed code: U+07F7 - Valid code: U+07F7 - Result: OK!
Char: न - Computed code: U+0928 - Valid code: U+0928 - Result: OK!
Char: ਿ - Computed code: U+0A3F - Valid code: U+0A3F - Result: OK!
Char: ௵ - Computed code: U+0BF5 - Valid code: U+0BF5 - Result: OK!
Char: ൿ - Computed code: U+0D7F - Valid code: U+0D7F - Result: OK!
Char: ࿏ - Computed code: U+0FCF - Valid code: U+0FCF - Result: OK!
Char: ᄫ - Computed code: U+112B - Valid code: U+112B - Result: OK!
Char: ᕰ - Computed code: U+1570 - Valid code: U+1570 - Result: OK!
Char: ᚙ - Computed code: U+1699 - Valid code: U+1699 - Result: OK!
Char: ᢇ - Computed code: U+1887 - Valid code: U+1887 - Result: OK!
Char: ᦿ - Computed code: U+19BF - Valid code: U+19BF - Result: OK!
Char: Ắ - Computed code: U+1EAE - Valid code: U+1EAE - Result: OK!
Char: ※ - Computed code: U+203B - Valid code: U+203B - Result: OK!
Char: ▓ - Computed code: U+2593 - Valid code: U+2593 - Result: OK!
Char: ✰ - Computed code: U+2730 - Valid code: U+2730 - Result: OK!

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0