解析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 相关文章推荐
不用数据库的多用户文件自由上传投票系统(1)
Oct 09 PHP
PHP一些有意思的小区别
Dec 06 PHP
php.ini中的php-5.2.0配置指令详解
Mar 27 PHP
php下获取Discuz论坛登录用户名、用户组、用户ID等信息的实现代码
Dec 29 PHP
解析mysql中UNIX_TIMESTAMP()函数与php中time()函数的区别
Jun 24 PHP
PHP数据库操作之基于Mysqli的数据库操作类库
Apr 19 PHP
php校验表单检测字段是否为空的方法
Mar 20 PHP
PHP设计模式之观察者模式实例
Feb 22 PHP
Yii框架实现图片上传的方法详解
May 20 PHP
Laravel如何使用Redis共享Session
Feb 23 PHP
php-app开发接口加密详解
Apr 18 PHP
Thinkphp框架+Layui实现图片/文件上传功能分析
Feb 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生成HTML静态页面实例代码
2008/08/31 PHP
判断、添加和删除WordPress置顶文章的相关PHP函数小结
2015/12/10 PHP
分析php://output和php://stdout的区别
2018/05/06 PHP
基于jquery的blockui插件显示弹出层
2011/04/14 Javascript
我用的一些Node.js开发工具、开发包、框架等总结
2014/09/25 Javascript
jQuery实现form表单元素序列化为json对象的方法
2015/12/09 Javascript
Bootstrap Fileinput文件上传组件用法详解
2016/05/10 Javascript
JS点击某个图标或按钮弹出文件选择框的实现代码
2016/09/27 Javascript
Mac系统下Webstorm快捷键整理大全
2017/05/28 Javascript
BootStrap Select清除选中的状态恢复默认状态
2017/06/20 Javascript
AngularJS对动态增加的DOM实现ng-keyup事件示例
2018/03/12 Javascript
js Element Traversal规范中的元素遍历方法
2018/04/19 Javascript
vue加载完成后的回调函数方法
2018/09/07 Javascript
微信小程序中遇到的iOS兼容性问题小结
2018/11/14 Javascript
js array数组对象操作方法汇总
2019/03/18 Javascript
如何从零开始手写Koa2框架
2019/03/22 Javascript
vue 地区选择器v-distpicker的常用功能
2019/07/23 Javascript
vue柱状进度条图像的完美实现方案
2019/08/26 Javascript
基于JS正则表达式实现模板数据动态渲染(实现思路详解)
2020/03/07 Javascript
vue深度监听(监听对象和数组的改变)与立即执行监听实例
2020/09/04 Javascript
python中matplotlib实现最小二乘法拟合的过程详解
2017/07/11 Python
python去掉空白行的多种实现代码
2018/03/19 Python
Python 多线程不加锁分块读取文件的方法
2018/12/11 Python
python实现小程序推送页面收录脚本
2020/04/20 Python
python+requests接口压力测试500次,查看响应时间的实例
2020/04/30 Python
sqlalchemy实现时间列自动更新教程
2020/09/02 Python
HTML5如何为形状图上颜色怎么绘制具有颜色和透明度的矩形
2014/06/23 HTML / CSS
Linux中如何设置Java环境变量(Ubuntu)
2016/07/24 面试题
北京鼎普科技股份有限公司软件测试面试题
2012/04/07 面试题
金融专业个人求职信范文
2013/11/28 职场文书
自荐信封面
2013/12/04 职场文书
经贸专业毕业生求职信范文
2014/05/01 职场文书
民族团结先进集体事迹材料
2014/05/22 职场文书
幼儿园中秋节活动总结
2015/03/23 职场文书
山楂树之恋观后感
2015/06/11 职场文书
分布式架构Redis中有哪些数据结构及底层实现原理
2022/03/13 Redis