2013-01-14 12 views
7

Chcę potwierdzić adres domeny w PHP, które mogą być w formacie umiędzynarodowionego nazwy domeny jak w greckiej nazwy domeny = http: //παράδειγμα.δοκιμή Czy ich sposób, aby potwierdzić go za pomocą regularnych wyrażenie?jak potwierdzić internationalized domain name

+1

„Sprawdź poprawność”, jak w „sprawdzić, czy jest to dopuszczalne dla DNS” (awarie byłoby dość rzadko) lub jak w „sprawdzić, czy rzeczywiście istnieje w DNS” (awarie byłyby powszechne, biorąc pod uwagę wejście losowe). – tripleee

+0

Co jest ważne? Czy jest to po prostu 'http: //', po którym następują niektóre znaki, a następnie '.' i kilka znaków? –

+0

Chcę tylko sprawdzić, czy DNS jest ważny, czy nie. Czy istnieje regex, który może mi pomóc tutaj. Adres URL może zawierać znaki z innych języków, takich jak niemiecki. na przykład yĘhoo.com. Używam tego wyrażenia regularnego, ale nie będzie działać tylko dla znaków alfanumerycznych./^ [a-z \ d] [a-z \ d -] {0,62} $/i. W jaki sposób mogę utworzyć wyrażenie regularne, które również przyjmuje postać z innych języków, – user1969981

Odpowiedz

2

To są domeny idn, najpierw zamieniłbym je na domeny puny code i validate domen.

Ale jeśli naprawdę chcesz, aby sprawdzić poprawność przez regex

<?php 

$domain = 'παράδειγμα.gr'; 
$regex = '#^([\w-]+://?|www[\.])?([^\-\s\,\;\:\+\/\\\?\^\`\=\&\%\"\'\*\#\<\>]*)\.[a-z]{2,7}$#'; 
if (preg_match($regex, $domain)) { 
    echo "VALID"; 
} 

Ale to pozwolić uruchomić fałszywych possitives, bo to jest naprawdę skomplikowane, aby zweryfikować domenę IDN tryed, aby potwierdzić, że nie ma nieprawidłowe znaki są wewnątrz, ale lista NIE jest kompletna.

lepiej konwertować bevore kodu punny

$regex = '#^([\w-]+://?|www[\.])?[a-z0-9]+[a-z0-9\-\.]*[a-z0-9]+\.[a-z]{2,7}$#'; 
if (preg_match($regex, idn_to_ascii($domain))) { 
    echo "VALID"; 
} 

A jeśli dodatkowy chcą sprawdzić, czy domena może być rozwiązany spróbować:

$regex = '#^([\w-]+://?|www[\.])?[a-z0-9]+[a-z0-9\-\.]*[a-z0-9]+\.[a-z]{2,7}$#'; 
$punny_domain = idn_to_ascii($domain); 
if (preg_match($regex, $punny_domain)) { 
    if (gethostbyname($punny_domain) != $punny_domain) { 
     echo "VALID"; 
    } 
} 
1

Jest to tzw IDN domain. Klienci obsługujący domeny IDN normalizują je przy użyciu standardu IDNA2008 określonego w RFC 5890, a następnie zastępują pozostałe znaki Unicode przy użyciu kodowania Punycode zgodnie z definicją w RFC 3492 przed przesłaniem w celu rozpoznawania nazw DNS.

Zgodnie ze specyfikacją, każdy znak w zestawie znaków UTF-8 może być używany w domenie IDN, ale każdy organ domeny najwyższego poziomu może definiować prawidłowe znaki w zestawie znaków Unicode, więc trudno będzie uzyskać create and maintain a real regex.

Jeśli chcesz akceptować domeny IDN w swojej aplikacji, powinieneś wewnętrznie pracować z zakodowaną wersją. PHP extension intl daje dwie funkcje en- i dekodowania IDN domen

echo idn_to_ascii('täst.de'); 

xn--tst-qla.de

po kodowaniu, domena będzie przechodzić każdy traditional regex check

prosty sprawdzanie poprawności:

$url = "http://example.com/"; 
if (preg_match('/^(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i', $url)) { 
    echo 'OK'; 
} else { 
    echo 'Invalid URL.'; 
} 

EDIT:

Jeśli chcesz prawdziwego DNS verfification można użyć dns_get_record (PHP 5) lub gethostbyaddr

przykład

$domain = 'ελληνικά.idn.icann.org'; 
$idnDomain = idn_to_ascii($domain); 

if ($dnsResult = dns_get_record($idnDomain, DNS_ANY)) 
{ 
    echo $idnDomain , "\n"; 
    print_r($dnsResult); 
} 
else 
{ 
    echo "failed to lookup domain\n"; 
} 

