diff --git a/axml_Chrome43/LEORChn.baseLib.js b/axml_Chrome43/LEORChn.baseLib.js new file mode 100644 index 0000000..4ecfa35 --- /dev/null +++ b/axml_Chrome43/LEORChn.baseLib.js @@ -0,0 +1,276 @@ +var htmlhead=document.head, + htmlbody=document.body; +(function(){ + // Generic Method Compat + if(!('contains' in String.prototype)) String.prototype.contains=function(s){ return this.indexOf(s)>-1; }; + var imed=false; + HTMLInputElement.prototype.__defineGetter__('imeDisabled',function(){ return imed? true: false; }); + HTMLInputElement.prototype.__defineSetter__('imeDisabled',function(s){ + imed = s? true: false; + this.onkeyup = imed? function(){ + var sel = this.selectionStart, + sav = this.value, + right = sav.substr(sel), + lef = sav.substr(0, sel), + aft = lef.replace(/'/g, ''), + wipecount = lef.length - aft.length; + if(sel != this.selectionEnd) return; + this.blur(); + this.focus(); + this.value = aft + right; + this.selectionStart = this.selectionEnd = sel - wipecount; + }: undefined; + }); + + // IE Method Compat + _proto(HTMLElement, 'remove', function(){ try{this.parentElement.removeChild(this);}catch(e){} }); + _proto(EventTarget, 'addEventListener', function(n,f){ this.attachEvent('on'+n, f); }); + _proto(String, 'includes', function(s){ return this.indexOf(s)>-1; }); + + // Firefox Method Compat + if(!('innerText' in document.body)){ + HTMLElement.prototype.__defineGetter__("innerText", function(){ return this.textContent; }); + HTMLElement.prototype.__defineSetter__("innerText", function(s){ return this.textContent=s; }); + } + + // Constom Method Modify + _proto(Array, 'foreach', function(func){ for(var i=0; i 2) pl(new Error('Somewhere might using old version to create Elements. PLEASE UPDATE YOUR CODE.')); + tag = { + entity: null, + raw: tag, + data: tag.split(/[#\.\s]/g) + }; + var nextStart = 0; + tag.data.foreach(function(e){ + nextStart ++; + if(e.length == 0) return; // continue + nextStart --; + switch(tag.raw.charAt(nextStart)){ + case ' ': case '.': + addClass(tag.entity, e); break; + case '#': + tag.entity.id = e; break; + default: + tag.entity = document.createElement(e); + nextStart --; + } + nextStart += e.length + 1; + }); + if(t) tag.entity.innerText = t; + return tag.entity; +} +function msgbox(msg){alert(msg);} +function inputbox(title,defalt){return prompt(title,defalt);} +function pl(s){console.log(s);} +function vaild(o){return!(o==undefined||o==null||isNaN(o));} +function gquery(n){ return _GET(n); } // get Query +function _GET(n){ + var r=location.search.match(new RegExp("[\?\&]"+n+"=([^\&]+)","i")); + return r==null||r.length<1?'':r[1]; +} +/* patch() 参数情况: + 单个EventTarget:直接返回本体 + 单个EventTarget但是用数组封装:返回该数组 + 多个EventTarget:返回封装数组 + 其他情况比如数组和EventTarget混用等:不管他 +*/ +function patch(){ + var args = arguments, + insideSelf = args.length==1 && args[0] instanceof EventTarget; + if(args.length==1 && args[0] instanceof Array) args = args[0]; // 如果参数只是一个数组而且没有别的东西,就分离解析 + for(var i=0; i 0){ // 0值键可以输出,但是要求在此之前没有输出任何东西,比如想要匹配 protectionLevel 中的 normal,那么就要求不能匹配比他优先级更高的值 + return; // 当之前已经输出过其他键时,跳过输出0值键 + } + if(names.length > 0) names += '|'; // 第二个以及之后输出的,添加一个分隔符然后再连接 + names += e[1]; + value ^= e[0]; // 异或该值,使其更低优先级的值不可匹配。比如 protectionLevel 在匹配 signatureOrSystem 之后不可再匹配 signature 和 dangerous + } + }); + return names; + }, + 'android:configChanges': [ // 使用或运算符连接。https://developer.android.com/reference/android/R.attr?hl=zh-cn#configChanges + [0x40000000, 'fontScale'], + [ 0x4000, 'colorMode'], + [ 0x2000, 'layoutDirection'], + [ 0x1000, 'density'], + [ 0x800, 'smallestScreenSize'], + [ 0x400, 'screenSize'], + [ 0x200, 'uiMode'], + [ 0x100, 'screenLayout'], + [ 0x80, 'orientation'], + [ 0x40, 'navigation'], + [ 0x20, 'keyboardHidden'], + [ 0x10, 'keyboard'], + [ 8, 'touchscreen'], + [ 4, 'locale'], + [ 2, 'mnc'], + [ 1, 'mcc'] + ], + 'android:protectionLevel': [ // 使用或运算符连接。https://developer.android.com/reference/android/R.attr?hl=zh-cn#protectionLevel + [0x1000000, 'retailDemo'], + [ 0x800000, 'companion'], + [ 0x200000, 'appPredictor'], + [ 0x100000, 'incidentReportApprover'], + [ 0x80000, 'configurator'], + [ 0x40000, 'documenter'], + [ 0x20000, 'wellbeing'], + [ 0x10000, 'textClassifier'], + [ 0x8000, 'vendorPrivileged'], + [ 0x4000, 'oem'], + [ 0x2000, 'runtime'], + [ 0x1000, 'instant'], + [ 0x800, 'setup'], + [ 0x400, 'preinstalled'], + [ 0x200, 'verifier'], + [ 0x100, 'installer'], + [ 0x80, 'pre23'], + [ 0x40, 'appop'], + [ 0x20, 'development'], + [ 0x10, 'system'], // the name: "privileged" deprecated in api23 + [ 3, 'signatureOrSystem'], // 常用 + [ 2, 'signature'], // 常用 + [ 1, 'dangerous'], // 常用 + [ 0, 'normal'] // 常用 + ] +}; diff --git a/axml_Chrome43/axml_ECMAScript5_readonly.js b/axml_Chrome43/axml_ECMAScript5_readonly.js new file mode 100644 index 0000000..30c9df9 --- /dev/null +++ b/axml_Chrome43/axml_ECMAScript5_readonly.js @@ -0,0 +1,416 @@ +/* Android Manifest Reader */ +"use strict"; + +function abort(message) { + throw ('Failure: ' + message); +} + +function le32_get(array, offset) { + return (array[offset + 3] << 24) | (array[offset + 2] << 16) | (array[offset + 1] << 8) | array[offset]; +} + +function le16_get(array, offset) { + return (array[offset + 1] << 8) | array[offset]; +} + +function parse_manifest_header(array, offset) { + const header = { + magic: le16_get(array, offset), + self_size: le16_get(array, offset + 2), + file_size: le32_get(array, offset + 4) + }; + + if (header.magic !== 0x0003 || header.self_size !== 8) { + abort('unrecognized manifest header'); + } + + return header; +} + +function parse_string_pool(array, offset) { + const header = { + magic: le16_get(array, offset), + self_size: le16_get(array, offset + 2), + chunk_size: le32_get(array, offset + 4), + nstrings: le32_get(array, offset + 8), + nstyles: le32_get(array, offset + 12), + flags: le32_get(array, offset + 16), + strings_offset: le32_get(array, offset + 20), + styles_offset: le32_get(array, offset + 24) + }; + + if (header.magic !== 0x0001 || header.self_size !== 28) { + abort('unrecognized string pool header'); + } + + if (header.nstyles !== 0 || header.styles_offset !== 0) { + abort('styles are not supported'); + } + + offset += header.strings_offset; + + const pool = []; + + for (let i = 0; i < header.nstrings; i++) { + const slen = le16_get(array, offset) * 2; + offset += 2; + var str = utf16ToUtf8(String.fromCharCode.apply(null, array.slice(offset, offset + slen))); + pool.push({ + index: i, + length: slen, + value: str + }); + offset += slen + 2; + } + + return { + header: header, + pool: pool + }; +} + +function parse_resource_pool(array, offset) { + const header = { + magic: le16_get(array, offset), + self_size: le16_get(array, offset + 2), + chunk_size: le32_get(array, offset + 4), + }; + + if (header.magic !== 0x0180 || header.self_size !== 8) { + abort('unrecognized resource pool header'); + } + + const nresources = (header.chunk_size - header.self_size) / 4; + offset += header.self_size; + + const pool = []; + + for (let i = 0; i < nresources; i++) { + pool.push({ + value: le32_get(array, offset) + }); + offset += 4; + } + + return { + header: header, + pool: pool + }; +} + +function bind_resource_ids(string_pool, resource_pool) { + let bound = 0; + + for (let i = 0; i < resource_pool.pool.length; i++) { + if (i >= string_pool.pool.length) { + abort('resource range exceeded'); + } + + string_pool.pool[i].resource_id = resource_pool.pool[i].value; + bound++; + } + console.log('bound ' + bound + ' resource ids.'); +} + +function type2str(type) { + switch (type) { + case 0x01000008: + return 'id_ref'; + case 0x02000008: + return 'attr_ref'; + case 0x03000008: + return 'string'; + case 0x05000008: + return 'dimen'; + case 0x06000008: + return 'fraction'; + case 0x10000008: + return 'int'; + case 0x04000008: + return 'float'; + case 0x11000008: + return 'flags'; + case 0x12000008: + return 'bool'; + case 0x1c000008: + return 'color'; + case 0x1d000008: + return 'color2'; + default: + return "" + type; + } +} + +function parse_attribute(array, offset, string_pool) { + const result = { + namespace: le32_get(array, offset), + name: le32_get(array, offset + 4), + value: le32_get(array, offset + 8), + type: type2str(le32_get(array, offset + 12)), + resource_id: le32_get(array, offset + 16) + }; + + result.name_string = get_string_from_pool(string_pool, result.name); + + if (result.type === 0x03000008) { // type string + result.value_string = get_string_from_pool(string_pool, result.value); + } + + return result; +} + +function parse_attributes(tag, array, offset, string_pool) { + for (let i = 0; i < tag.attributes_count; i++) { + tag.attributes.push(parse_attribute(array, offset + 36 + i * 20, string_pool)); + } +} + +function get_string_from_pool(string_pool, index) { + if (index >= string_pool.header.nstrings) { + console.log('string index ' + index + ' out of range'); + return '(unknown)'; + } + + return string_pool.pool[index].value; +} + +function parse_xml_tag(array, offset, string_pool) { + let id = le32_get(array, offset); + + switch (id) { + case 0x00100100: + case 0x00100101: + return { + role: id === 0x00100100 ? 'start-ns' : 'end-ns', + chunk_size: le32_get(array, offset + 4), + line: le32_get(array, offset + 8), + comment: le32_get(array, offset + 12), + prefix: le32_get(array, offset + 16), + namespace: le32_get(array, offset + 20) + }; + case 0x00100102: + const tag = { + role: 'start-tag', + chunk_size: le32_get(array, offset + 4), + line: le32_get(array, offset + 8), + comment: le32_get(array, offset + 12), + namespace: le32_get(array, offset + 16), + name: le32_get(array, offset + 20), + name_string: get_string_from_pool(string_pool, le32_get(array, offset + 20)), + attributes_size: le32_get(array, offset + 24), + attributes_count: le32_get(array, offset + 28), + attribute_id: le32_get(array, offset + 32), + attributes: [] + }; + parse_attributes(tag, array, offset, string_pool); + return tag; + case 0x00100104: + return { + role: 'text', + chunk_size: le32_get(array, offset + 4), + line: le32_get(array, offset + 8), + comment: le32_get(array, offset + 12), + string_id: le32_get(array, offset + 16), + unused1: le32_get(array, offset + 20), + unused2: le32_get(array, offset + 24) + }; + case 0x00100103: + return { + role: 'end-tag', + chunk_size: le32_get(array, offset + 4), + line: le32_get(array, offset + 8), + comment: le32_get(array, offset + 12), + namespace: le32_get(array, offset + 16), + name: le32_get(array, offset + 20), + name_string: get_string_from_pool(string_pool, le32_get(array, offset + 20)) + }; + default: + abort('unrecognized tag found'); + } +} + +function decompress_xml(source) { + const array = source; + let offset = 0; + + const manifest = parse_manifest_header(array, offset); + offset += manifest.self_size; + + console.log('file size: ' + manifest.file_size + ' bytes.'); + + const string_pool = parse_string_pool(array, offset); + offset += string_pool.header.chunk_size; + + // console.log('parsed string pool.'); + + const resource_pool = parse_resource_pool(array, offset); + offset += resource_pool.header.chunk_size; + + // console.log('parsed resource pool.'); + + bind_resource_ids(string_pool, resource_pool); + + const xml = []; + + while (offset < array.length) { + const tag = parse_xml_tag(array, offset, string_pool); + xml.push(tag); + offset += tag.chunk_size; + } + + // console.log('parsed xml document.'); + + const result = { + string_pool: string_pool.pool, + xml: xml + }; + + // console.log('done xml decompressing.'); + return result; +} + +function parse_to_xml(source){ + if(source.constructor.name != 'Array'){ + source = arr(source); + } + var j = decompress_xml(source); + + pl(j); // preview + + // ===== ===== ===== ===== + + // convert to custom json format, for convert to xml later + var s = j.string_pool, + doc = { + ns: [], // namespace pool + }, + cur_tag = doc; + var first_start_tag = true; + j.xml.foreach(function(e){ + switch(e.role){ + case 'start-ns': + doc.ns[e.namespace] = { + name: s[e.prefix].value, + url: s[e.namespace].value + }; + break; + case 'start-tag': + var t = {}; + t.__parent = cur_tag; + t.name = (e.namespace == -1? '': doc.ns[e.namespace].name + ':') + e.name_string; + if('attributes' in e){ + t.attr = []; + e.attributes.foreach(function(f){ + var a = {}; + a.name = (f.namespace == -1? '': doc.ns[f.namespace].name + ':') + f.name_string; + switch(f.type){ + case 'int': + a.value = f.resource_id; + break; + case 'string': + a.value = s[f.value].value; + break; + case 'bool': + a.value = f.value == 0? 'false': 'true'; + break; + case 'id_ref': + a.value = '@' + f.resource_id.toString(16); + break; + case 'flags': + a.value = android_R_attr.toString(a.name, f.resource_id); + break; + default: + pl('uncase value type: '+f.type); + } + t.attr.push(a); + }); + } + if(!('_children' in cur_tag)){ + cur_tag._children = []; + } + cur_tag._children.push(t); + cur_tag = t; + break; + case 'end-tag': + cur_tag = cur_tag.__parent; + break; + } + }); + + // push namespace to the root node + var rootnode = doc._children[0]; + if(!('attr' in rootnode)) rootnode.attr = []; + doc.ns.foreach(function(e){ + if(!e) return; + rootnode.attr.push({ + name: 'xmlns:' + e.name, + value: e.url + }); + }); + + pl(doc); // preview + + // ===== ===== ===== ===== + + // convert the custom json to xml + var dom = '', + processor = function(e){ + var attr = ''; + if('attr' in e){ + e.attr.foreach(function(f){ + attr += ` ${f.name}="${f.value}"`; // 先拼接节点属性 + }); + } + var firstline = '<' + e.name + attr, // 拼接节点头部(不确定有没有子节点所以先放着) + childline = '', + lastline = ''; + if('_children' in e && e._children.length > 0){ + firstline += '>'; // 确定有子节点,补充节点头部 + lastline = ``; // 由于有子节点,那么节点尾部就是这样的 + e._children.foreach(function(f){ + childline += processor(f); // 拼接子节点(递归) + }); + }else{ + lastline = ' />'; // 由于没有子节点,那么节点尾部是这样的 + } + return firstline + childline + lastline; + }; + var output = dom + processor(doc._children[0]); + + // return output; + ft('textarea')[0].innerText = output; +} + +function utf16ToUtf8(s){ + if(!s) return; + + var i, code, ret = [], len = s.length; + for(i = 0; i < len; i++){ + code = s.charCodeAt(i); + if(code > 0x0 && code <= 0x7f){ + // 单字节 + // UTF-16 0000 - 007F + // UTF-8 0xxxxxxx + ret.push(s.charAt(i)); + }else if(code >= 0x80 && code <= 0x7ff){ + // 双字节 + // UTF-16 0080 - 07FF + // UTF-8 110xxxxx 10xxxxxx + ret.push( + String.fromCharCode(0xc0 | ((code >> 6) & 0x1f)), // 110xxxxx + String.fromCharCode(0x80 | (code & 0x3f)) // 10xxxxxx + ); + }else if(code >= 0x800 && code <= 0xffff){ + // 三字节 + // UTF-16 0800 - FFFF + // UTF-8 1110xxxx 10xxxxxx 10xxxxxx + ret.push( + String.fromCharCode(0xe0 | ((code >> 12) & 0xf)), // 1110xxxx + String.fromCharCode(0x80 | ((code >> 6) & 0x3f)), // 10xxxxxx + String.fromCharCode(0x80 | (code & 0x3f)) // 10xxxxxx + ); + } + } + + return ret.join(''); +} diff --git a/axml_Chrome43/index.html b/axml_Chrome43/index.html new file mode 100644 index 0000000..96073be --- /dev/null +++ b/axml_Chrome43/index.html @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + +
+ +
VersionName
VersionCode
+ +
+ + + + + + + \ No newline at end of file diff --git a/axml_Chrome43/testcase/Parallel_Space_64Bit_Support_1.0.3032_gg_signed.apk b/axml_Chrome43/testcase/Parallel_Space_64Bit_Support_1.0.3032_gg_signed.apk new file mode 100644 index 0000000..901388e Binary files /dev/null and b/axml_Chrome43/testcase/Parallel_Space_64Bit_Support_1.0.3032_gg_signed.apk differ