diff --git a/README.md b/README.md
index 20b79507b..a0fa8b4ab 100644
--- a/README.md
+++ b/README.md
@@ -8,16 +8,19 @@


[](https://search.maven.org/search?q=g:io.github.skylot%20AND%20jadx)
+
[](http://www.apache.org/licenses/LICENSE-2.0.html)
**jadx** - Dex to Java decompiler
Command line and GUI tools for producing Java source code from Android Dex and Apk files
-:exclamation::exclamation::exclamation: Please note that in most cases **jadx** can't decompile all 100% of the code, so errors will occur. Check [Troubleshooting guide](https://github.com/skylot/jadx/wiki/Troubleshooting-Q&A#decompilation-issues) for workarounds
+> [!WARNING]
+> Please note that in most cases **jadx** can't decompile all 100% of the code, so errors will occur.
+> Check [Troubleshooting guide](https://github.com/skylot/jadx/wiki/Troubleshooting-Q&A#decompilation-issues) for workarounds.
**Main features:**
-- decompile Dalvik bytecode to java classes from APK, dex, aar, aab and zip files
+- decompile Dalvik bytecode to Java code from APK, dex, aar, aab and zip files
- decode `AndroidManifest.xml` and other resources from `resources.arsc`
- deobfuscator included
@@ -79,7 +82,7 @@ and also packed to `build/jadx-.zip`
### Usage
```
-jadx[-gui] [command] [options] (.apk, .dex, .jar, .class, .smali, .zip, .aar, .arsc, .aab, .xapk)
+jadx[-gui] [command] [options] (.apk, .dex, .jar, .class, .smali, .zip, .aar, .arsc, .aab, .xapk, .jadx.kts)
commands (use ' --help' for command options):
plugins - manage jadx plugins
@@ -171,8 +174,8 @@ Plugin options (-P=):
- kotlin-metadata.to-string - rename fields using toString, values: [yes, no], default: yes
- kotlin-metadata.getters - rename simple getters to field names, values: [yes, no], default: yes
4) rename-mappings: various mappings support
- - rename-mappings.format - mapping format, values: [auto, TINY, TINY_2, ENIGMA, ENIGMA_DIR, MCP, SRG, TSRG, TSRG2, PROGUARD], default: auto
- - rename-mappings.invert - invert mapping, values: [yes, no], default: no
+ - rename-mappings.format - mapping format, values: [AUTO, TINY_FILE, TINY_2_FILE, ENIGMA_FILE, ENIGMA_DIR, SRG_FILE, XSRG_FILE, CSRG_FILE, TSRG_FILE, TSRG_2_FILE, PROGUARD_FILE], default: AUTO
+ - rename-mappings.invert - invert mapping on load, values: [yes, no], default: no
Environment variables:
JADX_DISABLE_ZIP_SECURITY - set to 'true' to disable all security checks for zip files
@@ -186,7 +189,7 @@ Examples:
jadx --log-level ERROR app.apk
jadx -Pdex-input.verify-checksum=no app.apk
```
-These options also worked on jadx-gui running from command line and override options from preferences dialog
+These options also work in jadx-gui running from command line and override options from preferences' dialog
### Troubleshooting
Please check wiki page [Troubleshooting Q&A](https://github.com/skylot/jadx/wiki/Troubleshooting-Q&A)
diff --git a/jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java b/jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java
index 33f7d34ca..2f4f29f6d 100644
--- a/jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java
+++ b/jadx-cli/src/main/java/jadx/cli/JCommanderWrapper.java
@@ -17,7 +17,6 @@ import com.beust.jcommander.ParameterDescription;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameterized;
-import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;
import jadx.api.plugins.JadxPluginInfo;
import jadx.api.plugins.options.JadxPluginOptions;
@@ -165,7 +164,7 @@ public class JCommanderWrapper {
opt.append("- ").append(description);
}
if (addDefaults) {
- String defaultValue = getDefaultValue(args, f, opt);
+ String defaultValue = getDefaultValue(args, f);
if (defaultValue != null && !description.contains("(default)")) {
opt.append(", default: ").append(defaultValue);
}
@@ -188,7 +187,7 @@ public class JCommanderWrapper {
}
@Nullable
- private static String getDefaultValue(Object args, Field f, StringBuilder opt) {
+ private static String getDefaultValue(Object args, Field f) {
try {
Class> fieldType = f.getType();
if (fieldType == int.class) {
@@ -219,7 +218,7 @@ public class JCommanderWrapper {
StringBuilder sb = new StringBuilder();
int k = 1;
// load and init all options plugins to print all options
- try (JadxDecompiler decompiler = new JadxDecompiler(new JadxArgs())) {
+ try (JadxDecompiler decompiler = new JadxDecompiler(argsObj.toJadxArgs())) {
JadxPluginManager pluginManager = decompiler.getPluginManager();
pluginManager.load(new JadxExternalPluginsLoader());
pluginManager.initAll();
diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
index a8f66babd..6c99e7feb 100644
--- a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
+++ b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
@@ -34,7 +34,7 @@ import jadx.core.utils.files.FileUtils;
public class JadxCLIArgs {
- @Parameter(description = " (.apk, .dex, .jar, .class, .smali, .zip, .aar, .arsc, .aab, .xapk)")
+ @Parameter(description = " (.apk, .dex, .jar, .class, .smali, .zip, .aar, .arsc, .aab, .xapk, .jadx.kts)")
protected List files = new ArrayList<>(1);
@Parameter(names = { "-d", "--output-dir" }, description = "output directory")
diff --git a/jadx-core/src/main/java/jadx/api/plugins/options/OptionFlag.java b/jadx-core/src/main/java/jadx/api/plugins/options/OptionFlag.java
index d36b18315..d826b9323 100644
--- a/jadx-core/src/main/java/jadx/api/plugins/options/OptionFlag.java
+++ b/jadx-core/src/main/java/jadx/api/plugins/options/OptionFlag.java
@@ -12,12 +12,12 @@ public enum OptionFlag {
HIDE_IN_GUI,
/**
- * Do not show this option in jadx-gui (useful if option is configured with custom ui)
+ * Option will be read-only in jadx-gui (can be used for calculated properties)
*/
DISABLE_IN_GUI,
/**
- * Add this flag only if option do not affect generated code.
+ * Add this flag only if the option does not affect generated code.
* If added, option value change will not cause code cache reset.
*/
NOT_CHANGING_CODE,
diff --git a/jadx-plugins/jadx-script/examples/scripts/deobf/deobf.jadx.kts b/jadx-plugins/jadx-script/examples/scripts/deobf/deobf.jadx.kts
index 7173f7d65..e36c54176 100644
--- a/jadx-plugins/jadx-script/examples/scripts/deobf/deobf.jadx.kts
+++ b/jadx-plugins/jadx-script/examples/scripts/deobf/deobf.jadx.kts
@@ -1,3 +1,5 @@
+import jadx.api.plugins.options.OptionFlag.PER_PROJECT
+
/**
* Custom regexp deobfuscator
*/
@@ -7,10 +9,10 @@ jadx.args.isDeobfuscationOn = false
jadx.args.renameFlags = emptySet()
val regexOpt = jadx.options.registerString(
- "regex",
- "Apply rename for names matches regex",
+ name = "regex",
+ desc = "Apply rename for names matches regex",
defaultValue = "[Oo0]+",
-)
+).flags(PER_PROJECT)
val regex = regexOpt.value.toRegex()
var n = 0
diff --git a/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/data/Options.kt b/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/data/Options.kt
index e41a39a32..5d5e92c97 100644
--- a/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/data/Options.kt
+++ b/jadx-plugins/jadx-script/jadx-script-runtime/src/main/kotlin/jadx/plugins/script/runtime/data/Options.kt
@@ -2,6 +2,7 @@ package jadx.plugins.script.runtime.data
import jadx.api.plugins.options.JadxPluginOptions
import jadx.api.plugins.options.OptionDescription
+import jadx.api.plugins.options.OptionFlag
import jadx.api.plugins.options.OptionType
import jadx.api.plugins.options.impl.JadxOptionDescription
import jadx.plugins.script.runtime.JadxScriptInstance
@@ -29,6 +30,7 @@ class ScriptOptionDesc(
class ScriptOption(
val name: String,
val id: String,
+ val optData: ScriptOptionDesc,
private val getter: () -> T,
) {
private var validate: ((T) -> Boolean)? = null
@@ -48,6 +50,11 @@ class ScriptOption(
validate = predicate
return this
}
+
+ fun flags(vararg flags: OptionFlag): ScriptOption {
+ optData.flags += flags
+ return this
+ }
}
class JadxScriptOptions(
@@ -62,10 +69,10 @@ class JadxScriptOptions(
type: OptionType = OptionType.STRING,
convert: (String?) -> T,
): ScriptOption {
- val optDesc = ScriptOptionDesc(jadx.scriptName, name, desc, defaultValue, values, type)
- options.descriptions.add(optDesc)
- val optId = optDesc.name()
- return ScriptOption(name, optId) { convert.invoke(options.values[optId]) }
+ val optData = ScriptOptionDesc(jadx.scriptName, name, desc, defaultValue, values, type)
+ options.descriptions.add(optData)
+ val optId = optData.name()
+ return ScriptOption(name, optId, optData) { convert.invoke(options.values[optId]) }
}
fun registerString(