分享php实现JavaScript中escape函数加密与unescape解密
2015年10月11日星期日 | | |在json中不支持中文,用它传送中文数据就会出现数据丢失或者乱码,必须在传送前对要发送的字符串进行编码,由于传送过去需要用js进行数据解析,考虑 到js中有unescape函数,故若在php中有个escape函数,对数据进行编码,在客户端用unescape进行 解码,这样就会方便很多。
先在网上搜索一把,很多用php实现的escape函数,大同小异
- function phpescape($str){
- preg_match_all("/[\x80-\xff].|[\x01-\x7f]+/",$str,$newstr);
- $ar = $newstr[0];
- foreach($ar as $k=>$v){
- if(ord($ar[$k])>=127){
- $tmpString=bin2hex(iconv("GBK","ucs-2",$v));
- if (!eregi("WIN",PHP_OS)){
- $tmpString = substr($tmpString,2,2).substr($tmpString,0,2);
- }
- $reString.="%u".$tmpString;
- } else {
- $reString.= rawurlencode($v);
- }
- }
- return $reString;
- }
这个函数可以很好的工作,但是,也许有新手不理解这个函数的原理(比如我),用起来总是不放心,现在我就来解释一下这个函数的原理。而且我认为,拿别人的代码来复用,好比站在了巨人的肩膀上,但是若不理解别人的代码,迟早要掉到地面上。
第一句: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编码
}
这个就是关于php中escape函数的一个实现,欢迎大家补充
有时候可能会遇到PHP版本不同,导致出来结果不同,以致于乱码
下面这个备用
php提供的URL编码函数是基于字节的,对由ie的javascript函数escape编码的数据就无能为力了。
因此在此共享本人的php版的escape/unescape函数
一个加密一个解密的
- function escape($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);
- }
- function unescape($str) {
- $str = rawurldecode($str);
- preg_match_all("/(?:%u.{4})|.+/",$str,$r);
- $ar = $r[0];
- foreach($ar as $k=>$v) {
- if(substr($v,0,2) == "%u" && strlen($v) == 6)
- $ar[$k] = iconv("UCS-2","GB2312",pack("H4",substr($v,-4)));
- }
- return join("",$ar);
- }
//编码,编码后为小写
function escape($str){
preg_match_all("/[\x80-\xff].|[\x01-\x7f]+/",$str,$newstr);
$ar = $newstr[0];
foreach($ar as $k=>$v){
if(ord($ar[$k])>=127){
$tmpString=bin2hex(iconv("GBK","ucs-2//IGNORE",$v));
if (!eregi("WIN",PHP_OS)){
$tmpString = substr($tmpString,2,2).substr($tmpString,0,2);
}
$reString.="%u".$tmpString;
}else{
$reString.= rawurlencode($v);
}
}
return $reString;
}
//解码为HTML实体字符
function unescape ($source){
$decodedStr = "";
$pos = 0;
$len = strlen ($source);
while ($pos < $len){
$charAt = substr ($source, $pos, 1);
if ($charAt == '%'){
$pos++;
$charAt = substr ($source, $pos, 1);
if ($charAt == 'u'){
// we got a unicode character
$pos++;
$unicodeHexVal = substr ($source, $pos, 4);
$unicode = hexdec ($unicodeHexVal);
$entity = "&#". $unicode . ';';
$decodedStr .= utf8_encode ($entity);
$pos += 4;
}else{
// we have an escaped ascii character
$hexVal = substr ($source, $pos, 2);
$decodedStr .= chr (hexdec ($hexVal));
$pos += 2;
}
}else{
$decodedStr .= $charAt;
$pos++;
}
}
return $decodedStr;
}
//直接解码为字符串。网上找到的这个版本的函数是解码为HTML实体字符,这是我修改的
function unescape($source){
$decodedStr = "";
$pos = 0;
$len = strlen ($source);
while ($pos < $len){
$charAt = substr ($source, $pos, 1);
if ($charAt == '%'){
$pos++;
$charAt = substr ($source, $pos, 1);
if ($charAt == 'u'){
// we got a unicode character
$pos++;
$unicodeHexVal = substr ($source, $pos, 4);
$unicode = hexdec ($unicodeHexVal);
$decodedStr .= u2utf82gb($unicode);
$pos += 4;
}else{
// we have an escaped ascii character
$hexVal = substr ($source, $pos, 2);
$decodedStr .= chr (hexdec ($hexVal));
$pos += 2;
}
}else{
$decodedStr .= $charAt;
$pos++;
}
}
return $decodedStr;
}
function u2utf82gb($c){
$strphp = "";
if($c < 0x80){
$strphp .= $c;
}elseif($c < 0x800){
$strphp .= chr(0xC0 | $c>>6);
$strphp .= chr(0x80 | $c & 0x3F);
}elseif($c < 0x10000){
$strphp .= chr(0xE0 | $c>>12);
$strphp .= chr(0x80 | $c>>6 & 0x3F);
$strphp .= chr(0x80 | $c & 0x3F);
}elseif($c < 0x200000){
$strphp .= chr(0xF0 | $c>>18);
$strphp .= chr(0x80 | $c>>12 & 0x3F);
$strphp .= chr(0x80 | $c>>6 & 0x3F);
$strphp .= chr(0x80 | $c & 0x3F);
}
return iconv('UTF-8', 'GB2312', $strphp);
}