Commit a5035278 authored by Skylot's avatar Skylot

core: use resources ids in manifest decoding

parent ff093aee
......@@ -281,7 +281,7 @@ public class ClassNode extends LineAttrNode implements ILoadable {
if (field == null && obj instanceof Integer) {
String str = dex.root().getResourcesNames().get(obj);
if (str != null) {
return new ResRefField(dex, str);
return new ResRefField(dex, str.replace('/', '.'));
}
}
return field;
......
......@@ -12,7 +12,6 @@ import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.files.InputFile;
import jadx.core.xmlgen.ResTableParser;
import jadx.core.xmlgen.ResourceStorage;
import jadx.core.xmlgen.entry.ResourceEntry;
import java.io.IOException;
import java.io.InputStream;
......@@ -32,6 +31,10 @@ public class RootNode {
private final ErrorsCounter errorsCounter = new ErrorsCounter();
private List<DexNode> dexNodes;
/**
* Resources *
*/
private Map<Integer, String> resourcesNames = new HashMap<Integer, String>();
@Nullable
private String appPackage;
......@@ -95,10 +98,7 @@ public class RootNode {
}
ResourceStorage resStorage = parser.getResStorage();
appPackage = resStorage.getAppPackage();
for (ResourceEntry entry : resStorage.getResources()) {
resourcesNames.put(entry.getId(), entry.getTypeName() + "." + entry.getKeyName());
}
resourcesNames = resStorage.getResourcesNames();
}
public void initAppResClass() {
......
......@@ -7,6 +7,7 @@ import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.xmlgen.entry.ValuesParser;
import java.io.IOException;
import java.io.InputStream;
......@@ -42,8 +43,10 @@ public class BinaryXMLParser extends CommonBinaryParser {
private boolean firstElement;
private boolean wasOneLiner = false;
private Map<Integer, String> styleMap = new HashMap<Integer, String>();
private Map<Integer, FieldNode> localStyleMap = new HashMap<Integer, FieldNode>();
private final Map<Integer, String> styleMap = new HashMap<Integer, String>();
private final Map<Integer, FieldNode> localStyleMap = new HashMap<Integer, FieldNode>();
private final Map<Integer, String> resNames;
private ValuesParser valuesParser;
private final ManifestAttributes attributes;
......@@ -62,6 +65,9 @@ public class BinaryXMLParser extends CommonBinaryParser {
}
}
}
resNames = root.getResourcesNames();
attributes = new ManifestAttributes();
attributes.parse();
} catch (Exception e) {
......@@ -103,6 +109,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
break;
case RES_STRING_POOL_TYPE:
strings = parseStringPoolNoType();
valuesParser = new ValuesParser(strings, resNames);
break;
case RES_XML_RESOURCE_MAP_TYPE:
parseResourceMap();
......@@ -121,7 +128,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
break;
default:
die("Type: " + Integer.toHexString(type) + " not yet implemented");
die("Type: 0x" + Integer.toHexString(type) + " not yet implemented");
break;
}
}
......@@ -244,48 +251,32 @@ public class BinaryXMLParser extends CommonBinaryParser {
}
private void decodeAttribute(int attributeNS, int attrValDataType, int attrValData) {
switch (attrValDataType) {
case 0x3:
writer.add(strings[attrValData]);
break;
case 0x10:
writer.add(String.valueOf(attrValData));
break;
case 0x12:
// FIXME: What to do, when data is always -1?
if (attrValData == 0) {
writer.add("false");
} else if (attrValData == 1 || attrValData == -1) {
writer.add("true");
} else {
writer.add("UNKNOWN_BOOLEAN_TYPE");
if (attrValDataType == TYPE_REFERENCE) {
// reference custom processing
String name = styleMap.get(attrValData);
if (name != null) {
writer.add("@*");
if (attributeNS != -1) {
writer.add(nsPrefix).add(':');
}
break;
case 0x1:
String name = styleMap.get(attrValData);
if (name != null) {
writer.add("@*");
if (attributeNS != -1) {
writer.add(nsPrefix).add(':');
}
writer.add("style/").add(name.replaceAll("_", "."));
writer.add("style/").add(name.replaceAll("_", "."));
} else {
FieldNode field = localStyleMap.get(attrValData);
if (field != null) {
String cls = field.getParentClass().getShortName().toLowerCase();
writer.add("@").add(cls).add("/").add(field.getName());
} else {
FieldNode field = localStyleMap.get(attrValData);
if (field != null) {
String cls = field.getParentClass().getShortName().toLowerCase();
writer.add("@").add(cls).add("/").add(field.getName());
String resName = resNames.get(attrValData);
if (resName != null) {
writer.add("@").add(resName);
} else {
writer.add("0x").add(Integer.toHexString(attrValData));
}
}
break;
default:
writer.add("UNKNOWN_DATA_TYPE_0x" + Integer.toHexString(attrValDataType));
break;
}
} else {
String str = valuesParser.decodeValue(attrValDataType, attrValData);
writer.add(str);
}
}
......
......@@ -71,7 +71,10 @@ public class ResTableParser extends CommonBinaryParser {
}
CodeWriter writer = new CodeWriter();
ValuesParser vp = new ValuesParser(strings, resStorage);
writer.add("app package: ").add(resStorage.getAppPackage());
writer.startLine();
ValuesParser vp = new ValuesParser(strings, resStorage.getResourcesNames());
for (ResourceEntry ri : resStorage.getResources()) {
writer.startLine(ri + ": " + vp.getValueString(ri));
}
......
......@@ -7,7 +7,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ResourceStorage {
......@@ -49,4 +51,12 @@ public class ResourceStorage {
public void setAppPackage(String appPackage) {
this.appPackage = appPackage;
}
public Map<Integer, String> getResourcesNames() {
Map<Integer, String> map = new HashMap<Integer, String>();
for (ResourceEntry entry : list) {
map.put(entry.getId(), entry.getTypeName() + "/" + entry.getKeyName());
}
return map;
}
}
......@@ -73,14 +73,6 @@ public final class ResourceEntry {
return config;
}
public String formatAsRef() {
return "@" + typeName + "/" + keyName;
}
public String formatAsAttribute() {
return "?" + typeName + "/" + keyName;
}
@Override
public String toString() {
return " 0x" + Integer.toHexString(id) + " (" + id + ")" + config + " = " + typeName + "." + keyName;
......
package jadx.core.xmlgen.entry;
import jadx.core.xmlgen.ParserConstants;
import jadx.core.xmlgen.ResourceStorage;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -14,11 +14,11 @@ public class ValuesParser extends ParserConstants {
private static final Logger LOG = LoggerFactory.getLogger(ValuesParser.class);
private final String[] strings;
private final ResourceStorage resStorage;
private final Map<Integer, String> resMap;
public ValuesParser(String[] strings, ResourceStorage resourceStorage) {
public ValuesParser(String[] strings, Map<Integer, String> resMap) {
this.strings = strings;
this.resStorage = resourceStorage;
this.resMap = resMap;
}
public String getValueString(ResourceEntry ri) {
......@@ -43,6 +43,10 @@ public class ValuesParser extends ParserConstants {
public String decodeValue(RawValue value) {
int dataType = value.getDataType();
int data = value.getData();
return decodeValue(dataType, data);
}
public String decodeValue(int dataType, int data) {
switch (dataType) {
case TYPE_NULL:
return null;
......@@ -67,19 +71,19 @@ public class ValuesParser extends ParserConstants {
return String.format("#%03x", data & 0xFFF);
case TYPE_REFERENCE: {
ResourceEntry ri = resStorage.getByRef(data);
String ri = resMap.get(data);
if (ri == null) {
return "?unknown_ref: " + Integer.toHexString(data);
}
return ri.formatAsRef();
return "@" + ri;
}
case TYPE_ATTRIBUTE: {
ResourceEntry ri = resStorage.getByRef(data);
String ri = resMap.get(data);
if (ri == null) {
return "?unknown_ref: " + Integer.toHexString(data);
return "?unknown_attr_ref: " + Integer.toHexString(data);
}
return ri.formatAsAttribute();
return "?" + ri;
}
case TYPE_DIMENSION:
......@@ -101,9 +105,9 @@ public class ValuesParser extends ParserConstants {
return null;
}
}
ResourceEntry ri = resStorage.getByRef(ref);
String ri = resMap.get(ref);
if (ri != null) {
return ri.getTypeName() + "." + ri.getKeyName();
return ri.replace('/', '.');
}
return "?0x" + Integer.toHexString(nameRef);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment