protected function decodePunycode($encoded)
{
$found = preg_match('/([^a-z0-9\\x2d]{1,10})$/i', $encoded);
if (empty($encoded) || $found > 0) {
// no punycode encoded string, return as is
$this->_error(self::CANNOT_DECODE_PUNYCODE);
return false;
}
$separator = strrpos($encoded, '-');
if ($separator > 0) {
for ($x = 0; $x < $separator; ++$x) {
// prepare decoding matrix
$decoded[] = ord($encoded[$x]);
}
} else {
$this->_error(self::CANNOT_DECODE_PUNYCODE);
return false;
}
$lengthd = count($decoded);
$lengthe = strlen($encoded);
// decoding
$init = true;
$base = 72;
$index = 0;
$char = 0x80;
for ($indexe = $separator ? $separator + 1 : 0; $indexe < $lengthe; ++$lengthd) {
for ($old_index = $index, $pos = 1, $key = 36; 1; $key += 36) {
$hex = ord($encoded[$indexe++]);
$digit = $hex - 48 < 10 ? $hex - 22 : ($hex - 65 < 26 ? $hex - 65 : ($hex - 97 < 26 ? $hex - 97 : 36));
$index += $digit * $pos;
$tag = $key <= $base ? 1 : ($key >= $base + 26 ? 26 : $key - $base);
if ($digit < $tag) {
break;
}
$pos = (int) ($pos * (36 - $tag));
}
$delta = intval($init ? ($index - $old_index) / 700 : ($index - $old_index) / 2);
$delta += intval($delta / ($lengthd + 1));
for ($key = 0; $delta > 910 / 2; $key += 36) {
$delta = intval($delta / 35);
}
$base = intval($key + 36 * $delta / ($delta + 38));
$init = false;
$char += (int) ($index / ($lengthd + 1));
$index %= $lengthd + 1;
if ($lengthd > 0) {
for ($i = $lengthd; $i > $index; $i--) {
$decoded[$i] = $decoded[$i - 1];
}
}
$decoded[$index++] = $char;
}
// convert decoded ucs4 to utf8 string
foreach ($decoded as $key => $value) {
if ($value < 128) {
$decoded[$key] = chr($value);
} elseif ($value < 1 << 11) {
$decoded[$key] = chr(192 + ($value >> 6));
$decoded[$key] .= chr(128 + ($value & 63));
} elseif ($value < 1 << 16) {
$decoded[$key] = chr(224 + ($value >> 12));
$decoded[$key] .= chr(128 + ($value >> 6 & 63));
$decoded[$key] .= chr(128 + ($value & 63));
} elseif ($value < 1 << 21) {
$decoded[$key] = chr(240 + ($value >> 18));
$decoded[$key] .= chr(128 + ($value >> 12 & 63));
$decoded[$key] .= chr(128 + ($value >> 6 & 63));
$decoded[$key] .= chr(128 + ($value & 63));
} else {
$this->_error(self::CANNOT_DECODE_PUNYCODE);
return false;
}
}
return implode($decoded);
}