2019.3月修复APP分发,仿fir.im分发,APP分发应用托管平台,支持苹果安卓APP分发下载
<?php
namespace ApkParser;
use ApkParserExceptionsXmlParserException;
class XmlParser
{
const END_DOC_TAG = 0x101;
const START_TAG = 0x102;
const END_TAG = 0x103;
const TEXT_TAG = 0x104;
const RES_STRING_POOL_TYPE = 0x1;
const RES_XML_START_ELEMENT_TYPE = 0x102;
const RES_XML_RESOURCE_MAP_TYPE = 0x180;
private $xml = "<?xml version="1.0" encoding="UTF-8"?>
";
private $bytes = array();
private $ready = false;
public static $indent_spaces = "";
private $xmlObject = NULL;
public function __construct(Stream $apkStream)
{
$this->bytes = $apkStream->getByteArray();
}
public static function decompressFile($file, $destination = NULL)
{
if (!is_file($file)) {
throw new Exception("{$file} is not a regular file");
}
$parser = new self(new Stream(fopen($file, 'rd')));
file_put_contents($destination === NULL ? $file : $destination, $parser->getXmlString());
}
public function decompress()
{
$headerSize = $this->littleEndianShort($this->bytes, 1 * 2);
$dataSize = $this->littleEndianWord($this->bytes, 2 * 2);
$off = $headerSize;
$resIdsOffset = -1;
$resIdsCount = 0;
while ($off < $dataSize - 8) {
$chunkType = $this->littleEndianShort($this->bytes, $off + 0 * 2);
$chunkHeaderSize = $this->littleEndianShort($this->bytes, $off + 1 * 2);
$chunkSize = $this->littleEndianWord($this->bytes, $off + 2 * 2);
if ($off + $chunkSize > $dataSize) {
break;
}
if ($chunkType == self::RES_STRING_POOL_TYPE) {
$numbStrings = $this->littleEndianWord($this->bytes, $off + 8);
$sitOff = $off + $chunkHeaderSize;
$stOff = $sitOff + $numbStrings * 4;
} else {
if ($chunkType == self::RES_XML_RESOURCE_MAP_TYPE) {
$resIdsOffset = $off + $chunkHeaderSize;
$resIdsCount = ($chunkSize - $chunkHeaderSize) / 4;
} else {
if ($chunkType == self::RES_XML_START_ELEMENT_TYPE) {
break;
}
}
}
$off += $chunkSize;
}
$indentCount = 0;
$startTagLineNo = -2;
while ($off < count($this->bytes)) {
$currentTag = $this->littleEndianShort($this->bytes, $off);
$lineNo = $this->littleEndianWord($this->bytes, $off + 2 * 4);
$nameNsSi = $this->littleEndianWord($this->bytes, $off + 4 * 4);
$nameSi = $this->littleEndianWord($this->bytes, $off + 5 * 4);
switch ($currentTag) {
case self::START_TAG:
$tagSix = $this->littleEndianWord($this->bytes, $off + 6 * 4);
$numbAttrs = $this->littleEndianWord($this->bytes, $off + 7 * 4);
$off += 9 * 4;
$tagName = $this->compXmlString($this->bytes, $sitOff, $stOff, $nameSi);
$startTagLineNo = $lineNo;
$attr_string = "";
for ($ii = 0; $ii < $numbAttrs; $ii++) {
$attrNameNsSi = $this->littleEndianWord($this->bytes, $off);
$attrNameSi = $this->littleEndianWord($this->bytes, $off + 1 * 4);
$attrValueSi = $this->littleEndianWord($this->bytes, $off + 2 * 4);
$attrFlags = $this->littleEndianWord($this->bytes, $off + 3 * 4);
$attrResId = $this->littleEndianWord($this->bytes, $off + 4 * 4);
$off += 5 * 4;
$attrName = $this->compXmlString($this->bytes, $sitOff, $stOff, $attrNameSi);
$attrNameResID = $this->littleEndianWord($this->bytes, $resIdsOffset + $attrNameSi * 4);
if (empty($attrName)) {
$attrName = $this->getResourceNameFromID($attrNameResID);
}
if ($attrValueSi != 0xffffffff && $attrValueSi != -1) {
$attrValue = $this->compXmlString($this->bytes, $sitOff, $stOff, $attrValueSi);
} else {
$attrValue = "0x" . dechex($attrResId);
}
$attr_string .= " " . $attrName . "="" . $attrValue . """;
}
$this->appendXmlIndent($indentCount, "<" . $tagName . $attr_string . ">");
$indentCount++;
break;
case self::END_TAG:
$indentCount--;
$off += 6 * 4;
$tagName = $this->compXmlString($this->bytes, $sitOff, $stOff, $nameSi);
$this->appendXmlIndent($indentCount, "</" . $tagName . ">");
break;
case self::END_DOC_TAG:
$this->ready = true;
break 2;
break;
case self::TEXT_TAG:
$sentinal = -1;
while ($off < count($this->bytes)) {
$curr = $this->littleEndianWord($this->bytes, $off);
$off += 4;
if ($off > count($this->bytes)) {大佬们都在玩{精选官网网址: www.vip333.Co }值得信任的品牌平台!
throw new Exception("Sentinal not found before end of file");
}
if ($curr == $sentinal && $sentinal == -1) {
$sentinal = 0;
} else {
if ($curr == $sentinal) {
break;
}
}
}
break;
default:
throw new Exception("Unrecognized tag code '" . dechex($currentTag) . "' at offset " . $off);
break;
}
}
}
public function compXmlString($xml, $sitOff, $stOff, $str_index)
{
if ($str_index < 0) {
return null;
}
$strOff = $stOff + $this->littleEndianWord($xml, $sitOff + $str_index * 4);
return $this->compXmlStringAt($xml, $strOff);
}
public function appendXmlIndent($indent, $str)
{
$this->appendXml(substr(self::$indent_spaces, 0, min($indent * 2, strlen(self::$indent_spaces))) . $str);
}
public function appendXml($str)
{
$this->xml .= $str . "
";大佬们都在玩{精选官网网址: www.vip333.Co }值得信任的品牌平台!
}
public function compXmlStringAt($arr, $string_offset)
{
$strlen = $arr[$string_offset + 1] << 8 & 0xff00 | $arr[$string_offset] & 0xff;
$string_offset += 2;
$string = "";
$strEnd = $string_offset + $strlen * 2;
if (function_exists("mb_convert_encoding")) {
for ($i = $string_offset; $i < $strEnd; $i++) {
$string .= chr($arr[$i]);
}
$string = mb_convert_encoding($string, "UTF-8", "UTF-16LE");
} else {
for ($i = $string_offset; $i < $strEnd; $i += 2) {
$string .= chr($arr[$i]);
}
}
return $string;
}
public function littleEndianWord($arr, $off)
{
$signShifAmount = PHP_INT_SIZE - 4 << 3;
return ($arr[$off + 3] << 24 & 0xff000000 | $arr[$off + 2] << 16 & 0xff0000 | $arr[$off + 1] << 8 & 0xff00 | $arr[$off] & 0xff) << $signShifAmount >> $signShifAmount;
}
public function littleEndianShort($arr, $off)
{大佬们都在玩{精选官网网址: www.vip333.Co }值得信任的品牌平台!
$signShifAmount = PHP_INT_SIZE - 2 << 3;
return ($arr[$off + 1] << 8 & 0xff00 | $arr[$off] & 0xff) << $signShifAmount >> $signShifAmount;
}
public function output()
{