fix: use resource table file name as prefix in sub files (#2373)

This commit is contained in:
Skylot
2025-05-29 22:58:54 +01:00
parent 6b54cde89c
commit 3374f9b64a
6 changed files with 30 additions and 6 deletions
@@ -160,6 +160,7 @@ public final class ResourcesLoader implements IResourcesLoader {
if (parser == null) {
throw new JadxRuntimeException("Unknown type of resource file: " + resFile.getOriginalName());
}
parser.setBaseFileName(resFile.getDeobfName());
parser.decode(is);
return parser;
}
@@ -12,4 +12,8 @@ public interface IResTableParser {
ResourceStorage getResStorage();
BinaryXMLStrings getStrings();
default void setBaseFileName(String fileName) {
// optional
}
}
@@ -67,6 +67,7 @@ public class ResTableBinaryParser extends CommonBinaryParser implements IResTabl
private ResourceStorage resStorage;
private BinaryXMLStrings strings;
private String baseFileName = "";
public ResTableBinaryParser(RootNode root) {
this(root, false);
@@ -77,6 +78,11 @@ public class ResTableBinaryParser extends CommonBinaryParser implements IResTabl
this.useRawResName = useRawResNames;
}
@Override
public void setBaseFileName(String fileName) {
this.baseFileName = fileName;
}
@Override
public void decode(InputStream inputStream) throws IOException {
long start = System.currentTimeMillis();
@@ -96,8 +102,8 @@ public class ResTableBinaryParser extends CommonBinaryParser implements IResTabl
ResXmlGen resGen = new ResXmlGen(resStorage, vp, root.initManifestAttributes());
ICodeInfo content = XmlGenUtils.makeXmlDump(root.makeCodeWriter(), resStorage);
List<ResContainer> xmlFiles = resGen.makeResourcesXml(root.getArgs());
return ResContainer.resourceTable("res", xmlFiles, content);
List<ResContainer> xmlFiles = resGen.makeResourcesXml(root.getArgs(), baseFileName);
return ResContainer.resourceTable(baseFileName, xmlFiles, content);
}
void decodeTableChunk() throws IOException {
@@ -52,6 +52,10 @@ public class ResXmlGen {
}
public List<ResContainer> makeResourcesXml(JadxArgs args) {
return makeResourcesXml(args, "");
}
public List<ResContainer> makeResourcesXml(JadxArgs args, String baseFileName) {
Map<String, ICodeWriter> contMap = new HashMap<>();
for (ResourceEntry ri : resStorage.getResources()) {
if (SKIP_RES_TYPES.contains(ri.getTypeName())) {
@@ -68,7 +72,7 @@ public class ResXmlGen {
}
addValue(cw, ri);
}
String filePrefix = baseFileName.isEmpty() ? null : baseFileName + ':';
List<ResContainer> files = new ArrayList<>(contMap.size());
for (Map.Entry<String, ICodeWriter> entry : contMap.entrySet()) {
String fileName = entry.getKey();
@@ -76,6 +80,9 @@ public class ResXmlGen {
content.decIndent();
content.startLine("</resources>");
ICodeInfo codeInfo = content.finish();
if (filePrefix != null) {
fileName = filePrefix + fileName;
}
files.add(ResContainer.textResource(fileName, codeInfo));
}
Collections.sort(files);
@@ -75,7 +75,7 @@ public class JadxDecompilerTest {
.findFirst().orElseThrow();
ResContainer resContainer = arsc.loadContent();
ResContainer xmlRes = resContainer.getSubFiles().stream()
.filter(r -> r.getName().equals("res/values/colors.xml"))
.filter(r -> r.getName().equals("resources.arsc:res/values/colors.xml"))
.findFirst().orElseThrow();
assertThat(xmlRes.getText())
.code()
@@ -27,11 +27,17 @@ import jadx.core.xmlgen.entry.ValuesParser;
public class ResTableProtoParser extends CommonProtoParser implements IResTableParser {
private final RootNode root;
private ResourceStorage resStorage;
private String baseFileName = "";
public ResTableProtoParser(RootNode root) {
this.root = root;
}
@Override
public void setBaseFileName(String fileName) {
this.baseFileName = fileName;
}
@Override
public void decode(InputStream inputStream) throws IOException {
resStorage = new ResourceStorage(root.getArgs().getSecurity());
@@ -47,8 +53,8 @@ public class ResTableProtoParser extends CommonProtoParser implements IResTableP
ValuesParser vp = new ValuesParser(new BinaryXMLStrings(), resStorage.getResourcesNames());
ResXmlGen resGen = new ResXmlGen(resStorage, vp, root.initManifestAttributes());
ICodeInfo content = XmlGenUtils.makeXmlDump(root.makeCodeWriter(), resStorage);
List<ResContainer> xmlFiles = resGen.makeResourcesXml(root.getArgs());
return ResContainer.resourceTable("res", xmlFiles, content);
List<ResContainer> xmlFiles = resGen.makeResourcesXml(root.getArgs(), baseFileName);
return ResContainer.resourceTable(baseFileName, xmlFiles, content);
}
private void parse(Package p) {