解析php中的escape函数
<a href="" onclick="window.open('product_list.php?p_sort='+escape(''));">这样点击链接后的效时:
引⽤:127.0.0.1/shop/product_list.php?p_sort=PHP%u5F00%u53D1%u8D44%u6E90%u7F51
⽣成了这样的效果, 很明显⽤PHP的urldecode()或者base64_decode()是⽆法反解的。
复制代码代码如下:
function js_unescape($str){
$ret = '';
$len = strlen($str);
for ($i = 0; $i < $len; $i++)
{
if ($str[$i] == '%' && $str[$i+1] == 'u')
{
$val = hexdec(substr($str, $i+2, 4));
if ($val < 0x7f) $ret .= chr($val);
else if($val < 0x800) $ret .= chr(0xc0|($val>>6)).chr(0x80|($val&0x3f)); else $ret .= chr(0xe0|
($val>>12)).chr(0x80|(($val>>6)&0x3f)).chr(0x80|($val&0x3f));
$i += 5;
}
else if ($str[$i] == '%')
{
$ret .= urldecode(substr($str, $i, 3));
$i += 2;
}
else $ret .= $str[$i];
}
return $ret;}
注意JS编码会⾃动转换成为UTF-8, 所以必须进⾏编码转换才能得到正确的结果,否则会中⽂乱码。但如果使⽤UTF-8编码就不⽤这⼀步了。
代码如下:print iconv('utf-8', 'gb2312', js_unescape($_REQUEST['p_sort']));
到此我们就成功地反解了js的escape编码了。
如下:
另外我到个⽤PHP实现js的escape编码的函数:
复制代码代码如下:
function phpescape($str)
{
$sublen=strlen($str);
$retrunString="";
for ($i=0;$i<$sublen;$i++)
{
if(ord($str[$i])>=127)
{
$tmpString=bin2hex(iconv("gb2312","ucs-2",substr($str,$i,2)));
//$tmpString=substr($tmpString,2,2).substr($tmpString,0,2);window下可能要打开此项
$retrunString.="%u".$tmpString;
$i++;
} else
{
$retrunString.="%".dechex(ord($str[$i]));
}
}
return $retrunString;
}
在json中不⽀持中⽂,⽤它传送中⽂数据就会出现数据丢失或者乱码,必须在传送前对要发送的字符串进⾏编码,由于传送过去需要⽤js进⾏数据解析,考虑到js中有unescape函数,故若在php中有个escape函数,对数据进⾏编码,在客户端⽤unescape进⾏解码,这样就会⽅便很多。
先在⽹上搜索⼀把,很多⽤php实现的escape函数,⼤同⼩异,⽐如下⾯⼀个:
复制代码代码如下:
function phpEscape($str) {
preg_match_all("/[ 80- ff].|[ 01- 7f]+/",$str,$r);
$ar = $r[0];
foreach($ar as $k=>$v) {
if(ord($v[0]) < 128)
$ar[$k] = rawurlencode($v);
else
$ar[$k] = "%u".bin2hex(iconv("GB2312","UCS-2",$v));
}
return join("",$ar);
}
这个函数可以很好的⼯作,但是,也许有新⼿不理解这个函数的原理(⽐如我),⽤起来总是不放⼼,现在我就来解释⼀下这个函数的原理。⽽且我认为,拿别⼈的代码来复⽤,好⽐站在了巨⼈的肩膀上,但是若不理解别⼈的代码,迟早要掉到地⾯上。preg_match_all("/[ 80- ff].|[ 01- 7f]+/",$str,$r);这个是⽤正则表达式匹配字符串中所有的字符,[ 80- ff]. 匹配的是汉字,表⽰匹配字符的16进制编码,[ ] 是类选择符,“.” 表⽰任意⼀个字符,这样[ 80- ff].匹配的是两个字符,其中第⼀个就是16进制从80到ff的字符,⽽这恰好就是汉字编码的第⼀个字符。这样就能完整的匹配⼀个汉字。关于unicode中汉字的编码,⼤家可以到⽹上搜索⼀下。同理,[ 01- 7f]+英⽂字符串,因为最早的英⽂是 ASCII编码,编码值⼩于128,也就是16进制的从01到7f,"+"表⽰⼀个或者多个字符,这样[ 01- 7f]+就能匹配连续多个英⽂字符串。
复制代码代码如下:
$ar = $r[0]; //$r[0]⾥存放是匹配到的数组
foreach($ar as $k=>$v) {
if(ord($v[0]) < 128) //假如字符编码值⼩于128,说明是个英⽂字符
$ar[$k] = rawurlencode($v); //直接⽤rawurlencode编码
else
$ar[$k] = "%u".bin2hex(iconv("GB2312","UCS-2",$v)); //否则的话⽤iconv函数把汉字转变成ucs-2编码,也就是unicode 编码
}
在javascript中就可以⽤unescape来解码了
\u0391-\uFFE5 和\u4e00-\u9fa5来匹配中⽂
但好像前者包含汉字下的A-¥等后者可能是纯汉字。
其中解码函数为:
复制代码代码如下:
function unescape($str) {
$str = rawurldecode($str);
preg_match_all("/%u.{4}|&#x.{4};|&#\d+;|.+/U",$str,$r);
$ar = $r[0];
foreach($ar as $k=>$v) {
if(substr($v,0,2) == "%u")
$ar[$k] = iconv("UCS-2","GBK",pack("H4",substr($v,-4)));
elseif(substr($v,0,3) == "&#x")
$ar[$k] = iconv("UCS-2","GBK",pack("H4",substr($v,3,-1)));
elseif(substr($v,0,2) == "&#") {
$ar[$k] = iconv("UCS-2","GBK",pack("n",substr($v,2,-1)));
}
}
return join("",$ar);
}
字符串函数php00- ff GBK双字节编码范围
20- 7f ASCII
a1- ff 中⽂
80- ff 中⽂
\u4e00-\u9fa5 (中⽂)
3130- 318F (韩⽂
AC00- D7A3 (韩⽂)
\u0800-\u4e00 (⽇⽂)
ps: 韩⽂是⼤于[\u9fa5]的字符
preg_replace("/([ 80- ff])/","",$str);
preg_replace("/([u4e00-u9fa5])/","",$str);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论