fix(xapk): support files in sub-dirs in xapk (#2834)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
package jadx.gui.treemodel;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -27,6 +26,7 @@ public class JRoot extends JNode {
|
||||
private static final long serialVersionUID = 8888495789773527342L;
|
||||
|
||||
private static final ImageIcon ROOT_ICON = UiUtils.openSvgIcon("nodes/rootPackageFolder");
|
||||
private static final Pattern SPLIT_PATH_PATTERN = Pattern.compile("[/\\\\]+");
|
||||
|
||||
private final transient JadxWrapper wrapper;
|
||||
private final transient MainWindow mainWindow;
|
||||
@@ -56,15 +56,9 @@ public class JRoot extends JNode {
|
||||
|
||||
private JResource getHierarchyResources(List<ResourceFile> resources) {
|
||||
JResource root = new JResource(null, NLS.str("tree.resources_title"), JResType.ROOT);
|
||||
String splitPathStr = Pattern.quote(File.separator);
|
||||
for (ResourceFile rf : resources) {
|
||||
String rfName;
|
||||
if (rf.getZipEntry() != null) {
|
||||
rfName = rf.getDeobfName();
|
||||
} else {
|
||||
rfName = new File(rf.getDeobfName()).getName();
|
||||
}
|
||||
String[] parts = new File(rfName).getPath().split(splitPathStr);
|
||||
String rfName = rf.getDeobfName();
|
||||
String[] parts = SPLIT_PATH_PATTERN.split(rfName);
|
||||
JResource curRf = root;
|
||||
int count = parts.length;
|
||||
for (int i = 0; i < count - 1; i++) {
|
||||
|
||||
+14
-1
@@ -7,12 +7,14 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jadx.api.ResourceFile;
|
||||
import jadx.api.ResourceType;
|
||||
import jadx.api.ResourcesLoader;
|
||||
import jadx.api.plugins.CustomResourcesLoader;
|
||||
import jadx.api.plugins.JadxPluginContext;
|
||||
import jadx.api.plugins.input.ICodeLoader;
|
||||
import jadx.api.plugins.input.JadxCodeInput;
|
||||
import jadx.api.plugins.input.data.impl.EmptyCodeLoader;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
import jadx.plugins.input.dex.DexInputPlugin;
|
||||
import jadx.plugins.input.xapk.data.XApkData;
|
||||
|
||||
@@ -51,7 +53,18 @@ public class XApkCustomInput implements JadxCodeInput, CustomResourcesLoader {
|
||||
resLoader.defaultLoadFile(list, apkPath.toFile(), apkPath.getFileName() + "/");
|
||||
}
|
||||
for (Path filePath : xApkData.getFiles()) {
|
||||
resLoader.defaultLoadFile(list, filePath.toFile(), "");
|
||||
File innerFile = filePath.toFile();
|
||||
String relativePath = xApkData.getTmpDir().relativize(filePath).toString();
|
||||
if (FileUtils.isZipFile(innerFile)) {
|
||||
// zip will be unpacked by default loader
|
||||
resLoader.defaultLoadFile(list, innerFile, relativePath + "/");
|
||||
} else {
|
||||
// create resource to file in tmp folder, but with name relative to xapk root
|
||||
ResourceType type = ResourceType.getFileType(relativePath);
|
||||
ResourceFile resFile = ResourceFile.createResourceFile(context.getDecompiler(), innerFile, type);
|
||||
resFile.setDeobfName(relativePath);
|
||||
list.add(resFile);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+23
-14
@@ -75,25 +75,34 @@ public class XApkLoader {
|
||||
}
|
||||
}
|
||||
|
||||
private XApkData unpackXApk(File xapkFile, XApkManifest xApkManifest, ZipContent content) throws IOException {
|
||||
Set<String> declaredApks = xApkManifest.getSplitApks().stream()
|
||||
.map(SplitApk::getFile).collect(Collectors.toSet());
|
||||
private XApkData unpackXApk(File xapkFile, XApkManifest xApkManifest, ZipContent content) {
|
||||
Set<String> declaredApks = xApkManifest.getSplitApks()
|
||||
.stream()
|
||||
.map(SplitApk::getFile)
|
||||
.collect(Collectors.toSet());
|
||||
List<Path> apks = new ArrayList<>(declaredApks.size());
|
||||
List<Path> files = new ArrayList<>();
|
||||
|
||||
String dirName = xapkFile.getName() + '_' + System.currentTimeMillis();
|
||||
List<Path> files = new ArrayList<>(content.getEntries().size());
|
||||
String dirName = FileUtils.md5Sum(xapkFile.getAbsolutePath());
|
||||
Path tmpDir = context.files().getPluginTempDir().resolve(dirName);
|
||||
FileUtils.makeDirs(tmpDir);
|
||||
for (IZipEntry entry : content.getEntries()) {
|
||||
String fileName = entry.getName();
|
||||
Path file = tmpDir.resolve(fileName);
|
||||
try (InputStream inputStream = entry.getInputStream()) {
|
||||
Files.copy(inputStream, file, StandardCopyOption.REPLACE_EXISTING);
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
if (declaredApks.contains(fileName)) {
|
||||
apks.add(file);
|
||||
} else {
|
||||
files.add(file);
|
||||
try {
|
||||
String fileName = entry.getName();
|
||||
Path file = tmpDir.resolve(fileName);
|
||||
FileUtils.makeDirsForFile(file);
|
||||
try (InputStream inputStream = entry.getInputStream()) {
|
||||
Files.copy(inputStream, file, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
if (declaredApks.contains(fileName)) {
|
||||
apks.add(file);
|
||||
} else {
|
||||
files.add(file);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to unpack XApk entry: {}", entry.getName(), e);
|
||||
}
|
||||
}
|
||||
return new XApkData(xApkManifest, tmpDir, apks, files);
|
||||
|
||||
Reference in New Issue
Block a user