diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java index bbe98d3a5..6ac04faa5 100644 --- a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java +++ b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java @@ -32,6 +32,12 @@ public class JadxCLIArgs implements IJadxArgs { @Parameter(names = {"-d", "--output-dir"}, description = "output directory") protected String outDirName; + @Parameter(names = {"-ds", "--output-dir-src"}, description = "output directory for sources") + protected String outDirNameSrc; + + @Parameter(names = {"-dr", "--output-dir-res"}, description = "output directory for resources") + protected String outDirNameRes; + @Parameter(names = {"-j", "--threads-count"}, description = "processing threads count") protected int threadsCount = DEFAULT_THREADS_COUNT; @@ -90,6 +96,8 @@ public class JadxCLIArgs implements IJadxArgs { private final List input = new ArrayList<>(1); private File outputDir; + private File outputDirSrc; + private File outputDirRes; public boolean processArgs(String[] args) { return parse(args) && process(); @@ -128,9 +136,22 @@ public class JadxCLIArgs implements IJadxArgs { if (input.size() > 1) { throw new JadxException("Only one input file is supported"); } + if(outDirNameSrc != null) { + outputDirSrc = new File(outDirNameSrc); + } + if(outDirNameRes != null) { + outputDirRes = new File(outDirNameRes); + } if (outDirName != null) { outputDir = new File(outDirName); + if(outputDirSrc == null) { + outputDirSrc = new File(outputDir, "source"); + } + if(outputDirRes == null) { + outputDirRes = new File(outputDir, "res"); + } } + if (isVerbose()) { ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); @@ -207,6 +228,16 @@ public class JadxCLIArgs implements IJadxArgs { return outputDir; } + @Override + public File getOutDirSrc() { + return outputDirSrc; + } + + @Override + public File getOutDirRes() { + return outputDirRes; + } + public void setOutputDir(File outputDir) { this.outputDir = outputDir; } diff --git a/jadx-core/src/main/java/jadx/api/IJadxArgs.java b/jadx-core/src/main/java/jadx/api/IJadxArgs.java index ea8dbfcb0..8a0d30370 100644 --- a/jadx-core/src/main/java/jadx/api/IJadxArgs.java +++ b/jadx-core/src/main/java/jadx/api/IJadxArgs.java @@ -4,6 +4,10 @@ import java.io.File; public interface IJadxArgs { File getOutDir(); + + File getOutDirSrc(); + + File getOutDirRes(); int getThreadsCount(); diff --git a/jadx-core/src/main/java/jadx/api/JadxArgs.java b/jadx-core/src/main/java/jadx/api/JadxArgs.java index 8dc0f9f4b..e3dfa8e9a 100644 --- a/jadx-core/src/main/java/jadx/api/JadxArgs.java +++ b/jadx-core/src/main/java/jadx/api/JadxArgs.java @@ -5,6 +5,8 @@ import java.io.File; public class JadxArgs implements IJadxArgs { private File outDir = new File("jadx-output"); + private File outDirSrc = new File(outDir, "source"); + private File outDirRes = new File(outDir, "res"); private int threadsCount = Math.max(1, Runtime.getRuntime().availableProcessors() - 1); private boolean cfgOutput = false; @@ -39,6 +41,24 @@ public class JadxArgs implements IJadxArgs { this.outDir = outDir; } + @Override + public File getOutDirSrc() { + return outDirSrc; + } + + public void setOutDirSrc(File outDirSrc) { + this.outDirSrc = outDirSrc; + } + + @Override + public File getOutDirRes() { + return outDirRes; + } + + public void setOutDirRes(File outDirRes) { + this.outDirRes = outDirRes; + } + @Override public int getThreadsCount() { return threadsCount; diff --git a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java index 680e9b977..cdc3ee6b4 100644 --- a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java +++ b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java @@ -11,7 +11,6 @@ import jadx.core.dex.nodes.RootNode; import jadx.core.dex.visitors.IDexTreeVisitor; import jadx.core.dex.visitors.SaveCode; import jadx.core.export.ExportGradleProject; -import jadx.core.utils.exceptions.DecodeException; import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.files.InputFile; @@ -57,6 +56,8 @@ public final class JadxDecompiler { private final List inputFiles = new ArrayList<>(); private File outDir; + private File outDirRes; + private File outDirSrc; private RootNode root; private List passes; @@ -71,26 +72,52 @@ public final class JadxDecompiler { private Map methodsMap = new ConcurrentHashMap<>(); private Map fieldsMap = new ConcurrentHashMap<>(); - public JadxDecompiler() { + public JadxDecompiler() throws JadxException { this(new JadxArgs()); } - public JadxDecompiler(IJadxArgs jadxArgs) { + public JadxDecompiler(IJadxArgs jadxArgs) throws JadxException { this.args = jadxArgs; this.outDir = jadxArgs.getOutDir(); + this.outDirSrc = jadxArgs.getOutDirSrc(); + this.outDirRes = jadxArgs.getOutDirRes(); reset(); init(); } - public void setOutputDir(File outDir) { + public void setOutputDir(File outDir) throws JadxException { this.outDir = outDir; init(); } - void init() { + public void setOutputDirSrc(File outDirSrc) throws JadxException { + this.outDirSrc = outDirSrc; + init(); + } + + public void setOutputDirRes(File outDirRes) throws JadxException { + this.outDirRes = outDirRes; + init(); + } + + void init() throws JadxException { + if(outDir == null && outDirSrc == null) { + outDirSrc = new JadxArgs().getOutDirSrc(); + } + if(outDir == null && outDirRes == null) { + outDirRes = new JadxArgs().getOutDirRes(); + } if (outDir == null) { outDir = new JadxArgs().getOutDir(); } + else { + if(outDirSrc == null && outDirRes != null && !args.isSkipSources()) { + throw new JadxException("--output-dir-src must be specified"); + } + if(outDirSrc != null && outDirRes == null && !args.isSkipResources()) { + throw new JadxException("--output-dir-res must be specified"); + } + } this.passes = Jadx.getPassesList(args, outDir); this.codeGen = new CodeGen(args); } @@ -172,8 +199,8 @@ public final class JadxDecompiler { sourcesOutDir = export.getSrcOutDir(); resOutDir = export.getResOutDir(); } else { - sourcesOutDir = outDir; - resOutDir = outDir; + sourcesOutDir = outDirSrc; + resOutDir = outDirRes; } if (saveSources) { appendSourcesSave(executor, sourcesOutDir); @@ -267,7 +294,7 @@ public final class JadxDecompiler { root.getErrorsCounter().printReport(); } - void parse() throws DecodeException { + void parse() throws JadxException { reset(); init(); diff --git a/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java b/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java index c43271eb9..4aab04b17 100644 --- a/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java +++ b/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java @@ -83,8 +83,9 @@ public abstract class IntegrationTest extends TestUtils { } public ClassNode getClassNodeFromFile(File file, String clsName) { - JadxDecompiler d = new JadxDecompiler(args); + JadxDecompiler d = null; try { + d = new JadxDecompiler(args); d.loadFile(file); } catch (JadxException e) { e.printStackTrace();