PHP girdi filtreleme - utf8 kontrol vs ASCII kontrol

4 Cevap php

Ben bütün dizeleri utf8 olmasını sağlamak gerekir. Bir kullanıcıdan gelen bu giriş ASCII-gibi ya da utf8 gibi olduğunu kontrol etmek daha iyi olurdu?

//KohanaPHP
function is_ascii($str) {
    return ! preg_match('/[^\x00-\x7F]/S', $str);
}

//Wordpress
function seems_utf8($Str) {
    for ($i=0; $i<strlen($Str); $i++) {
    	if (ord($Str[$i]) < 0x80) continue; # 0bbbbbbb
    	elseif ((ord($Str[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
    	elseif ((ord($Str[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
    	elseif ((ord($Str[$i]) & 0xF8) == 0xF0) $n=3; # 11110bbb
    	elseif ((ord($Str[$i]) & 0xFC) == 0xF8) $n=4; # 111110bb
    	elseif ((ord($Str[$i]) & 0xFE) == 0xFC) $n=5; # 1111110b
    	else return false; # Does not match any model
    	for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
    		if ((++$i == strlen($Str)) || ((ord($Str[$i]) & 0xC0) != 0x80))
    		return false;
    	}
    }
    return true;
}

Ben 100 dizeleri (yarım geçerli utf8/ascii ve yarım değil) bazı kıyaslama yaptım ve is_ascii sadece 0,001 alır ederken seems_utf8 () görevleri 0.011 bulundu. Ama benim gut sizin için ne ödeme olsun bana ve utf8 kontrol daha iyi bir seçim olacaktır.

Ben o zaman bu dönüştürme gibi bir şey yapmayı planlıyorum.

<?php

/* Example data */
$string[] = 'hello';
$string[] = 'asdfghjkl;qwertyuiop[]\zxcvbnm,./]12345657890-=+_)(*&^%$#@!';
$string[] = '';
$string[] = 'accentué';
$string[] = '»á½µÎ½Ï‰Î½ Ï„á½° ';
$string[] = '???R??=8 ????? ++++¦??? ???2??????';
$string[] = 'hello¦ùó 5/5¡45-52ZÜ¿»'. "0x93". octdec('77'). decbin(26). "F???pp?? ??? ". '»á½µÎ½Ï‰Î½ Ï„á½° ';


$time = microtime(true);

//Count the successes
$true = array(1 => 0, 0 => 0);

foreach($string as $s) {
    $r = seems_utf8($s);	//0.011

    print_pre(mb_substr($s, 0, 30). ' is '. ($r ? 'UTF-8' : 'non-UTF-8'));


    if( ! $r ) {

    	$e = mb_detect_encoding($s, "auto");

    	print_pre('Encoding: '. $e);

    	//Convert
    	$s = iconv($e, 'UTF-8//TRANSLIT', $s);

    	print_pre(mb_substr($s, 0, 30). ' is now '. (seems_utf8($s) ? 'valid' : 'not'). ' UTF-8');
    }

}

print_pre($true);
print_pre((microtime(TRUE) - $time). ' seconds');

function print_pre() { print '<pre>'; print_r(func_get_args()); print '</pre>'; }

4 Cevap

Ben bu yaklaşımın gerekli parçaları nasıl emin değilim. UTF-8 giriş için kullanıcı isteyin ve onlar atmak ve tekrar sormak size "başka bir şey" verirseniz.

Çeşitli karakter kusurlu (zorunlu, trajik ve) orada evrensel dışarı fonksiyonlarını tespit ayarlayın. MB kütüphanede olanlar yanı sıra iconv içinde olanları dışarı orada bazı şeyler karşılaştırıldığında bile gelişmiş değil. Karakter setleri bir liste üzerinden temelde dolaşır mb_detect_encoding ve elinde geçerli bir görünüme sahiptir dize yapar ilkini döndürür. Bu gün ve yaş olarak bu birkaç () (sipariş mb_detect_order aracılığıyla maruz neden olan) gerçek dönecekti muhtemelen.

Sayfalarınız doğru HTTP & sağlanmaktadır olun HTML karakter bildirimleri ayarlamak ve tarayıcılar aynı verileri dönmelidir. İlave spesifik olmak için form etiketi kabul charset beyanı bulunmaktadır. Ben bir saldırıyı temsil etmedi bu göz ardı edildi olgusunu keşfetmek için henüz ettik.

Bir bayt akışı kodlamasını kontrol etmek için, sadece mb_check_encoding () kullanabilirsiniz.

Performansa dayalı ASCII ve UTF8'den arasında seçim yapma muhtemelen yanlış bir yaklaşımdır. Bu sorunun cevabı gerçekten kullanımı durumda bağlıdır. Lütfen dize uluslararasılaşma destek gerekiyorsa, büyük olasılıkla UTF8'den ile gitmek. Siteniz sadece İngilizce ise, ASCII ile gidebilir. Ya da belki hala UTF8'den ile gitmek. Neyi seçerseniz seçin, muhtemelen size kullanıcı girişi istemek için hizmet HTML formu için belirlenen kodlama karakter eşleşmesi gerekir.

Ben iconv çalıştırmadan önce gerekli görünüyor denetliyor ne yaptığınızı farz ediyorum?

Eğer ASCII olmayan karakterler çok sık tekrarlamasını beklemeyin Eğer en etkili yaklaşım olacak gibi, o is_ascii görünüyor. Iconv yalnızca> 7-bit karakter karşılaşıldı eğer tetiklenebilir gerekir.

Kontrol dizesinde yüksek-bit karakter olması muhtemeldir varsa, o seems_utf8 yüksek bit ancak non-UTF8 karakterleri bir yüksek frekans orada da sürece çok daha az iconv aramak gerekir, daha verimli olabilir.

Sadece onlar sadece UTF-8 kabul böylece girişleri korumak için çalışıyorsanız, ben sadece mb_check_encoding kullanabilirsiniz düşünüyorum. Böyle bir şey:

if(!mb_check_encoding($input, 'UTF-8'){
  die('Non UTF-8 character found');
}

geçersiz giriş reddetmek için yeterli olmalıdır.