| 1 |
<?php defined('ABSPATH') or die("Protected By WT!"); |
| 2 |
|
| 3 |
final class WTSEC_LIBRARY_Idn |
| 4 |
{ |
| 5 |
private static $decodeTable = array( |
| 6 |
'a' => 0, 'b' => 1, 'c' => 2, 'd' => 3, 'e' => 4, 'f' => 5, |
| 7 |
'g' => 6, 'h' => 7, 'i' => 8, 'j' => 9, 'k' => 10, 'l' => 11, |
| 8 |
'm' => 12, 'n' => 13, 'o' => 14, 'p' => 15, 'q' => 16, 'r' => 17, |
| 9 |
's' => 18, 't' => 19, 'u' => 20, 'v' => 21, 'w' => 22, 'x' => 23, |
| 10 |
'y' => 24, 'z' => 25, '0' => 26, '1' => 27, '2' => 28, '3' => 29, |
| 11 |
'4' => 30, '5' => 31, '6' => 32, '7' => 33, '8' => 34, '9' => 35, |
| 12 |
); |
| 13 |
public static function idn_to_utf8($domain) |
| 14 |
{ |
| 15 |
$domain = mb_strtolower($domain); |
| 16 |
$parts = explode('.', $domain); |
| 17 |
foreach ($parts as &$part) { |
| 18 |
$length = \strlen($part); |
| 19 |
if ($length < 1 || 63 < $length) { |
| 20 |
continue; |
| 21 |
} |
| 22 |
if (0 !== strpos($part, 'xn--')) { |
| 23 |
continue; |
| 24 |
} |
| 25 |
$part = substr($part, 4); |
| 26 |
$part = self::decodePart($part); |
| 27 |
} |
| 28 |
$output = implode('.', $parts); |
| 29 |
return \strlen($output) > 255 ? false : mb_strtolower($output); |
| 30 |
} |
| 31 |
private static function calculateThreshold($k, $bias) |
| 32 |
{ |
| 33 |
if ($k <= $bias + 1) { |
| 34 |
return 1; |
| 35 |
} |
| 36 |
if ($k >= $bias + 26) { |
| 37 |
return 26; |
| 38 |
} |
| 39 |
return $k - $bias; |
| 40 |
} |
| 41 |
private static function adapt($delta, $numPoints, $firstTime) |
| 42 |
{ |
| 43 |
$delta = (int) ($firstTime ? $delta / 700 : $delta / 2); |
| 44 |
$delta += (int) ($delta / $numPoints); |
| 45 |
$k = 0; |
| 46 |
while ($delta > 35 * 13) { |
| 47 |
$delta = (int) ($delta / 35); |
| 48 |
$k = $k + 36; |
| 49 |
} |
| 50 |
return $k + (int) (36 * $delta / ($delta + 38)); |
| 51 |
} |
| 52 |
private static function decodePart($input) |
| 53 |
{ |
| 54 |
$n = 128; |
| 55 |
$i = 0; |
| 56 |
$bias = 72; |
| 57 |
$output = ''; |
| 58 |
$pos = strrpos($input, '-'); |
| 59 |
if (false !== $pos) { |
| 60 |
$output = substr($input, 0, $pos++); |
| 61 |
} else { |
| 62 |
$pos = 0; |
| 63 |
} |
| 64 |
$outputLength = \strlen($output); |
| 65 |
$inputLength = \strlen($input); |
| 66 |
while ($pos < $inputLength) { |
| 67 |
$oldi = $i; |
| 68 |
$w = 1; |
| 69 |
for ($k = 36;; $k += 36) { |
| 70 |
$digit = self::$decodeTable[$input[$pos++]]; |
| 71 |
$i += $digit * $w; |
| 72 |
$t = self::calculateThreshold($k, $bias); |
| 73 |
if ($digit < $t) { |
| 74 |
break; |
| 75 |
} |
| 76 |
$w *= 36 - $t; |
| 77 |
} |
| 78 |
$bias = self::adapt($i - $oldi, ++$outputLength, 0 === $oldi); |
| 79 |
$n = $n + (int) ($i / $outputLength); |
| 80 |
$i = $i % $outputLength; |
| 81 |
$output = mb_substr($output, 0, $i, 'utf-8').mb_chr($n, 'utf-8').mb_substr($output, $i, $outputLength - 1, 'utf-8'); |
| 82 |
++$i; |
| 83 |
} |
| 84 |
return $output; |
| 85 |
} |
| 86 |
} |
| 87 |
if (!function_exists('mb_chr')) { |
| 88 |
function mb_chr($ord, $encoding = 'UTF-8') { |
| 89 |
if ($encoding === 'UCS-4BE') { |
| 90 |
return pack("N", $ord); |
| 91 |
} else { |
| 92 |
return mb_convert_encoding(mb_chr($ord, 'UCS-4BE'), $encoding, 'UCS-4BE'); |
| 93 |
} |
| 94 |
} |
| 95 |
} |
| 96 |
if (!function_exists('mb_convert_encoding')) { |
| 97 |
function mb_convert_encoding($str, $to_encoding, $from_encoding = NULL) { |
| 98 |
return iconv(($from_encoding === NULL) ? mb_internal_encoding() : $from_encoding, $to_encoding, $str); |
| 99 |
} |
| 100 |
} |