Base64在PHP和JavaScript之间使用加号或与号字符对字符串进行编码


Base64 encode string with plus or ampersand char between PHP and JavaScript

我的目标是:

  • 使用PHP从数据库读取数据,进行jQueryajax调用
  • PHP通过对base64中字段的内容进行编码来创建JSON字符串(自定义过程)
  • 读取jQuery响应并解码内容以创建页面

我在PHP中尝试了这个例子(这里缺少数据库的读取部分和JSON编码),但我对包含字符"+"answers"&"的字符串有问题。

我用"bencode"例程解决了一些问题(我在php文档中找到了它)。。。请尝试字符串=">>>>>>"。

<?php
$h = <<<HTML
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html" charset="utf-8" />
        <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
        <title>test base 64</title>
        <script type="text/javascript">
            var Base64={
                _keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
                ,encode:function(e){
                    var t="";
                    var n,r,i,s,o,u,a;
                    var f=0;
                    e=Base64._utf8_encode(e);
                    while(f<e.length){
                        n=e.charCodeAt(f++);
                        r=e.charCodeAt(f++);
                        i=e.charCodeAt(f++);
                        s=n>>2;
                        o=(n&3)<<4|r>>4;
                        u=(r&15)<<2|i>>6;
                        a=i&63;
                        if(isNaN(r)){
                            u=a=64
                        }else if(isNaN(i)){
                            a=64
                        }
                        t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)
                    }
                    return t
                }
                ,decode:function(e){
                    var t="";
                    var n,r,i;
                    var s,o,u,a;
                    var f=0;
                    e=e.replace(/[^A-Za-z0-9+/=]/g,"");
                    while(f<e.length){
                        s=this._keyStr.indexOf(e.charAt(f++));
                        o=this._keyStr.indexOf(e.charAt(f++));
                        u=this._keyStr.indexOf(e.charAt(f++));
                        a=this._keyStr.indexOf(e.charAt(f++));
                        n=s<<2|o>>4;
                        r=(o&15)<<4|u>>2;
                        i=(u&3)<<6|a;
                        t = t + String.fromCharCode(n);
                        if(u!=64){
                            t=t+String.fromCharCode(r)
                        }
                        if(a!=64){
                            t=t+String.fromCharCode(i)
                        }
                    }
                    t=Base64._utf8_decode(t);
                    return t
                }
                ,_utf8_encode:function(e){
                    e=e.replace(/''r''n/g,"''n");
                    var t="";
                    for(var n=0;n<e.length;n++){
                        var r=e.charCodeAt(n);
                        if(r<128){
                            t+=String.fromCharCode(r)
                        }else if(r>127&&r<2048){
                            t+=String.fromCharCode(r>>6|192);
                            t+=String.fromCharCode(r&63|128)
                        }else{
                            t+=String.fromCharCode(r>>12|224);
                            t+=String.fromCharCode(r>>6&63|128);
                            t+=String.fromCharCode(r&63|128)
                        }
                    }
                    return t
                }
                ,_utf8_decode:function(e){
                    var t="";
                    var n=0;
                    var r=c1=c2=0;
                    while(n<e.length){
                        r=e.charCodeAt(n);
                        if(r<128){
                            t+=String.fromCharCode(r);
                            n++
                        }else if(r>191&&r<224){
                            c2=e.charCodeAt(n+1);
                            t+=String.fromCharCode((r&31)<<6|c2&63);
                            n+=2
                        }else{
                            c2=e.charCodeAt(n+1);
                            c3=e.charCodeAt(n+2);
                            t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);
                            n+=3
                        }
                    }
                    return t
                }
            }
            $(function() {
                $( "input" ).keyup(function() {
                    // javascript
                    var sj = $( this ).val();
                    var encoded = Base64.encode(sj);
                    $( "#encoded" ).text( encoded );
                    var decoded = Base64.decode(encoded);
                    $( "#decoded" ).text( decoded );
                    // php
                    var sp = $( this ).val();
                    var encodedphp = '';
                    var decodedphp = '';
                    var bencodedphp = '';
                    if (sp != '') {
                        $.ajax({
                            type: "POST", url: 'base64.php', dataType: 'text', async: false,
                            data: 'toencode64='+sp,
                            success: function( data ) {
                                encodedphp = data;
                            },
                            error: function(jqXHR, textStatus, errorThrown) {
                                console.log(jqXHR);console.log(textStatus);console.log(errorThrown);
                            }
                        });    
                        $.ajax({
                            type: "POST", url: 'base64.php', dataType: 'text', async: false,
                            data: 'todecode64='+encodedphp,
                            success: function( data ) {
                                decodedphp = data;
                            },
                            error: function(jqXHR, textStatus, errorThrown) {
                                console.log(jqXHR);console.log(textStatus);console.log(errorThrown);
                            }
                        });    
                        $.ajax({
                            type: "POST", url: 'base64.php', dataType: 'text', async: false,
                            data: 'bencode='+sp,
                            success: function( data ) {
                                bencodedphp = data;
                            },
                            error: function(jqXHR, textStatus, errorThrown) {
                                console.log(jqXHR);console.log(textStatus);console.log(errorThrown);
                            }
                        });    
                    };
                    $( "#encodedphp" ).text( encodedphp );
                    $( "#decodedphp" ).text( decodedphp );
                    $( "#bencodedphp" ).text( bencodedphp );
                    var encodedjsphp = Base64.decode(encodedphp);
                    $( "#encodedjsphp" ).text( encodedjsphp );
                    var bencodedjsphp = Base64.decode(bencodedphp);
                    $( "#bencodedjsphp" ).text( bencodedjsphp );
                })
                .keyup();
            });
        </script>
    </head>
    <body>
        <input type="text">
        <table>
        <tr><td>01. js encode:</td><td id="encoded"></td></tr>
        <tr><td>02. js decode:</td><td id="decoded"></td></tr>
        <tr><td>03. php encode:</td><td id="encodedphp"></td></tr>
        <tr><td>04. php decode:</td><td id="decodedphp"></td></tr>
        <tr><td>05. php bencode:</td><td id="bencodedphp"></td></tr>
        <tr><td>06. js decode php encode:</td><td id="encodedjsphp"></td></tr>
        <tr><td>07. js decode php bencode:</td><td id="bencodedjsphp"></td></tr>
        </table>
    </body>
</html>
HTML;
?>
<?php
    foreach ($_REQUEST as $key => $value) { 
        $$key = $value;
    };
    $s=$h;
    if (isset($toencode64)) {$s = strtr(base64_encode($toencode64), '+/', '-_');};
    if (isset($todecode64)) {$s = base64_decode(strtr($todecode64, '-_', '+/'));};
    if (isset($bencode)) {$s = bencode($bencode);};
    echo $s;
    function bencode($string='') {
        $binval = convert_binary_str($string);
        $final = "";
        $start = 0;
        while ($start < strlen($binval)) {
            if (strlen(substr($binval,$start)) < 6)
                $binval .= str_repeat("0",6-strlen(substr($binval,$start)));
            $tmp = bindec(substr($binval,$start,6));
            if ($tmp < 26)
                $final .= chr($tmp+65);
            elseif ($tmp > 25 && $tmp < 52)
                $final .= chr($tmp+71);
            elseif ($tmp == 62)
                $final .= "+";
            elseif ($tmp == 63)
                $final .= "/";
            elseif (!$tmp)
                $final .= "A";
            else
                $final .= chr($tmp-4);
            $start += 6;
        }
        if (strlen($final)%4>0)
            $final .= str_repeat("=",4-strlen($final)%4);
        return $final;
    }
    function convert_binary_str($string) {
        if (strlen($string)<=0) return;
        $tmp = decbin(ord($string[0]));
        $tmp = str_repeat("0",8-strlen($tmp)).$tmp;
        return $tmp.convert_binary_str(substr($string,1));
    }
?>

正确的脚本(2016年4月1日)

