使用新的 base64 解析,同时增加 b64 参数

This commit is contained in:
Shawn
2020-05-24 13:48:02 +08:00
parent df12421c0a
commit 36f75f9fa5

View File

@@ -1,5 +1,5 @@
/** /**
# Quantumult X 资源解析器 (2020-05-24: 12:59 ) # Quantumult X 资源解析器 (2020-05-24: 13:59 )
本资源解析器作者: Shawn(请勿私聊问怎么用)有bug请反馈: @Shawn_KOP_bot 本资源解析器作者: Shawn(请勿私聊问怎么用)有bug请反馈: @Shawn_KOP_bot
更新请关注tg频道: https://t.me/QuanX_API 更新请关注tg频道: https://t.me/QuanX_API
@@ -20,7 +20,8 @@
- cert=0跳过证书验证(vmess/trojan),即强制"tls-verification=false"; - cert=0跳过证书验证(vmess/trojan),即强制"tls-verification=false";
- tls13=1, 开启 "tls13=true"(vmess/trojan), 请自行确认服务端是否支持; - tls13=1, 开启 "tls13=true"(vmess/trojan), 请自行确认服务端是否支持;
- sort=1 或 sort=-1, 排序参数,分别根据节点名 正序/逆序 排列; - sort=1 或 sort=-1, 排序参数,分别根据节点名 正序/逆序 排列;
- info=1, 开启通知提示流量信息(前提:原订阅链接有返回该信息),默认关闭 - info=1, 开启通知提示流量信息(前提:原订阅链接有返回该信息),默认关闭;
- b64=1, 由于QuanX的特性整体base64-encode 后导入时Quanx 才会自动解码检查并忽视错误节点(所以可在解析提示"内容无效/invalid..."时,尝试使用此参数)
2⃣ "rewrite(重写)/filter(分流)" 引用--参数说明: 2⃣ "rewrite(重写)/filter(分流)" 引用--参数说明:
- 参数为 "out=xxx", 多个参数用 "+" 连接; - 参数为 "out=xxx", 多个参数用 "+" 连接;
@@ -64,7 +65,9 @@ var Pcert0=mark0 && para.indexOf("cert=")!=-1? para.split("#")[1].split("cert=")
var Psort0=mark0 && para.indexOf("sort=")!=-1? para.split("#")[1].split("sort=")[1].split("&")[0].split("+"):0; var Psort0=mark0 && para.indexOf("sort=")!=-1? para.split("#")[1].split("sort=")[1].split("&")[0].split("+"):0;
var PTls13=mark0 && para.indexOf("tls13=")!=-1? para.split("#")[1].split("tls13=")[1].split("&")[0].split("+"):0; var PTls13=mark0 && para.indexOf("tls13=")!=-1? para.split("#")[1].split("tls13=")[1].split("&")[0].split("+"):0;
var Pntf0= mark0 && para.indexOf("ntf=")!=-1? para.split("#")[1].split("ntf=")[1].split("&")[0].split("+"):0; var Pntf0= mark0 && para.indexOf("ntf=")!=-1? para.split("#")[1].split("ntf=")[1].split("&")[0].split("+"):0;
var Pb64= mark0 && para.indexOf("b64=")!=-1? para.split("#")[1].split("b64=")[1].split("&")[0].split("+"):0;
//$notify(type0,"tt",content0) //$notify(type0,"tt",content0)
const Base64=new Base64Code();
//响应头流量处理部分 //响应头流量处理部分
var subinfo=$resource.info; var subinfo=$resource.info;
@@ -150,10 +153,11 @@ if(flag==3){
}; };
//$notify("Final","List",total) //$notify("Final","List",total)
total=total.join("\n"); total=total.join("\n");
if(flag==1 && Pb64==1){
total=Base64.encode(total)}
$done({content : total}); $done({content : total});
} }
//判断订阅类型 //判断订阅类型
function Type_Check(subs){ function Type_Check(subs){
var type="unknown" var type="unknown"
@@ -219,7 +223,7 @@ function Rewrite_Filter(subs,Pout){
hname="hostname="+nname.join(", "); hname="hostname="+nname.join(", ");
//console.log(hname) //console.log(hname)
nlist.push(hname) nlist.push(hname)
if(dname.length>0){$notify("🤖 您添加的[rewrite]过滤关键词为"+Pout0.join(", "),"☠️ 主机名 hostname 中已为您删除以下"+dname.length+"个匹配项",dname.join(",") )} if(dname.length>0){$notify("🤖 您添加的 [rewrite] 过滤关键词为:","🚫 "+Pout0.join(", "),"☠️ 主机名 hostname 中已为您删除以下"+dname.length+"个匹配项:"+"\n"+dname.join(",") )}
} // if cc -hostname } // if cc -hostname
else{ else{
drewrite.push(cc); drewrite.push(cc);
@@ -230,7 +234,7 @@ function Rewrite_Filter(subs,Pout){
} //else } //else
} }
}//cnt for }//cnt for
if(drewrite.length>0){$notify("🤖 您添加的[rewrite]过滤关键词为"+Pout0.join(", "),"☠️ 复写 rewrite 中已为您禁用以下"+drewrite.length+"个匹配项",drewrite.join("\n") )}; if(drewrite.length>0){$notify("🤖 您添加的 [rewrite] 过滤关键词为:","🚫 "+Pout0.join(", "),"☠️ 复写 rewrite 中已为您禁用以下"+drewrite.length+"个匹配项:"+"\n"+drewrite.join("\n") )};
return nlist return nlist
}else { // Pout if }else { // Pout if
//$notify("no filter at all") //$notify("no filter at all")
@@ -258,8 +262,8 @@ function Rule_Handle(subs,Pout){
} }
}//for cnt }//for cnt
var no=dlist.length var no=dlist.length
if(dlist.length>0){$notify("🤖 您添加的分流 [filter] 过滤关键词为"+out,"☠️ 已为您删除以下 "+no+"条匹配规则", dlist.join("\n")) if(dlist.length>0){$notify("🤖 您添加的分流 [filter] 过滤关键词为:","🚫 "+out,"☠️ 已为您删除以下 "+no+"条匹配规则:"+"\n"+dlist.join("\n"))
}else{$notify("🤖 您添加的[filter]过滤关键词为:"+out,"☠️ 没有发现任何匹配项",dlist)} }else{$notify("🤖 您添加的[filter]过滤关键词为:","🚫 "+out,"☠️ 没有发现任何匹配项")}
return nlist return nlist
} else{return cnt.map(Rule_Policy)}//if Pout } else{return cnt.map(Rule_Policy)}//if Pout
} }
@@ -296,8 +300,8 @@ function Rule_Policy(content){ //增加、替换 policy
//混合订阅类型,用于整体进行了 base64 encode 后的类型 //混合订阅类型,用于整体进行了 base64 encode 后的类型
function SubsEd2QX(subs,Pudp,Ptfo,Pcert,Ptls13){ function SubsEd2QX(subs,Pudp,Ptfo,Pcert,Ptls13){
const $base64 = new Base64() var list0=Base64.decode(subs).split("\n");
var list0=$base64.decode(subs).split("\n"); //$notify("After B64","lists",list0)
var QuanXK=["shadowsocks=","trojan=","vmess=","http="]; var QuanXK=["shadowsocks=","trojan=","vmess=","http="];
var SurgeK=["=ss","=vmess","=trojan","=http","=custom"]; var SurgeK=["=ss","=vmess","=trojan","=http","=custom"];
var QXlist=[]; var QXlist=[];
@@ -331,7 +335,6 @@ function SubsEd2QX(subs,Pudp,Ptfo,Pcert,Ptls13){
//混合订阅类型,用于未整体进行 base64 encode 的类型 //混合订阅类型,用于未整体进行 base64 encode 的类型
function Subs2QX(subs,Pudp,Ptfo,Pcert,Ptls13){ function Subs2QX(subs,Pudp,Ptfo,Pcert,Ptls13){
//const $base64 = new Base64()
var list0=subs.split("\n"); var list0=subs.split("\n");
var QuanXK=["shadowsocks=","trojan=","vmess=","http="]; var QuanXK=["shadowsocks=","trojan=","vmess=","http="];
var SurgeK=["=ss","=vmess","=trojan","=http"]; var SurgeK=["=ss","=vmess","=trojan","=http"];
@@ -377,12 +380,17 @@ function TagCheck_QX(content){
$notify("⚠️ 订阅内出现空节点名:", "✅ 已自动将节点“类型+IP”作为节点名","✅ "+nm) $notify("⚠️ 订阅内出现空节点名:", "✅ 已自动将节点“类型+IP”作为节点名","✅ "+nm)
item=item.split("tag")[0]+"tag="+nm item=item.split("tag")[0]+"tag="+nm
} }
var ni=0
while(nmlist.indexOf(nm)!=-1){ while(nmlist.indexOf(nm)!=-1){
$notify("⚠️ 订阅内出现重复节点名:", "⚠️ "+ nm, "✅ 已自动添加“”符号作为区分:"+nm+"") ni=ni+1
nm=nm+"" nm=nm.split("")[0]+"^"+ni
item=item.split("tag")[0]+"tag="+nm item=item.split("tag")[0]+"tag="+nm
} }
nmlist.push(nm) if(ni!=0){
$notify("⚠️ 订阅内出现重复节点名:", "⚠️ "+ nm.split("")[0], "✅ 已自动添加“”符号作为区分:"+nm)
}
nmlist.push(nm)
ni=0
Nlist.push(item) Nlist.push(item)
} }
@@ -392,10 +400,9 @@ function TagCheck_QX(content){
//V2RayN uri转换成 QUANX 格式 //V2RayN uri转换成 QUANX 格式
function V2QX(subs,Pudp,Ptfo,Pcert,Ptls13){ function V2QX(subs,Pudp,Ptfo,Pcert,Ptls13){
const $base64 = new Base64()
var cert=Pcert var cert=Pcert
var tls13=Ptls13 var tls13=Ptls13
var server=String($base64.decode(subs.replace("vmess://","")).trim()).split("\u0000")[0]; var server=String(Base64.decode(subs.replace("vmess://","")).trim()).split("\u0000")[0];
var nss=[]; var nss=[];
if(server!=""){ if(server!=""){
ss=JSON.parse(server); ss=JSON.parse(server);
@@ -497,26 +504,25 @@ function filter(servers,Pin,Pout){
//SSR 类型 URI 转换 quanx 格式 //SSR 类型 URI 转换 quanx 格式
function SSR2QX(subs,Pudp,Ptfo){ function SSR2QX(subs,Pudp,Ptfo){
const $base64 = new Base64()
var nssr=[] var nssr=[]
var cnt=$base64.decode(subs.split("ssr://")[1].replace(/-/g,"+").replace(/_/g,"/")).split("\u0000")[0] var cnt=Base64.decode(subs.split("ssr://")[1].replace(/-/g,"+").replace(/_/g,"/")).split("\u0000")[0]
var obfshost = ''; var obfshost = '';
var oparam = ''; var oparam = '';
if(cnt.split(":").length<=6) { //排除难搞的 ipv6 节点 if(cnt.split(":").length<=6) { //排除难搞的 ipv6 节点
type="shadowsocks="; type="shadowsocks=";
ip=cnt.split(":")[0]+":"+cnt.split(":")[1]; ip=cnt.split(":")[0]+":"+cnt.split(":")[1];
pwd="password="+$base64.decode(cnt.split("/?")[0].split(":")[5].replace(/-/g,"+").replace(/_/g,"/")).split("\u0000")[0]; pwd="password="+Base64.decode(cnt.split("/?")[0].split(":")[5].replace(/-/g,"+").replace(/_/g,"/")).split("\u0000")[0];
mtd="method="+cnt.split(":")[3]; mtd="method="+cnt.split(":")[3];
obfs="obfs="+cnt.split(":")[4]+", "; obfs="obfs="+cnt.split(":")[4]+", ";
ssrp="ssr-protocol="+cnt.split(":")[2]; ssrp="ssr-protocol="+cnt.split(":")[2];
if(cnt.indexOf("obfsparam=")!=-1){ if(cnt.indexOf("obfsparam=")!=-1){
obfshost=cnt.split("obfsparam=")[1].split("&")[0]!=""? "obfs-host="+$base64.decode(cnt.split("obfsparam=")[1].split("&")[0].replace(/-/g,"+").replace(/_/g,"/")).split(",")[0].split("\u0000")[0]+", ":"" obfshost=cnt.split("obfsparam=")[1].split("&")[0]!=""? "obfs-host="+Base64.decode(cnt.split("obfsparam=")[1].split("&")[0].replace(/-/g,"+").replace(/_/g,"/")).split(",")[0].split("\u0000")[0]+", ":""
} }
if(cnt.indexOf("protoparam=")!=-1){ if(cnt.indexOf("protoparam=")!=-1){
oparam=cnt.split("protoparam=")[1].split("&")[0]!=""? "ssr-protocol-param="+$base64.decode(cnt.split("protoparam=")[1].split("&")[0].replace(/-/g,"+").replace(/_/g,"/")).split(",")[0].split("\u0000")[0]+", ":"" oparam=cnt.split("protoparam=")[1].split("&")[0]!=""? "ssr-protocol-param="+Base64.decode(cnt.split("protoparam=")[1].split("&")[0].replace(/-/g,"+").replace(/_/g,"/")).split(",")[0].split("\u0000")[0]+", ":""
} }
tag="tag="+($base64.decode(cnt.split("remarks=")[1].split("&")[0].replace(/-/g,"+").replace(/_/g,"/"))).split("\u0000")[0] tag="tag="+(Base64.decode(cnt.split("remarks=")[1].split("&")[0].replace(/-/g,"+").replace(/_/g,"/"))).split("\u0000")[0]
//console.log($base64.decode(cnt.split("remarks=")[1].split("&")[0].replace(/-/g,"+").replace(/_/g,"/"))) //console.log(Base64.decode(cnt.split("remarks=")[1].split("&")[0].replace(/-/g,"+").replace(/_/g,"/")))
pudp= Pudp==1? "udp-relay=true":"udp-relay=false"; pudp= Pudp==1? "udp-relay=true":"udp-relay=false";
ptfo= Ptfo==1? "fast-open=true":"fast-open=false"; ptfo= Ptfo==1? "fast-open=true":"fast-open=false";
nssr.push(type+ip,pwd,mtd,obfs+obfshost+oparam+ssrp,pudp,ptfo,tag) nssr.push(type+ip,pwd,mtd,obfs+obfshost+oparam+ssrp,pudp,ptfo,tag)
@@ -550,16 +556,16 @@ function TJ2QX(subs,Pudp,Ptfo,Pcert,Ptls13){
//SS 类型 URI 转换 quanx 格式 //SS 类型 URI 转换 quanx 格式
function SS2QX(subs,Pudp,Ptfo){ function SS2QX(subs,Pudp,Ptfo){
const $base64 = new Base64()
var nssr=[] var nssr=[]
var cnt=subs.split("ss://")[1] var cnt=subs.split("ss://")[1]
//$notify("SS转换 ing","SS",cnt)
if(cnt.split(":").length<=6) { //排除难搞的 ipv6 节点 if(cnt.split(":").length<=6) { //排除难搞的 ipv6 节点
type="shadowsocks="; type="shadowsocks=";
if(cnt.indexOf("@")!=-1){ if(cnt.indexOf("@")!=-1){
ip=cnt.split("@")[1].split("#")[0].split("/")[0]; ip=cnt.split("@")[1].split("#")[0].split("/")[0];
pwdmtd=$base64.decode(cnt.split("@")[0].replace(/-/g,"+").replace(/_/g,"/")).split("\u0000")[0].split(":") pwdmtd=Base64.decode(cnt.split("@")[0].replace(/-/g,"+").replace(/_/g,"/")).split("\u0000")[0].split(":")
}else{ }else{
var cnt0=$base64.decode(cnt.split("#")[0].replace(/-/g,"+").replace(/_/g,"/").split("\u0000")[0]); var cnt0=Base64.decode(cnt.split("#")[0].replace(/-/g,"+").replace(/_/g,"/").split("\u0000")[0]);
ip=cnt0.split("@")[1].split("#")[0].split("/")[0]; ip=cnt0.split("@")[1].split("#")[0].split("/")[0];
pwdmtd=cnt0.split("@")[0].split(":") pwdmtd=cnt0.split("@")[0].split(":")
@@ -833,284 +839,152 @@ function Shttp2QX(content){
return nserver return nserver
} }
//比较完美的一款 base64 encode/decode 工具
// Base64, adapted from internet : https://www.jianshu.com/p/54084db83d70 /*
function Base64(){ * base64.js: https://github.com/dankogai/js-base64#readme
*
// 一般的Base64编码字符 * Licensed under the BSD 3-Clause License.
var commonbase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; * http://opensource.org/licenses/BSD-3-Clause
// 对URL进行编码使用的字符 *
var urlBase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; * References:
* http://en.wikipedia.org/wiki/Base64
// Base64解码用到的映射表兼容一般编码的Base64和针对URL进行扩展编码的Base64 */
var base64DecodeChars = new Array( //base64 完毕
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, function Base64Code(){
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // constants
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, 63, -1, -1, 63, var b64chars
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, var b64tab = function(bin) {
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, 62, -1, var t = {};
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1); return t;
}(b64chars);
var fromCharCode = String.fromCharCode;
/** 通用的Base64编码函数 // encoder stuff
* str为待编码的串 var cb_utob = function(c) {
* isUrl用来表明编码的对象(str)是否是一个URL if (c.length < 2) {
*/ var cc = c.charCodeAt(0);
function base64encode(str,isUrl){ return cc < 0x80 ? c
var out, i, len; : cc < 0x800 ? (fromCharCode(0xc0 | (cc >>> 6))
var c1, c2, c3; + fromCharCode(0x80 | (cc & 0x3f)))
: (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f))
// 针对不同的编码方式,选择不同的字符集 + fromCharCode(0x80 | ((cc >>> 6) & 0x3f))
var base64EncodeChars = isUrl ? urlBase64EncodeChars : commonbase64EncodeChars; + fromCharCode(0x80 | ( cc & 0x3f)));
} else {
len = str.length; var cc = 0x10000
i = 0; + (c.charCodeAt(0) - 0xD800) * 0x400
out = ""; + (c.charCodeAt(1) - 0xDC00);
while(i < len){ return (fromCharCode(0xf0 | ((cc >>> 18) & 0x07))
c1 = str.charCodeAt(i++) & 0xff; + fromCharCode(0x80 | ((cc >>> 12) & 0x3f))
+ fromCharCode(0x80 | ((cc >>> 6) & 0x3f))
// 当最后只有一个字节时 + fromCharCode(0x80 | ( cc & 0x3f)));
if(i == len){
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt((c1 & 0x3) << 4);
out += "==";
break;
}
c2 = str.charCodeAt(i++);
// 当最后剩余两个字节时
if(i == len){
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt((c2 & 0xF) << 2);
out += "=";
break;
}
//当剩余字节数大于等于3时
c3 = str.charCodeAt(i++);
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
out += base64EncodeChars.charAt(c3 & 0x3F);
} }
return out; };
} var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
var utob = function(u) {
/** return u.replace(re_utob, cb_utob);
* Base64解码函数 };
* @param str var cb_encode = function(ccc) {
* @returns {*} var padlen = [0, 2, 1][ccc.length % 3],
*/ ord = ccc.charCodeAt(0) << 16
function base64decode(str){ | ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8)
var c1, c2, c3, c4; | ((ccc.length > 2 ? ccc.charCodeAt(2) : 0)),
var i, len, out; chars = [
b64chars.charAt( ord >>> 18),
len = str.length; b64chars.charAt((ord >>> 12) & 63),
i = 0; padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63),
out = ""; padlen >= 1 ? '=' : b64chars.charAt(ord & 63)
while(i < len){ ];
/* 得到第一个字符 c1 return chars.join('');
* 并过虑掉前后所有与Base64编码无关的字符 };
* */ var btoa = function(b) {
do{ return b.replace(/[\s\S]{1,3}/g, cb_encode);
c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; };
}while(i < len && c1 == -1); // var _encode = function(u) {
// var isUint8Array = Object.prototype.toString.call(u) === '[object Uint8Array]';
// 如果已经到达字符串结尾并最后还未得到有效的Base64编码字符就结尾循环 // return isUint8Array ? u.toString('base64')
if(c1 == -1) // : btoa(utob(String(u)));
break; // }
this.encode=function(u){
/* 得到字符 c2 var isUint8Array = Object.prototype.toString.call(u) === '[object Uint8Array]';
* 并过滤掉所有与Base64编码无关的字符 return isUint8Array ? u.toString('base64')
*/ : btoa(utob(String(u)));
do{
c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
}while(i < len && c2 == -1);
// 如果已经到达字符串结尾并最后还未得到有效的Base64编码字符就结尾循环
if(c2 == -1)
break;
// 根据Base64编码的 c1 和 c2 解码得到一个编码前的字符
out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
/* 得到字符 c3
* 并过滤掉所有与Base64编码无关的字符
* 如果获取的 c3 是 '=' 字符则说明已经解码完成,返回解码得到的字符串
*/
do{
c3 = str.charCodeAt(i++) & 0xff;
if(c3 == 61)
return out;
c3 = base64DecodeChars[c3];
}while(i < len && c3 == -1);
// 如果已经到达字符串结尾并最后还未得到有效的Base64编码字符就结尾循环
if(c3 == -1)
break;
// 根据Base64编码的 c2 和 c3 解码得到一个编码前的字符
out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
/* 这一步就比较复杂了
* 先是尝试获取第四个Base64 编码的字符 c4
* 如果获取的 c4 是 '=' 字符则说明已经解码完成,返回解码得到的字符串
* */
do{
c4 = str.charCodeAt(i++) & 0xff;
if(c4 == 61)
return out;
c4 = base64DecodeChars[c4];
}while(i < len && c4 == -1);
// 如果已经到达字符串结尾并最后还未得到有效的Base64编码字符就结尾循环
if(c4 == -1)
break;
// 根据Base64编码的 c3 和 c4 解码得到一个编码前的字符
out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
} }
return out; var uriencode = function(u, urisafe) {
} return !urisafe
? _encode(u)
/** : _encode(String(u)).replace(/[+\/]/g, function(m0) {
* 把 unicode 码转换成 utf8 编码 return m0 == '+' ? '-' : '_';
* @param str }).replace(/=/g, '');
* @returns {string} };
*/ var encodeURI = function(u) { return uriencode(u, true) };
function unicodeToUtf8(str){ // decoder stuff
var out, i, len, c; var re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g;
var cb_btou = function(cccc) {
out = ""; switch(cccc.length) {
len = str.length; case 4:
for(i = 0; i < len; i++){ var cp = ((0x07 & cccc.charCodeAt(0)) << 18)
c = str.charCodeAt(i); | ((0x3f & cccc.charCodeAt(1)) << 12)
| ((0x3f & cccc.charCodeAt(2)) << 6)
// 兼容 ASCII | (0x3f & cccc.charCodeAt(3)),
if((c >= 0x0001) && (c <= 0x007F)){ offset = cp - 0x10000;
out += str.charAt(i); return (fromCharCode((offset >>> 10) + 0xD800)
}else if(c > 0x07FF){ + fromCharCode((offset & 0x3FF) + 0xDC00));
// 占三个字节的 utf8 case 3:
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F)); return fromCharCode(
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F)); ((0x0f & cccc.charCodeAt(0)) << 12)
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); | ((0x3f & cccc.charCodeAt(1)) << 6)
}else{ | (0x3f & cccc.charCodeAt(2))
// 占两个字节的 utf8 );
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F)); default:
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); return fromCharCode(
} ((0x1f & cccc.charCodeAt(0)) << 6)
| (0x3f & cccc.charCodeAt(1))
);
} }
return out; };
var btou = function(b) {
return b.replace(re_btou, cb_btou);
};
var cb_decode = function(cccc) {
var len = cccc.length,
padlen = len % 4,
n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0)
| (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0)
| (len > 2 ? b64tab[cccc.charAt(2)] << 6 : 0)
| (len > 3 ? b64tab[cccc.charAt(3)] : 0),
chars = [
fromCharCode( n >>> 16),
fromCharCode((n >>> 8) & 0xff),
fromCharCode( n & 0xff)
];
chars.length -= [0, 0, 2, 1][padlen];
return chars.join('');
};
var _atob = function(a){
return a.replace(/\S{1,4}/g, cb_decode);
};
var atob = function(a) {
return _atob(String(a).replace(/[^A-Za-z0-9\+\/]/g, ''));
};
// var _decode = buffer ?
// buffer.from && Uint8Array && buffer.from !== Uint8Array.from
// ? function(a) {
// return (a.constructor === buffer.constructor
// ? a : buffer.from(a, 'base64')).toString();
// }
// : function(a) {
// return (a.constructor === buffer.constructor
// ? a : new buffer(a, 'base64')).toString();
// }
// : function(a) { return btou(_atob(a)) };
var _decode=function(u){
return btou(_atob(u))
} }
this.decode = function(a){
/** return _decode(
* 把 utf8 编码转换成 unicode 码 String(a).replace(/[-_]/g, function(m0) { return m0 == '-' ? '+' : '/' })
* @param str .replace(/[^A-Za-z0-9\+\/]/g, '')
* @returns {string} );
*/ };
function utf8ToUnicode(str){ }
var out, i, len, c;
var char2, char3;
out = "";
len = str.length;
i = 0;
while(i < len){
c = str.charCodeAt(i++);
switch(c >> 4){
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
// 0xxxxxxx ASCII 编码
out += str.charAt(i - 1);
break;
case 12:
case 13:
// 110x xxxx 10xx xxxx
// 占两个字节的 utf8
char2 = str.charCodeAt(i++);
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
// 占三个字节的 utf8
char2 = str.charCodeAt(i++);
char3 = str.charCodeAt(i++);
out += String.fromCharCode(((c & 0x0F) << 12) |
((char2 & 0x3F) << 6) |
((char3 & 0x3F) << 0));
break;
}
}
return out;
}
/**
* 转成 十六 进制编码
* @param str
* @returns {string}
* @constructor
*/
function CharToHex(str){
var out, i, len, c, h;
out = "";
len = str.length;
i = 0;
while(i < len){
c = str.charCodeAt(i++);
// 把数据转换成十六进制的字符串
h = c.toString(16);
if(h.length < 2)
h = "0" + h;
out += "\\x" + h + " ";
if(i > 0 && i % 8 == 0)
out += "\r\n";
}
return out;
}
this.encode=function(str){
// 普通 Base64 编码
return base64encode(unicodeToUtf8(str));
};
this.decode=function(str){
// 普通 Base64 编码
return utf8ToUnicode(base64decode(str));
};
// base64={
// encode:function(str){
// // 普通 Base64 编码
// return base64encode(unicodeToUtf8(str));
// },
// encodeUrl:function(str){
// // 使用 Base64 编码字符串
// return base64encode(unicodeToUtf8(str),1)
// },
// decode:function(str){
// // 兼容的 Base64 解码
// return utf8ToUnicode(base64decode(str));
// },
// encodeToHex:function(str){
// // 普通 Base64 编码 以十六进制显示
// return CharToHex(base64encode(unicodeToUtf8(str)));
// },
// encodeUrlToHex:function(str){
// // 使用 Base64 编码 url 以十六进制显示
// return CharToHex(base64encode(unicodeToUtf8(str),1));
// }
// }
};