程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 解析php中的escape函數

解析php中的escape函數

編輯:關於PHP編程

    采用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);

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved