From d7aa98322e42732d2d31f119009de24cfc5849eb Mon Sep 17 00:00:00 2001 From: REAndroid Date: Wed, 28 Dec 2022 14:13:50 -0500 Subject: [PATCH] Implement XML decoder --- .../lib/arsc/chunk/xml/ResXmlAttribute.java | 43 ++++++++++++++++++- .../lib/arsc/chunk/xml/ResXmlBlock.java | 43 ++++++++++++------- .../lib/arsc/chunk/xml/ResXmlElement.java | 33 ++++++++++++++ .../arsc/chunk/xml/ResXmlStartNamespace.java | 6 +++ 4 files changed, 108 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java index 6dac718..185055b 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java @@ -19,11 +19,16 @@ import com.reandroid.lib.arsc.array.ResXmlAttributeArray; import com.reandroid.lib.arsc.array.ResXmlIDArray; import com.reandroid.lib.arsc.base.Block; import com.reandroid.lib.arsc.container.FixedBlockContainer; +import com.reandroid.lib.arsc.decoder.ValueDecoder; +import com.reandroid.lib.arsc.group.EntryGroup; import com.reandroid.lib.arsc.item.*; import com.reandroid.lib.arsc.pool.ResXmlStringPool; import com.reandroid.lib.arsc.value.ValueType; +import com.reandroid.lib.common.EntryStore; import com.reandroid.lib.json.JSONConvert; import com.reandroid.lib.json.JSONObject; +import com.reandroid.xml.XMLAttribute; +import com.reandroid.xml.XMLException; import java.util.HashSet; import java.util.Set; @@ -406,7 +411,6 @@ import java.util.Set; } return name1.compareTo(name2); } - @Override public JSONObject toJson() { JSONObject jsonObject=new JSONObject(); @@ -444,6 +448,43 @@ import java.util.Set; setRawValue(json.getInt(NAME_data)); } } + public XMLAttribute decodeToXml(EntryStore entryStore, int currentPackageId) throws XMLException { + int resourceId=getNameResourceID(); + String name; + if(resourceId==0){ + name=getName(); + }else { + EntryGroup group = entryStore.getEntryGroup(resourceId); + if(group==null){ + throw new XMLException("Failed to decode attribute name: " + + String.format("0x%08x", resourceId)); + }else { + name=group.getSpecName(); + } + } + String prefix = getNamePrefix(); + if(prefix!=null){ + name=prefix+":"+name; + } + ValueType valueType=getValueType(); + int raw=getRawValue(); + String value; + if(valueType==ValueType.STRING){ + value = getValueAsString(); + }else { + value = ValueDecoder.decode(entryStore, + currentPackageId, + resourceId, + valueType, + raw); + } + XMLAttribute attribute = new XMLAttribute(name, value); + attribute.setNameId(resourceId); + if(valueType==ValueType.REFERENCE||valueType==ValueType.ATTRIBUTE){ + attribute.setValueId(raw); + } + return attribute; + } @Override public String toString(){ String fullName=getFullName(); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlBlock.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlBlock.java index 2fd56a6..3f96cd2 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlBlock.java @@ -15,24 +15,28 @@ */ package com.reandroid.lib.arsc.chunk.xml; -import com.reandroid.lib.arsc.chunk.ChunkType; -import com.reandroid.lib.arsc.chunk.BaseChunk; -import com.reandroid.lib.arsc.container.SingleBlockContainer; -import com.reandroid.lib.arsc.header.HeaderBlock; -import com.reandroid.lib.arsc.io.BlockReader; -import com.reandroid.lib.arsc.pool.ResXmlStringPool; -import com.reandroid.lib.arsc.value.ValueType; -import com.reandroid.lib.json.JSONConvert; -import com.reandroid.lib.json.JSONArray; -import com.reandroid.lib.json.JSONObject; + import com.reandroid.lib.arsc.chunk.BaseChunk; + import com.reandroid.lib.arsc.chunk.ChunkType; + import com.reandroid.lib.arsc.container.SingleBlockContainer; + import com.reandroid.lib.arsc.header.HeaderBlock; + import com.reandroid.lib.arsc.io.BlockReader; + import com.reandroid.lib.arsc.pool.ResXmlStringPool; + import com.reandroid.lib.arsc.value.ValueType; + import com.reandroid.lib.common.EntryStore; + import com.reandroid.lib.json.JSONArray; + import com.reandroid.lib.json.JSONConvert; + import com.reandroid.lib.json.JSONObject; + import com.reandroid.xml.XMLDocument; + import com.reandroid.xml.XMLElement; + import com.reandroid.xml.XMLException; -import java.io.*; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; + import java.io.*; + import java.util.ArrayList; + import java.util.HashSet; + import java.util.List; + import java.util.Set; -public class ResXmlBlock extends BaseChunk implements JSONConvert { + public class ResXmlBlock extends BaseChunk implements JSONConvert { private final ResXmlStringPool mResXmlStringPool; private final ResXmlIDMap mResXmlIDMap; private ResXmlElement mResXmlElement; @@ -205,6 +209,13 @@ public class ResXmlBlock extends BaseChunk implements JSONConvert { xmlElement.fromJson(json.optJSONObject(ResXmlBlock.NAME_element)); refresh(); } + public XMLDocument decodeToXml(EntryStore entryStore, int currentPackageId) throws XMLException { + XMLDocument xmlDocument = new XMLDocument(); + XMLElement xmlElement = getResXmlElement() + .decodeToXml(entryStore, currentPackageId); + xmlDocument.setDocumentElement(xmlElement); + return xmlDocument; + } private void onFromJson(JSONObject json){ List attributeList=recursiveAttributes(json.optJSONObject(ResXmlBlock.NAME_element)); buildResourceIds(attributeList); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java index 34ec844..42b3d44 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlElement.java @@ -24,9 +24,14 @@ import com.reandroid.lib.arsc.header.HeaderBlock; import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.ResXmlString; import com.reandroid.lib.arsc.pool.ResXmlStringPool; +import com.reandroid.lib.common.EntryStore; import com.reandroid.lib.json.JSONConvert; import com.reandroid.lib.json.JSONArray; import com.reandroid.lib.json.JSONObject; +import com.reandroid.xml.NameSpaceItem; +import com.reandroid.xml.XMLAttribute; +import com.reandroid.xml.XMLElement; +import com.reandroid.xml.XMLException; import java.io.IOException; @@ -705,6 +710,34 @@ import java.util.*; } start.calculatePositions(); } + + /** + * Decodes binary {@link ResXmlElement} to readable {@link XMLElement} + * @param entryStore : used for decoding attribute name and values + * @param currentPackageId : is id of current package defining this xml, used for + * decoding reference names e.g @{package.name}:string/entry_name + * */ + public XMLElement decodeToXml(EntryStore entryStore, int currentPackageId) throws XMLException { + XMLElement xmlElement = new XMLElement(getTagName()); + for(ResXmlStartNamespace startNamespace:getStartNamespaceList()){ + xmlElement.addAttribute(startNamespace.decodeToXml()); + } + for(ResXmlAttribute resXmlAttribute:listAttributes()){ + XMLAttribute xmlAttribute = + resXmlAttribute.decodeToXml(entryStore, currentPackageId); + xmlElement.addAttribute(xmlAttribute); + } + for(ResXmlElement childResXmlElement:listElements()){ + XMLElement childXMLElement = + childResXmlElement.decodeToXml(entryStore, currentPackageId); + xmlElement.addChild(childXMLElement); + } + ResXmlText resXmlText = getResXmlText(); + if(resXmlText!=null){ + xmlElement.setTextContent(resXmlText.getText()); + } + return xmlElement; + } @Override public String toString(){ ResXmlStartElement start = getStartElement(); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlStartNamespace.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlStartNamespace.java index cb77aaa..bc26292 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlStartNamespace.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlStartNamespace.java @@ -17,6 +17,9 @@ package com.reandroid.lib.arsc.chunk.xml; import com.reandroid.lib.arsc.chunk.ChunkType; import com.reandroid.lib.arsc.item.ResXmlString; +import com.reandroid.xml.NameSpaceItem; +import com.reandroid.xml.SchemaAttr; +import com.reandroid.xml.XMLAttribute; import java.util.Set; @@ -47,4 +50,7 @@ import java.util.Set; } return results; } + public XMLAttribute decodeToXml(){ + return new SchemaAttr(getPrefix(), getUri()); + } }