punycode转换函数

<?

define("punycode_TMIN", 1);
define("punycode_TMAX", 26);
define("punycode_BASE", 36);
define("punycode_INITIAL_N", 128);
define("punycode_INITIAL_BIAS", 72);
define("punycode_DAMP", 700);
define("punycode_SKEW", 38);
define("punycode_DELIMITER", "-");
define("punycode_MAXINT", 2147483647);

// 以下三个是encode编码时候的返回值
define("punycode_bad_input", -1);
define("punycode_big_output", -2);
define("punycode_overflow", -3);

//punycode转换函数 punycode编码
/*
输入的字符传不能有空格.
以.分割几段来进行处理
对中文全角字母不区分大小写
中文字符不能包含@#$%之类的字符
*/
//punycode 编码
function punycode_encode($input, $code = "GBK") {
$input = trim($input);
$input = str_replace("。", ".", $input);
$strarr = array();
$strarr = explode(".", $input);
$output = "";
for ($i = 0; $i < count($strarr); $i++) {
$tmp_output = punycode_encode2($strarr[$i], $code);
if (!$tmp_output || $tmp_output < 0)
return;

if ($i != count($strarr) - 1)
$tmp_output.=".";
$output.=$tmp_output;
}
return $output;
}

//punycode 解码
function punycode_decode($input, $code = "GBK") {
$input = trim($input);
$strarr = array();
$strarr = explode(".", $input);
$output = "";
for ($i = 0; $i < count($strarr); $i++) {
if (substr($strarr[$i], 0, 4) == "xn--") {
$input = substr($strarr[$i], 4);
$outtmp = punycode_decode2($input, $code);

if (!$outtmp || $outtmp < 0)
return;

$output.=$outtmp;
}else {
$output.=$strarr[$i];
}
if ($i != count($strarr) - 1)
$output.=".";
}//for
return $output;
}

//主要的编码转换工作
function punycode_encode2($input, $code = "GBK") {
//$input=str_replace(" "," ",$input);//某些输入法的全角有问题导致不能用iconv转换为Unicode,替换为标准的全角空格
$oldinput = $input;
$input = iconv($code, "Unicode", $input); //将输入字符转换为Unicode.cnnic用GBK,GBK是GB2312的扩展.取代GBK的是GB18030
$input = substr($input, 2); //去掉前面的255和254

$n = punycode_INITIAL_N;
$delta = 0;
$out = 0;
$max_out = 256;
$bias = punycode_INITIAL_BIAS;
$output = "";
$inputlen = strlen($input);
$ar = array(); //用一个数组来保存字的编码
for ($i = 0; $i < $inputlen; $i+=2) {
$tmpar = ord($input{$i + 1}) * 256 + ord($input{$i});
if ($tmpar == 32)
break; //32为空格的Unicode,空格后不作处理(参考cnnic).输入是最好限制输入不能包含空格
$ar[] = $tmpar;
}
$inputlen = count($ar);
for ($i = 0; $i < $inputlen; $i++) {//将大写全角字符转为小写
if ($ar[$i] >= 65313 && $ar[$i] <= 65338)
$ar[$i] = $ar[$i] + 32;
}
//$arr=array();
for ($j = 0; $j < $inputlen; $j++) {
if (punycode_isBasic($ar[$j])) {
if ($max_out - $out < 2)
return punycode_big_output;
//$arr[]=$case_flags ? punycode_encode_basic($input{$j}, $case_flags{$j}) : ord($input{$j});
$output.=$case_flags ? chr(punycode_encode_basic($ar[$j], $case_flags{$j})) : chr($ar[$j]); //不考虑大小写
$out++;
}
}

$h = $b = $out;
if ($b > 0) {
$output.=punycode_DELIMITER;
$out++;
}

while ($h < $inputlen) {
for ($m = punycode_MAXINT, $j = 0; $j < $inputlen; $j++) {
if ($ar[$j] >= $n && $ar[$j] < $m)
$m = $ar[$j];
}

if ($m - $n > (punycode_MAXINT - $delta) / ($h + 1))
return punycode_overflow;
$delta+=($m - $n) * ($h + 1);
$n = $m;

for ($j = 0; $j < $inputlen; $j++) {
if ($ar[$j] < $n) {
if (++$delta == 0)
return punycode_overflow;
}

if ($ar[$j] == $n) {
$q = $delta;
for ($k = punycode_BASE;; $k+=punycode_BASE) {
if ($out >= $max_out)
return punycode_big_output;
$t = $k <= $bias ? punycode_TMIN : ($k >= ($bias + punycode_TMAX) ? punycode_TMAX : ($k - $bias));
if ($q < $t)
break;
//$arr[]=punycode_encode_digit($t+($q-$t)%(punycode_BASE-$t),0);
$output.=chr(punycode_encode_digit($t + ($q - $t) % (punycode_BASE - $t), 0));
$out++;
$q = (int) (($q - $t) / (punycode_BASE - $t));
}

//$arr[]=punycode_encode_digit($q,$case_flags && $case_flags{$j});
//$output.=chr(punycode_encode_digit($q,$case_flags && $case_flags{$j}));
$output.=chr(punycode_encode_digit($q, 0)); //忽略大小写(0输出小写字母,1输出大写字母)
$out++;
$bias = punycode_adapt($delta, $h + 1, $h == $b);
$delta = 0;
$h++;
}
}
$delta++;
$n++;
}
if (substr($output, -1, 1) == punycode_DELIMITER)
$output = substr($output, 0, -1);
if ($output != $oldinput)
$output = "xn--" . $output;
return $output;
}

