fix(res): resolve custom attributes

This commit is contained in:
nitram84
2023-04-07 14:58:33 +02:00
committed by skylot
parent 058a5e3bb2
commit e1aa9f6de4
3 changed files with 46 additions and 3 deletions
@@ -43,6 +43,7 @@ import jadx.core.utils.Utils;
import jadx.core.utils.android.AndroidResourcesUtils;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.xmlgen.IResParser;
import jadx.core.xmlgen.ManifestAttributes;
import jadx.core.xmlgen.ResDecoder;
import jadx.core.xmlgen.ResourceStorage;
import jadx.core.xmlgen.entry.ResourceEntry;
@@ -174,12 +175,18 @@ public class RootNode {
if (parser != null) {
processResources(parser.getResStorage());
updateObfuscatedFiles(parser, resources);
updateManifestAttribMap(parser);
}
} catch (Exception e) {
LOG.error("Failed to parse '.arsc' file", e);
}
}
private void updateManifestAttribMap(IResParser parser) {
ManifestAttributes manifestAttributes = ManifestAttributes.getInstance();
manifestAttributes.updateAttributes(parser);
}
private @Nullable ResourceFile getResourceFile(List<ResourceFile> resources) {
for (ResourceFile rf : resources) {
if (rf.getType() == ResourceType.ARSC) {
@@ -17,6 +17,9 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.xmlgen.entry.RawNamedValue;
import jadx.core.xmlgen.entry.ResourceEntry;
import jadx.core.xmlgen.entry.ValuesParser;
public class ManifestAttributes {
private static final Logger LOG = LoggerFactory.getLogger(ManifestAttributes.class);
@@ -52,6 +55,8 @@ public class ManifestAttributes {
private final Map<String, MAttr> attrMap = new HashMap<>();
private final Map<String, MAttr> appAttrMap = new HashMap<>();
private static ManifestAttributes instance;
public static ManifestAttributes getInstance() {
@@ -168,7 +173,10 @@ public class ManifestAttributes {
public String decode(String attrName, long value) {
MAttr attr = attrMap.get(attrName);
if (attr == null) {
return null;
attr = appAttrMap.get(attrName);
if (attr == null) {
return null;
}
}
if (attr.getType() == MAttrType.ENUM) {
return attr.getValues().get(value);
@@ -190,4 +198,32 @@ public class ManifestAttributes {
}
return null;
}
public void updateAttributes(IResParser parser) {
appAttrMap.clear();
ResourceStorage resStorage = parser.getResStorage();
ValuesParser vp = new ValuesParser(parser.getStrings(), resStorage.getResourcesNames());
for (ResourceEntry ri : resStorage.getResources()) {
if (ri.getTypeName().equals("attr") && ri.getNamedValues().size() > 1) {
RawNamedValue first = ri.getNamedValues().get(0);
MAttrType attrTyp;
if (first.getRawValue().getData() == ValuesParser.ATTR_TYPE_FLAGS) {
attrTyp = MAttrType.FLAG;
} else if (first.getRawValue().getData() == ValuesParser.ATTR_TYPE_ENUM) {
attrTyp = MAttrType.ENUM;
} else {
continue;
}
MAttr attr = new MAttr(attrTyp);
for (int i = 1; i < ri.getNamedValues().size(); i++) {
RawNamedValue rv = ri.getNamedValues().get(i);
String value = vp.decodeNameRef(rv.getNameRef());
attr.getValues().put((long) rv.getRawValue().getData(), value.startsWith("id.") ? value.substring(3) : value);
}
appAttrMap.put(ri.getKeyName(), attr);
}
}
}
}
@@ -177,7 +177,7 @@ public class ResXmlGen {
if (dataType == ParserConstants.TYPE_INT_DEC && nameStr != null) {
try {
int intVal = Integer.parseInt(valueStr);
String newVal = ManifestAttributes.getInstance().decode(nameStr.replace("android:attr.", ""), intVal);
String newVal = ManifestAttributes.getInstance().decode(nameStr.replace("android:", "").replace("attr.", ""), intVal);
if (newVal != null) {
valueStr = newVal;
}
@@ -188,7 +188,7 @@ public class ResXmlGen {
if (dataType == ParserConstants.TYPE_INT_HEX && nameStr != null) {
try {
int intVal = Integer.decode(valueStr);
String newVal = ManifestAttributes.getInstance().decode(nameStr.replace("android:attr.", ""), intVal);
String newVal = ManifestAttributes.getInstance().decode(nameStr.replace("android:", "").replace("attr.", ""), intVal);
if (newVal != null) {
valueStr = newVal;
}