idn_to_ascii 和 idn_to_utf8 函数不能正确处理完整的 URL(即包含方案和路径的 URL),因此这里提供了一些辅助函数来处理所有 URL,包括包含路径但没有方案的 URL
<?php
function punycode_encode($url)
{
$no_scheme = false;
if (!preg_match('/^.+?:\/\//', $url) && substr($url, 0, 2) !== '//') {
$url = '//' . $url;
$no_scheme = true;
}
$parts = parse_url($url);
$out = '';
if (!empty($parts['scheme'])) $out .= $parts['scheme'] . ':';
if (!empty($parts['host'])) $out .= '//';
if (!empty($parts['user'])) $out .= $parts['user'];
if (!empty($parts['pass'])) $out .= ':' . $parts['pass'];
if (!empty($parts['user'])) $out .= '@';
if (!empty($parts['host'])) $out .= idn_to_ascii($parts['host']);
if (!empty($parts['port'])) $out .= ':' . $parts['port'];
if (!empty($parts['path'])) $out .= $parts['path'];
if (!empty($parts['query'])) $out .= '?' . $parts['query'];
if (!empty($parts['fragment'])) $out .= '#' . $parts['fragment'];
if ($no_scheme) {
$out = substr($out, 2);
}
return $out;
}
function punycode_decode($url)
{
$no_scheme = false;
if (!preg_match('/^.+?:\/\//', $url) && substr($url, 0, 2) !== '//') {
$url = '//' . $url;
$no_scheme = true;
}
$parts = parse_url($url);
$out = '';
if (!empty($parts['scheme'])) $out .= $parts['scheme'] . ':';
if (!empty($parts['host'])) $out .= '//';
if (!empty($parts['user'])) $out .= $parts['user'];
if (!empty($parts['pass'])) $out .= ':' . $parts['pass'];
if (!empty($parts['user'])) $out .= '@';
if (!empty($parts['host'])) $out .= idn_to_utf8($parts['host']);
if (!empty($parts['port'])) $out .= ':' . $parts['port'];
if (!empty($parts['path'])) $out .= $parts['path'];
if (!empty($parts['query'])) $out .= '?' . $parts['query'];
if (!empty($parts['fragment'])) $out .= '#' . $parts['fragment'];
if ($no_scheme) {
$out = substr($out, 2);
}
return $out;
}