<?php
$h = <<<HTML
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html" charset="utf-8" />
        <meta name="description" content="Base64">
        <meta name="keywords" content="test Base64">
        <meta name="author" content="Alberto Bongiorni">
        <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
        <title>test base 64</title>
        <script type="text/javascript">
            // decode base64 string
            String.prototype.btoa = function () {
                try {
                    return window.btoa(this);
                }
                catch(err) {
                    return err.message;
                }
            }
            // encode string to base64
            String.prototype.atob = function () {
                try {
                    return window.atob(this);
                }
                catch(err) {
                    return err.message;
                }
            }    
            String.prototype.replaceAll = function(target, replacement) {
                // se replacement = '' cancella tutti quei caratteri dalla stringa
                return this.split(target).join(replacement);
            };
            var Base64={
                _keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
                ,encode:function(e){
                    var t="";
                    var n,r,i,s,o,u,a;
                    var f=0;
                    e=Base64._utf8_encode(e);
                    while(f<e.length){
                        n=e.charCodeAt(f++);
                        r=e.charCodeAt(f++);
                        i=e.charCodeAt(f++);
                        s=n>>2;
                        o=(n&3)<<4|r>>4;
                        u=(r&15)<<2|i>>6;
                        a=i&63;
                        if(isNaN(r)){
                            u=a=64
                        }else if(isNaN(i)){
                            a=64
                        }
                        t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)
                    }
                    return t
                }
                ,decode:function(e){
                    var t="";
                    var n,r,i;
                    var s,o,u,a;
                    var f=0;
                    e=e.replace(/[^A-Za-z0-9+/=]/g,"");
                    while(f<e.length){
                        s=this._keyStr.indexOf(e.charAt(f++));
                        o=this._keyStr.indexOf(e.charAt(f++));
                        u=this._keyStr.indexOf(e.charAt(f++));
                        a=this._keyStr.indexOf(e.charAt(f++));
                        n=s<<2|o>>4;
                        r=(o&15)<<4|u>>2;
                        i=(u&3)<<6|a;
                        t = t + String.fromCharCode(n);
                        if(u!=64){
                            t=t+String.fromCharCode(r)
                        }
                        if(a!=64){
                            t=t+String.fromCharCode(i)
                        }
                    }
                    t=Base64._utf8_decode(t);
                    return t
                }
                ,_utf8_encode:function(e){
                    e=e.replace(/''r''n/g,"''n");
                    var t="";
                    for(var n=0;n<e.length;n++){
                        var r=e.charCodeAt(n);
                        if(r<128){
                            t+=String.fromCharCode(r)
                        }else if(r>127&&r<2048){
                            t+=String.fromCharCode(r>>6|192);
                            t+=String.fromCharCode(r&63|128)
                        }else{
                            t+=String.fromCharCode(r>>12|224);
                            t+=String.fromCharCode(r>>6&63|128);
                            t+=String.fromCharCode(r&63|128)
                        }
                    }
                    return t
                }
                ,_utf8_decode:function(e){
                    var t="";
                    var n=0;
                    var r=c1=c2=0;
                    while(n<e.length){
                        r=e.charCodeAt(n);
                        if(r<128){
                            t+=String.fromCharCode(r);
                            n++
                        }else if(r>191&&r<224){
                            c2=e.charCodeAt(n+1);
                            t+=String.fromCharCode((r&31)<<6|c2&63);
                            n+=2
                        }else{
                            c2=e.charCodeAt(n+1);
                            c3=e.charCodeAt(n+2);
                            t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);
                            n+=3
                        }
                    }
                    return t
                }
            }
            $(function() {
                $( "input" ).keyup(function() {
                    // javascript
                    var sj = $( this ).val();
                    var encoded = Base64.encode(sj);
                    $( "#encoded" ).text( encoded );
                    var decoded = Base64.decode(encoded);
                    $( "#decoded" ).text( decoded );
                    var sab = $( this ).val();
                    var satob = sab.atob();
                    $( "#atob" ).text( satob );
                    var sbtoa = satob.btoa();
                    $( "#btoa" ).text( sbtoa );
                    // php
                    var sp = $( this ).val();
                    var encodedphp = '';
                    if (sp != '') {
                        $.ajax({
                            type: "POST", url: 'base64.php', dataType: 'text', async: false,
                            data: 'toencode64='+encodeURI(encodeURIComponent(sp)),
                            success: function( data ) {
                                encodedphp = data;
                            },
                            error: function(jqXHR, textStatus, errorThrown) {
                                console.log(jqXHR);console.log(textStatus);console.log(errorThrown);
                            }
                        });    
                    };
                    $( "#encodedphp" ).text( encodedphp );
                })
                .keyup();
            });
        </script>
        <style>
            .bg_verde_t40   {background-color: rgba(0, 255, 0, 0.4);}
            .bg_blu_t40         {background-color: rgba(0, 0, 255, 0.4);}
            .bg_rosso_t40   {background-color: rgba(255, 0, 0, 0.4);}
            .bg_arancio_t40     {background-color: rgba(255, 128, 0, 0.4);}
            .bg_viola_t40   {background-color: rgba(128, 128, 255, 0.4);}
        </style>
    </head>
    <body>
        <input type="text">
        <table>
        <tr><td>01. js encode:</td><td id="encoded" class="bg_viola_t40"></td></tr>
        <tr><td>02. js decode:</td><td id="decoded"></td></tr>
        <tr><td>03. php encode:</td><td id="encodedphp" class="bg_viola_t40"></td></tr>
        <tr><td>04. atob encode:</td><td id="atob" class="bg_viola_t40"></td></tr>
        <tr><td>05. btoa decode:</td><td id="btoa"></td></tr>
        </table>
    </body>
</html>
HTML;
?>
<?php
    foreach ($_POST as $key => $value) {    
        $$key = $value;
    };
    $s = $h;
    if (isset($toencode64)) {$s = base64_encode(urldecode($toencode64)).' '.urldecode($toencode64);};
    if (isset($todecode64)) {$s = base64_decode(strtr($todecode64, '-_', '+/'));};
    echo $s;
?>

是的。。。我不知道你在哪里找到那些PHP函数,但天哪,它们太糟糕了。

我确信,你所需要的只是URL安全的base64编码,它可以用完成

function base64url_encode($bin) {
    return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($bin));
}
function base64url_decode($str) {
    return base64_decode(str_replace(['-', '_'], ['+', '/'], $str));
}

或者,在正文中使用POST或PUT请求来处理数据。