49 private static $encodeTable = array(
50 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
51 'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
52 'y',
'z',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
55 private static $decodeTable = array(
56 'a' => 0,
'b' => 1,
'c' => 2,
'd' => 3,
'e' => 4,
'f' => 5,
57 'g' => 6,
'h' => 7,
'i' => 8,
'j' => 9,
'k' => 10,
'l' => 11,
58 'm' => 12,
'n' => 13,
'o' => 14,
'p' => 15,
'q' => 16,
'r' => 17,
59 's' => 18,
't' => 19,
'u' => 20,
'v' => 21,
'w' => 22,
'x' => 23,
60 'y' => 24,
'z' => 25,
'0' => 26,
'1' => 27,
'2' => 28,
'3' => 29,
61 '4' => 30,
'5' => 31,
'6' => 32,
'7' => 33,
'8' => 34,
'9' => 35,
64 public static function idn_to_ascii($domain, $options, $variant, &$idna_info = array())
66 if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) {
67 @trigger_error(
'idn_to_ascii(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED);
70 if (self::INTL_IDNA_VARIANT_UTS46 === $variant) {
71 $domain = mb_strtolower($domain,
'utf-8');
74 $parts = explode(
'.', $domain);
76 foreach ($parts as $i => &$part) {
77 if (
'' === $part && \count($parts) > 1 + $i) {
80 if (
false === $part = self::encodePart($part)) {
85 $output = implode(
'.', $parts);
88 'result' => \strlen($output) > 255 ?
false : $output,
89 'isTransitionalDifferent' =>
false,
93 return $idna_info[
'result'];
96 public static function idn_to_utf8($domain, $options, $variant, &$idna_info = array())
98 if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) {
99 @trigger_error(
'idn_to_utf8(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED);
102 $parts = explode(
'.', $domain);
104 foreach ($parts as &$part) {
105 $length = \strlen($part);
106 if ($length < 1 || 63 < $length) {
109 if (0 !== strpos($part,
'xn--')) {
113 $part = substr($part, 4);
114 $part = self::decodePart($part);
117 $output = implode(
'.', $parts);
120 'result' => \strlen($output) > 255 ?
false : $output,
121 'isTransitionalDifferent' =>
false,
125 return $idna_info[
'result'];
128 private static function encodePart($input)
130 if (\substr($input, 0, 1) ===
'-' || \substr($input, -1) ===
'-') {
134 $codePoints = self::listCodePoints($input);
139 $h = $b = \count($codePoints[
'basic']);
142 foreach ($codePoints[
'basic'] as $code) {
143 $output .= mb_chr($code,
'utf-8');
145 if ($input === $output) {
152 $codePoints[
'nonBasic'] = array_unique($codePoints[
'nonBasic']);
153 sort($codePoints[
'nonBasic']);
156 $length = mb_strlen($input,
'utf-8');
157 while ($h < $length) {
158 $m = $codePoints[
'nonBasic'][$i++];
159 $delta += ($m - $n) * ($h + 1);
162 foreach ($codePoints[
'all'] as $c) {
163 if ($c < $n || $c < 128) {
168 for ($k = 36;; $k += 36) {
169 $t = self::calculateThreshold($k, $bias);
174 $code = $t + (($q - $t) % (36 - $t));
175 $output .= self::$encodeTable[$code];
177 $q = ($q - $t) / (36 - $t);
180 $output .= self::$encodeTable[$q];
181 $bias = self::adapt($delta, $h + 1, ($h === $b));
191 $output =
'xn--'.$output;
193 return \strlen($output) < 1 || 63 < \strlen($output) ? false : strtolower($output);
196 private static function listCodePoints($input)
201 'nonBasic' => array(),
204 $length = mb_strlen($input,
'utf-8');
205 for ($i = 0; $i < $length; ++$i) {
206 $char = mb_substr($input, $i, 1,
'utf-8');
207 $code = mb_ord($char,
'utf-8');
209 $codePoints[
'all'][] = $codePoints[
'basic'][] = $code;
211 $codePoints[
'all'][] = $codePoints[
'nonBasic'][] = $code;
218 private static function calculateThreshold($k, $bias)
220 if ($k <= $bias + 1) {
223 if ($k >= $bias + 26) {
230 private static function adapt($delta, $numPoints, $firstTime)
232 $delta = (int) ($firstTime ? $delta / 700 : $delta / 2);
233 $delta += (int) ($delta / $numPoints);
236 while ($delta > 35 * 13) {
237 $delta = (int) ($delta / 35);
241 return $k + (int) (36 * $delta / ($delta + 38));
244 private static function decodePart($input)
251 $pos = strrpos($input,
'-');
252 if (
false !== $pos) {
253 $output = substr($input, 0, $pos++);
258 $outputLength = \strlen($output);
259 $inputLength = \strlen($input);
261 while ($pos < $inputLength) {
265 for ($k = 36;; $k += 36) {
266 $digit = self::$decodeTable[$input[$pos++]];
268 $t = self::calculateThreshold($k, $bias);
277 $bias = self::adapt($i - $oldi, ++$outputLength, 0 === $oldi);
278 $n = $n + (int) ($i / $outputLength);
279 $i = $i % $outputLength;
280 $output = mb_substr($output, 0, $i,
'utf-8').mb_chr($n,
'utf-8').mb_substr($output, $i, $outputLength - 1,
'utf-8');