解析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 相关文章推荐
php删除页面记录 同时刷新页面 删除条件用GET方式获得
Jan 10 PHP
基于PHP字符串的比较函数strcmp()与strcasecmp()的使用详解
May 15 PHP
phpphp图片采集后按原路径保存图片示例
Feb 18 PHP
PHP中copy on write写时复制机制介绍
May 13 PHP
javascript+php实现根据用户时区显示当地时间的方法
Mar 11 PHP
php通过array_merge()函数合并两个数组的方法
Mar 18 PHP
php将HTML表格每行每列转为数组实现采集表格数据的方法
Apr 03 PHP
PHP中创建和验证哈希的简单方法实探
Jul 06 PHP
Laravel学习教程之request validation的编写
Oct 25 PHP
PHP实现会员账号单唯一登录的方法分析
Mar 07 PHP
PHP使用ajax的post方式下载excel文件简单示例
Aug 06 PHP
基于PHP的微信公众号的开发流程详解
Aug 07 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 安全过滤函数代码
2011/05/07 PHP
php curl模拟post提交数据示例
2013/12/31 PHP
php找出指定范围内回文数且平方根也是回文数的方法
2015/03/23 PHP
PHP封装的MSSql操作类完整实例
2016/05/26 PHP
php mongodb操作类 带几个简单的例子
2016/08/25 PHP
thinkphp5 migrate数据库迁移工具
2018/02/20 PHP
PHP+MySQL高并发加锁事务处理问题解决方法
2018/04/30 PHP
PHP get_html_translation_table()函数用法讲解
2019/02/16 PHP
gridpanel动态加载数据的实例代码
2013/07/18 Javascript
Js日期选择自动填充到输入框(界面漂亮兼容火狐)
2013/08/02 Javascript
JS实现的竖向折叠菜单代码
2015/10/21 Javascript
jquery插件方式实现table查询功能的简单实例
2016/06/06 Javascript
javascript 初学教程及五子棋小程序的简单实现
2017/07/04 Javascript
Vue基于NUXT的SSR详解
2017/10/24 Javascript
微信小程序request请求封装,验签代码实例
2019/12/04 Javascript
Vue循环中多个input绑定指定v-model实例
2020/08/31 Javascript
Python自动化构建工具scons使用入门笔记
2015/03/10 Python
Python3写入文件常用方法实例分析
2015/05/22 Python
Python读写unicode文件的方法
2015/07/10 Python
对numpy中array和asarray的区别详解
2018/04/17 Python
Python针对给定字符串求解所有子序列是否为回文序列的方法
2018/04/21 Python
Python Requests模拟登录实现图书馆座位自动预约
2018/04/27 Python
使用python将图片格式转换为ico格式的示例
2018/10/22 Python
Python3+Appium实现多台移动设备操作的方法
2019/07/05 Python
python列表每个元素同增同减和列表元素去空格的实例
2019/07/20 Python
基于Python实现粒子滤波效果
2020/12/01 Python
加拿大快时尚零售商:Ardene
2018/02/14 全球购物
编程输出如下图形
2013/11/24 面试题
三年大学生活自我鉴定
2014/01/21 职场文书
年级组长自我鉴定
2014/02/22 职场文书
浪费资源的建议书
2014/03/12 职场文书
餐饮周年庆活动方案
2014/08/14 职场文书
2015年爱牙日活动总结
2015/02/05 职场文书
志愿者个人总结
2015/03/03 职场文书
教师调动申请报告
2015/05/18 职场文书
2015年依法治校工作总结
2015/07/27 职场文书