UTF-8 preg_match kullanmadan PHP doğrulama ()

5 Cevap php

Ben UTF-8 olarak kodlanmış bazı kullanıcı girişlerini doğrulamak gerekir. Birçok aşağıdaki kodu kullanarak tavsiye var:

preg_match('/\A(
     [\x09\x0A\x0D\x20-\x7E]
   | [\xC2-\xDF][\x80-\xBF]
   |  \xE0[\xA0-\xBF][\x80-\xBF]
   | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}
   |  \xED[\x80-\x9F][\x80-\xBF]
   |  \xF0[\x90-\xBF][\x80-\xBF]{2}
   | [\xF1-\xF3][\x80-\xBF]{3}
   |  \xF4[\x80-\x8F][\x80-\xBF]{2}
  )*\z/x', $string);

Bu http://www.w3.org/International/questions/qa-forms-utf-8 alınan bir düzenli ifadedir. Ben $ string çok uzun ise. Preg_match () bir segment hataya neden en azından 2006 yılından bu yana var olmuştur görünüyor PHP bir hata keşfetti kadar her şey tamam oldu. Herhangi bir geçici çözüm var gibi görünüyor değil. Burada hata sunulması görebilirsiniz: http://bugs.php.net/bug.php?id=36463

Şimdi, yukarıdaki düzenli ifade olarak aynı şeyi yapar bir işlevi yarattık preg_match kullanarak önlemek için. Bu soru burada yığın taşması en uygun olup olmadığını bilmiyorum, ama ben yaptığım fonksiyonu doğru olup olmadığını bilmek istiyorum. İşte:

EDIT [13.01.2010]: If anyone is interested, there were several bugs in the previous version I've posted. Below is the final version of my function.

function check_UTF8_string(&$string) {
    $len = mb_strlen($string, "ISO-8859-1");
    $ok = 1;

    for ($i = 0; $i < $len; $i++) {
        $o = ord(mb_substr($string, $i, 1, "ISO-8859-1"));

        if ($o == 9 || $o == 10 || $o == 13 || ($o >= 32 && $o <= 126)) {

        }
        elseif ($o >= 194 && $o <= 223) {
            $i++;
            $o2 = ord(mb_substr($string, $i, 1, "ISO-8859-1"));
            if (!($o2 >= 128 && $o2 <= 191)) {
                $ok = 0;
                break;
            }
        }
        elseif ($o == 224) {
            $o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
            $o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
            $i += 2;
            if (!($o2 >= 160 && $o2 <= 191) || !($o3 >= 128 && $o3 <= 191)) {
                $ok = 0;
                break;
            }
        }
        elseif (($o >= 225 && $o <= 236) || $o == 238 || $o == 239) {
            $o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
            $o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
            $i += 2;
            if (!($o2 >= 128 && $o2 <= 191) || !($o3 >= 128 && $o3 <= 191)) {
                $ok = 0;
                break;
            }
        }
        elseif ($o == 237) {
            $o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
            $o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
            $i += 2;
            if (!($o2 >= 128 && $o2 <= 159) || !($o3 >= 128 && $o3 <= 191)) {
                $ok = 0;
                break;
            }
        }
        elseif ($o == 240) {
            $o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
            $o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
            $o4 = ord(mb_substr($string, $i + 3, 1, "ISO-8859-1"));
            $i += 3;
            if (!($o2 >= 144 && $o2 <= 191) ||
                !($o3 >= 128 && $o3 <= 191) ||
                !($o4 >= 128 && $o4 <= 191)) {
                $ok = 0;
                break;
            }
        }
        elseif ($o >= 241 && $o <= 243) {
            $o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
            $o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
            $o4 = ord(mb_substr($string, $i + 3, 1, "ISO-8859-1"));
            $i += 3;
            if (!($o2 >= 128 && $o2 <= 191) ||
                !($o3 >= 128 && $o3 <= 191) ||
                !($o4 >= 128 && $o4 <= 191)) {
                $ok = 0;
                break;
            }
        }
        elseif ($o == 244) {
            $o2 = ord(mb_substr($string, $i + 1, 1, "ISO-8859-1"));
            $o3 = ord(mb_substr($string, $i + 2, 1, "ISO-8859-1"));
            $o4 = ord(mb_substr($string, $i + 3, 1, "ISO-8859-1"));
            $i += 5;
            if (!($o2 >= 128 && $o2 <= 143) ||
                !($o3 >= 128 && $o3 <= 191) ||
                !($o4 >= 128 && $o4 <= 191)) {
                $ok = 0;
                break;
            }
        }
        else {
            $ok = 0;
            break;
        }
    }

    return $ok;
}

Evet, çok uzun. Ben bu düzenli ifade nasıl çalıştığını doğru anladım umarım. Ayrıca başkalarına yardım olacağını umuyoruz.

Şimdiden teşekkürler!

5 Cevap

Her zaman kullanarak yapabilirsiniz Multibyte String Functions:

Bunu çok kullanmak ve muhtemelen bazen, bunu değiştirmek istiyorsanız:

1) İlk config dosyanızda kullanmak istediğiniz kodlamayı ayarlayın

/* Set internal character encoding to UTF-8 */
mb_internal_encoding("UTF-8");

2) dize edin

if(mb_check_encoding($string))
{
    // do something
}

Bunu değiştirme planı yoksa Yoksa, her zaman sadece düz işlevi kodlama koyabilirsiniz:

if(mb_check_encoding($string, 'UTF-8'))
{
    // do something
}

Sen geçerliliğini denetlemek için iconv kullanmak gerekir. Sadece deneyin ve UTF-16 dönüştürmek ve bir hata alırsanız bakın.

Böyle eski bir konu zaten sabit olmalıdır. Ben İfadelerinin seviyorum ve preg_match (), bazen 200KB daha büyük dizeleri ile dahil, o her zaman kullanın. Onunla sorun yoktu. Bu sadece kolay ayrıştırmak için yolu ve biçimi veri değil, aynı zamanda PHP gibi yorumlanır dil için hızlı bir.

Burada bir dize işlevi tabanlı bir çözümdür:

http://www.php.net/manual/en/function.mb-detect-encoding.php#85294

<?php
function is_utf8($str) {
    $c=0; $b=0;
    $bits=0;
    $len=strlen($str);
    for($i=0; $i<$len; $i++){
        $c=ord($str[$i]);
        if($c > 128){
            if(($c >= 254)) return false;
            elseif($c >= 252) $bits=6;
            elseif($c >= 248) $bits=5;
            elseif($c >= 240) $bits=4;
            elseif($c >= 224) $bits=3;
            elseif($c >= 192) $bits=2;
            else return false;
            if(($i+$bits) > $len) return false;
            while($bits > 1){
                $i++;
                $b=ord($str[$i]);
                if($b < 128 || $b > 191) return false;
                $bits--;
            }
        }
    }
    return true;
}
?>