Wynik:

xn--hxargifdar.idn.icann.org 
Array 
(
    [0] => Array 
    (
     [host] => xn--hxargifdar.idn.icann.org 
     [class] => IN 
     [ttl] => 21456 
     [type] => A 
     [ip] => 199.7.85.10 
    ) 
    [1] => Array 
    (
     [host] => xn--hxargifdar.idn.icann.org 
     [class] => IN 
     [ttl] => 21600 
     [type] => AAAA 
     [ipv6] => 2620::2830:230:0:0:0:10 
    ) 
) 
+2

I * think * Znalazłem * ważny * błąd w twojej odpowiedzi. Mówisz: 'Według specyfikacji, dosłownie każdy znak w zestawie znaków UTF-8 jest prawidłowy do użycia w domenie IDN' (podczas gdy mówisz o IDNA2008 i RFC5890). * JEDNAK * (w moim rozumieniu), IDNA2008 teraz 'nie dopuszcza około ośmiu tysięcy znaków, które były ważne, w tym wszystkie wielkie litery, warianty pełne, pół szerokości, symbole i znaki interpunkcyjne' (wcześniej dozwolone w IDNA2003 iw tej chwili nadal praca w większości wdrożeń). Zobacz http://www.unicode.org/faq/idn.html i http://tools.ietf.org/html/rfc5892. Czy błędnie go przeczytałem? – GitaarLAB

+1

