解析php中的escape函数


Posted in PHP onJune 29, 2013

采用js对URL中的汉字进行escape编码。
<a href="" onclick="window.open('product_list.php?p_sort='+escape('三水点靠木'));">这样点击链接后的效时:
引用:http://127.0.0.1/shop/product_list.php?p_sort=PHP%u5F00%u53D1%u8D44%u6E90%u7F51
生成了这样的效果, 很明显用PHP的urldecode()或者base64_decode()是无法反解的。
解决方法, 用PHP写一个反解函数:

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("/[\x80-\xff].|[\x01-\x7f]+/",$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("/[\x80-\xff].|[\x01-\x7f]+/",$str,$r);这个是用正则表达式匹配 字符串中所有的字符,[\x80-\xff]. 匹配的是汉字,\x表示匹配字符的16进制编码,[ ] 是类选择符,“.” 表示任意一个字符,这样[\x80-\xff].匹配的是两个字符,其中第一个就是16进制从80到ff的字符,而这恰好就是汉字编码的第一个字符。这样 就能完整的匹配一个汉字。关于unicode中汉字的编码,大家可以到网上搜索一下。同理,[\x01-\x7f]+英文字符串,因为最早的英文是 ASCII编码,编码值小于128,也就是16进制的从01到7f,"+"表示一个或者多个字符,这样[\x01-\x7f]+就能匹配连续多个英文字符 串。
$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);
}

一、编码范围
1. GBK (GB2312/GB18030)
\x00-\xff   GBK双字节编码范围
\x20-\x7f   ASCII
\xa1-\xff   中文
\x80-\xff   中文
2. UTF-8 (Unicode)
\u4e00-\u9fa5 (中文)
\x3130-\x318F (韩文
\xAC00-\xD7A3 (韩文)
\u0800-\u4e00 (日文)
ps: 韩文是大于[\u9fa5]的字符
正则例子:
preg_replace("/([\x80-\xff])/","",$str);
preg_replace("/([u4e00-u9fa5])/","",$str);
PHP 相关文章推荐
Win2003服务器安全加固设置--进一步提高服务器安全性
May 23 PHP
php gzip压缩输出的实现方法
Apr 27 PHP
php后门URL的防范
Nov 12 PHP
理解PHP中的stdClass类
Apr 18 PHP
给WordPress的编辑后台添加提示框的代码实例分享
Dec 25 PHP
深入解析PHP的Yii框架中的缓存功能
Mar 29 PHP
thinkPHP内置字符串截取函数用法详解
Nov 15 PHP
thinkphp实现分页显示功能
Dec 03 PHP
PHP实现图的邻接矩阵表示及几种简单遍历算法分析
Nov 24 PHP
PHP封装的非对称加密RSA算法示例
May 28 PHP
多个Laravel项目如何共用migrations详解
Sep 25 PHP
PHP自动载入类文件函数__autoload的使用方法
Mar 25 PHP
使用PHP会话(Session)实现用户登陆功能
Jun 29 #PHP
php获取数组中重复数据的两种方法
Jun 28 #PHP
php setcookie(name, value, expires, path, domain, secure) 参数详解
Jun 28 #PHP
关于url地址传参数时字符串有回车造成页面脚本赋值失败的解决方法
Jun 28 #PHP
使用PHP实现Mysql读写分离
Jun 28 #PHP
win7下memCache的安装过程(具体操作步骤)
Jun 28 #PHP
浅析memcache启动以及telnet命令详解
Jun 28 #PHP
You might like
一步一步学习PHP(2)――PHP类型
2010/02/15 PHP
对象失去焦点时自己动提交数据的实现代码
2012/11/06 PHP
PHP在线生成二维码代码(google api)
2013/06/03 PHP
PHP使用JSON和将json还原成数组
2015/02/12 PHP
关于PHP中Session文件过多的问题及session文件保存位置
2016/03/17 PHP
PHP之将POST数据转化为字符串的实现代码
2016/11/03 PHP
Windows Live的@live.com域名注册漏洞 利用代码
2006/12/27 Javascript
jquery ready()的几种实现方法小结
2010/06/18 Javascript
基于jQuery的左右滚动实现代码
2010/12/03 Javascript
jQuery filter函数使用方法
2014/05/19 Javascript
上传文件返回的json数据会被提示下载问题解决方案
2014/12/03 Javascript
js跨浏览器的事件侦听器和事件对象的使用方法
2015/12/17 Javascript
js控件Kindeditor实现图片自动上传功能
2020/07/20 Javascript
微信小程序 实战小程序实例
2016/10/08 Javascript
基于vue实现多引擎搜索及关键字提示
2017/03/16 Javascript
利用JS对iframe父子(内外)页面进行操作的方法教程
2017/06/15 Javascript
搭建vue开发环境
2018/07/19 Javascript
vue中$nextTick的用法讲解
2019/01/17 Javascript
vue history 模式打包部署在域名的二级目录的配置指南
2019/07/02 Javascript
layui type2 通过url给iframe子页面传值的例子
2019/09/06 Javascript
javascript操作向表格中动态加载数据
2020/08/27 Javascript
Python中关键字nonlocal和global的声明与解析
2017/03/12 Python
Python wxPython库消息对话框MessageDialog用法示例
2018/09/03 Python
通过Turtle库在Python中绘制一个鼠年福鼠
2020/02/03 Python
Python读取xlsx数据生成图标代码实例
2020/08/12 Python
Django日志及中间件模块应用案例
2020/09/10 Python
在Python中实现字典反转案例
2020/12/05 Python
css3+jq创作含苞待放的荷花
2014/02/20 HTML / CSS
美国男士内衣品牌:Tommy John
2017/12/22 全球购物
波兰在线体育用品商店:Hop-Sport.pl
2019/07/23 全球购物
在Java开发中如何选择使用哪种集合类
2016/08/09 面试题
初中生学习生活的自我评价
2013/11/20 职场文书
大学生就业意向书范文
2014/04/01 职场文书
党代会心得体会
2014/09/04 职场文书
寒山寺导游词
2015/02/03 职场文书
Spring Security使用单点登录的权限功能
2022/04/03 Java/Android