//编码的参数
function punycode_adapt($delta, $numpoints, $firsttime) {
if ($firsttime)
$delta = (int) ($delta / punycode_DAMP);
else
$delta = (int) ($delta / 2);

$delta+=(int) ($delta / $numpoints);

for ($k = 0; $delta > (int) (((punycode_BASE - punycode_TMIN) * punycode_TMAX) / 2); $k+=punycode_BASE) {
$delta = (int) ($delta / (punycode_BASE - punycode_TMIN));
}
return $k + (int) (((punycode_BASE - punycode_TMIN + 1) * $delta) / ($delta + punycode_SKEW));
}

//处理数字,大小写字母
function punycode_encode_basic($bcp, $flag) {
//if ($bcp-97<26) $bcp-=32;
$bcp-=($bcp - 97 < 26) << 5;
return $bcp + ((!$flag && ($bcp - 65 < 26)) << 5);
}

//判断数字是否是ansi字符,禁止 @#$%^ 之类的符号
function punycode_isBasic($c) {
return $c < 128;
//return $aa=(($c==45) || ($c>=48 && $c<=57) || ($c>=65 && $c<=90) || ($c>=97 && $c<=122));
}

//处理数字,大小写字母
function punycode_decode_digit($c) {
if (($c - 48) < 10)
return ($c - 22);
if (($c - 65) < 26)
return ($c - 65);
if (($c - 97) < 26)
return ($c - 97);
return punycode_BASE;
}

//处理数字,大小写字母
function punycode_encode_digit($d, $flag) {
$s1 = (int) ($d < 26); //0或1
$s2 = (int) ($flag != 0);
return $d + 22 + 75 * $s1 - ($s2 << 5);
}

//主要的解码转换工作
function punycode_decode2($input, $code = "GBK") {
$n = punycode_INITIAL_N;
$out = 0;
$i = 0;
$max_out = 256;
$bias = punycode_INITIAL_BIAS;
$inputlen = strlen($input);
$outputa = array();

$b = 0;
for ($j = 0; $j < $inputlen; $j++)
if ($input{$j} == "-")
$b = $j;


for ($j = 0; $j < $b; $j++) {
/* 不考虑大小写
if (ord($input{$j})-65<26)
$case_flags[$out]="1";
else
$case_flags[$out]="0";
*/
if (ord($input{$j}) > 128)
return -1;
//$output.=$input{$j};
$outputa[] = ord($input{$j});
$out++;
}


for ($in = $b > 0 ? $b + 1 : 0; $in < $inputlen; $out++) {
$oldi = $i;
$w = 1;
for ($k = punycode_BASE;; $k+=punycode_BASE) {
if ($in >= $inputlen)
return -2;
$digit = punycode_decode_digit(ord($input{$in++}));
if ($digit >= punycode_BASE)
return -3;
if ($digit > (punycode_MAXINT - $i) / $w)
return -4;
$i = $i + $digit * $w;
$t = $k <= $bias ? punycode_TMIN : ($k >= ($bias + punycode_TMAX) ? punycode_TMAX : ($k - $bias));
if ($digit < $t)
break;
if ($w > punycode_MAXINT / (punycode_BASE - $t))
return -5;
$w = $w * (punycode_BASE - $t);
}

$bias = punycode_adapt($i - $oldi, $out + 1, $oldi == 0);
if ($i / ($out + 1) > punycode_MAXINT - $n)
return -6;
$n+=(int) ($i / ($out + 1));
$i = $i % ($out + 1);


if ($out >= $max_out)
return -7;

/* 不考虑大小写
for ($q=0;$q<$out-$i;$i++) $case_flags[$i+1+$q]= $case_flags[$i+$q];

if ($input[$in-1]-65<26)
$case_flags[$i]='1';
else
$case_flags[$i]='0';
*/
for ($qq = 0; $qq < ($out - $i); $qq++)
$outputa[($i + $out) - $i - $qq] = $outputa[($i + $out) - $i - $qq - 1];

$outputa[$i++] = $n;
}

$outputstr = "";
for ($i = 0; $i < count($outputa); $i++) {
if ($outputa[$i] < 128)
$outputstr.=chr($outputa[$i]);
else {
$hx = dechex($outputa[$i]);
$gaowei = substr($hx, 2, 2);
$diwei = substr($hx, 0, 2);
$tmp_output = chr(hexdec($gaowei)) . chr(hexdec($diwei));
$tmp_output = iconv("Unicode", $code, $tmp_output);
$outputstr.=$tmp_output;
}
}
return $outputstr;
}

?>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值