@Gitaar dzięki, tak masz rację. Jest to dla mnie nowe, ale ma absolutnie sens, ponieważ nazwy domen nie uwzględniają wielkości liter, a znaki interpunkcyjne mogą być zastrzeżone (np. Ogranicznik domeny "kropka", ogranicznik ciągu zapytania "?" –

2

Jeśli chcesz stworzyć swój własny libirary, trzeba użyć tabeli dozwolonych codepoints (IANA — Repository of IDN Practices, IDN Character Validation Guidance, IDNA Parameters) oraz tabelę właściwości skryptów Unicode (UNIDATA/Scripts.txt).

Gmail przyjmuje specyfikację "Unileode Consortium" "H ighly Restricted" (Protecting Gmail in a global world). Następujące kombinacje skryptów Unicode są dozwolone.

  • pojedynczy skrypt
  • łaciński + Han + hiragana + katakana
  • łaciński + Han + bopomofo
  • łaciński + Han + hangyl

może trzeba zapłacić attension szczególnej właściwości skryptu wartości (Common, Inherited, Unknown), ponieważ niektóre znaki mają wiele właściwości lub są niepoprawne.

Na przykład U + 3099 (ŁĄCZENIE KATAKANA-HIRAGANA Z GWARANCJĄ DŹWIĘKU WIZOWEGO) ma dwa dokumenty ("Katakana" i "Hiragana"), a funkcja PCRE klasyfikuje je jako "Odziedziczone". Innym przykładem jest U + x2A708. Althogh właściwą własnością skryptu U + 2A708 (połączenie U + 30C8 KATAKANA LETTER TO i U + 30E2 KATAKANA LIST MO) jest "Katakana", Specyfikacja Unicode błędnie klasyfikuje ją jako "Han". Może być konieczne rozważenie IDN homograph attack. Google Chrome IDN policy przyjmuje the blacklist chars.

Moja rekomendacja to użycie Zend \ Validator \ Nazwa hosta. Ta biblioteka używa języka the table of permitted code points w języku japońskim i chińskim.

Jeśli używasz Symfony, rozważ uaktualnienie aplikacji do wersji 2.5, która przyjmuje egulias/email-validatornd (Manual). Potrzebujesz dodatkowej weryfikacji, czy łańcuch jest dobrze uformowaną sekwencją bajtów. Zobacz mój numer report a>, aby uzyskać szczegółowe informacje.

Nie zapomnij o iniekcji XSS i SQL. Następujący adres jest prawidłowym adresem e-mail opartym na RFC5322.

// From Japanese tutorial 
// http://blog.tokumaru.org/2013/11/xsssqlrfc5322.html 
"><script>alert('or/**/1=1#')</script>"@example.jp 

myślę, że to wątpliwe za korzystanie idn_to_ascii walidacji od idn_to_ascii przechodzi prawie wszystkie znaki.

for ($i = 0; $i < 0x110000; ++$i) { 
    $c = utf8_chr($i); 

    if ($c !== '' && false !== idn_to_ascii($c)) { 
     $number = strtoupper(dechex($i)); 
     $length = strlen($number); 

     if ($i < 0x10000) { 
      $number = str_repeat('0', 4 - $length).$number; 
     } 

     $idn = $c.'example.com'; 

     echo 'U+'.$number.' '; 
     echo ' '.$idn.' '. idn_to_ascii($idn); 
     echo PHP_EOL; 
    } 
} 

function utf8_chr($code_point) { 

    if ($code_point < 0 || 0x10FFFF < $code_point || (0xD800 <= $code_point && $code_point <= 0xDFFF)) { 
     return ''; 
    } 

    if ($code_point < 0x80) { 
     $hex[0] = $code_point; 
     $ret = chr($hex[0]); 
    } else if ($code_point < 0x800) { 
     $hex[0] = 0x1C0 | $code_point >> 6; 
     $hex[1] = 0x80 | $code_point & 0x3F; 
     $ret = chr($hex[0]).chr($hex[1]); 
    } else if ($code_point < 0x10000) { 
     $hex[0] = 0xE0 | $code_point >> 12; 
     $hex[1] = 0x80 | $code_point >> 6 & 0x3F; 
     $hex[2] = 0x80 | $code_point & 0x3F; 
     $ret = chr($hex[0]).chr($hex[1]).chr($hex[2]); 
    } else { 
     $hex[0] = 0xF0 | $code_point >> 18; 
     $hex[1] = 0x80 | $code_point >> 12 & 0x3F; 
     $hex[2] = 0x80 | $code_point >> 6 & 0x3F; 
     $hex[3] = 0x80 | $code_point & 0x3F; 
     $ret = chr($hex[0]).chr($hex[1]).chr($hex[2]).chr($hex[3]); 
    } 

    return $ret; 
} 

Aby sprawdzić poprawność domeny za pomocą właściwości skryptu Unicode, należy użyć funkcji PCRE.

Poniższy kod pokazuje, w jaki sposób uzyskać nazwę właściwości skryptu Unicode. Jeśli chcesz sprawdzić w Perpicterze skryptu Unicode w JavaScript, użyj mathiasbynens/unicode-data.

function get_unicode_script_name($c) { 

    // http://php.net/manual/regexp.reference.unicode.php 
    $names = [ 
    'Arabic', 'Armenian', 'Avestan', 'Balinese', 'Bamum', 'Batak', 'Bengali', 
    'Bopomofo', 'Brahmi', 'Braille', 'Buginese', 'Buhid', 'Canadian_Aboriginal', 
    'Carian', 'Chakma', 'Cham', 'Cherokee', 'Common', 'Coptic', 'Cuneiform', 
    'Cypriot', 'Cyrillic', 'Deseret', 'Devanagari', 'Egyptian_Hieroglyphs', 
    'Ethiopic', 'Georgian', 'Glagolitic', 'Gothic', 'Greek', 'Gujarati', 
    'Gurmukhi', 'Han', 'Hangul', 'Hanunoo', 'Hebrew', 'Hiragana', 'Imperial_Aramaic', 
    'Inherited', 'Inscriptional_Pahlavi', 'Inscriptional_Parthian', 'Javanese', 
    'Kaithi', 'Kannada', 'Katakana', 'Kayah_Li', 'Kharoshthi', 'Khmer', 'Lao', 'Latin', 
    'Lepcha', 'Limbu', 'Linear_B', 'Lisu', 'Lycian', 'Lydian', 'Malayalam', 'Mandaic', 
    'Meetei_Mayek', 'Meroitic_Cursive', 'Meroitic_Hieroglyphs', 'Miao', 'Mongolian', 
    'Myanmar', 'New_Tai_Lue', 'Nko', 'Ogham', 'Old_Italic', 'Old_Persian', 
    'Old_South_Arabian', 'Old_Turkic', 'Ol_Chiki', 'Oriya', 'Osmanya', 'Phags_Pa', 
    'Phoenician', 'Rejang', 'Runic', 'Samaritan', 'Saurashtra', 'Sharada', 'Shavian', 
    'Sinhala', 'Sora_Sompeng', 'Sundanese', 'Syloti_Nagri', 'Syriac', 'Tagalog', 
    'Tagbanwa', 'Tai_Le', 'Tai_Tham', 'Tai_Viet', 'Takri', 'Tamil', 'Telugu', 'Thaana', 
    'Thai', 'Tibetan', 'Tifinagh', 'Ugaritic', 'Vai', 'Yi' 
    ]; 

    $ret = []; 

    foreach ($names as $name) { 

    $pattern = '/\p{'.$name.'}/u'; 

    if (preg_match($pattern, $c)) { 
     return $name; 
    } 
    } 

    return ''; 
}