From 63ad7fb12846f93893a694ee89222c860452093d Mon Sep 17 00:00:00 2001 From: Krzysztof Iwaniuk Date: Mon, 15 May 2023 14:58:13 +0200 Subject: [PATCH] feat: add option for hexadecimal integer format globally (PR #1869) * option for hexadecimal integer format globally * fix i18n strings, update readme --------- Co-authored-by: Skylot --- README.md | 5 +- .../src/main/java/jadx/cli/JadxCLIArgs.java | 22 ++++ .../src/main/java/jadx/api/JadxArgs.java | 13 ++- .../java/jadx/api/args/IntegerFormat.java | 11 ++ .../java/jadx/core/codegen/AnnotationGen.java | 18 +-- .../main/java/jadx/core/codegen/ClassGen.java | 24 ++-- .../java/jadx/core/codegen/MethodGen.java | 3 +- .../main/java/jadx/core/codegen/TypeGen.java | 103 +---------------- .../java/jadx/core/utils/StringUtils.java | 105 ++++++++++++++++++ .../utils/android/AndroidResourcesUtils.java | 8 +- .../jadx/gui/device/debugger/smali/Smali.java | 19 ++-- .../java/jadx/gui/settings/JadxSettings.java | 5 + .../jadx/gui/settings/JadxSettingsWindow.java | 9 ++ .../resources/i18n/Messages_de_DE.properties | 1 + .../resources/i18n/Messages_en_US.properties | 1 + .../resources/i18n/Messages_es_ES.properties | 1 + .../resources/i18n/Messages_ko_KR.properties | 1 + .../resources/i18n/Messages_pt_BR.properties | 1 + .../resources/i18n/Messages_ru_RU.properties | 1 + .../resources/i18n/Messages_zh_CN.properties | 1 + .../resources/i18n/Messages_zh_TW.properties | 1 + 21 files changed, 223 insertions(+), 130 deletions(-) create mode 100644 jadx-core/src/main/java/jadx/api/args/IntegerFormat.java diff --git a/README.md b/README.md index 4f5e89bd..e2f61911 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,6 @@ options: 'overwrite' - don't read, always save 'ignore' - don't read and don't save --deobf-use-sourcename - use source file name as class name alias - --deobf-parse-kotlin-metadata - parse kotlin metadata to class and package names --deobf-res-name-source - better name source for resources: 'auto' - automatically select best name (default) 'resources' - use resources names @@ -136,6 +135,10 @@ options: 'printable' - remove non-printable chars from identifiers, or single 'none' - to disable all renames or single 'all' - to enable all (default) + --integer-format - how integers are displayed: + 'auto' - automatically select (default) + 'decimal' - use decimal + 'hexadecimal' - use hexadecimal --fs-case-sensitive - treat filesystem as case sensitive, false by default --cfg - save methods control flow graph to dot file --raw-cfg - save methods control flow graph (use raw instructions) diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java index 843c2b1d..1fe530a0 100644 --- a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java +++ b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java @@ -24,6 +24,7 @@ import jadx.api.JadxArgs.RenameEnum; import jadx.api.JadxArgs.UseKotlinMethodsForVarNames; import jadx.api.JadxDecompiler; import jadx.api.args.GeneratedRenamesMappingFileMode; +import jadx.api.args.IntegerFormat; import jadx.api.args.ResourceNameSource; import jadx.api.args.UserRenamesMappingsMode; import jadx.core.utils.exceptions.JadxException; @@ -186,6 +187,16 @@ public class JadxCLIArgs { ) protected Set renameFlags = EnumSet.allOf(RenameEnum.class); + @Parameter( + names = { "--integer-format" }, + description = "how integers are displayed:" + + "\n 'auto' - automatically select (default)" + + "\n 'decimal' - use decimal" + + "\n 'hexadecimal' - use hexadecimal", + converter = IntegerFormatConverter.class + ) + protected IntegerFormat integerFormat = IntegerFormat.AUTO; + @Parameter(names = { "--fs-case-sensitive" }, description = "treat filesystem as case sensitive, false by default") protected boolean fsCaseSensitive = false; @@ -318,6 +329,7 @@ public class JadxCLIArgs { args.setRenameFlags(renameFlags); args.setFsCaseSensitive(fsCaseSensitive); args.setCommentsLevel(commentsLevel); + args.setIntegerFormat(integerFormat); args.setUseDxInput(useDx); args.setPluginOptions(pluginOptions); return args; @@ -447,6 +459,10 @@ public class JadxCLIArgs { return useKotlinMethodsForVarNames; } + public IntegerFormat getIntegerFormat() { + return integerFormat; + } + public boolean isEscapeUnicode() { return escapeUnicode; } @@ -564,6 +580,12 @@ public class JadxCLIArgs { } } + public static class IntegerFormatConverter extends BaseEnumConverter { + public IntegerFormatConverter() { + super(IntegerFormat::valueOf, IntegerFormat::values); + } + } + public abstract static class BaseEnumConverter> implements IStringConverter { private final Function parse; private final Supplier values; diff --git a/jadx-core/src/main/java/jadx/api/JadxArgs.java b/jadx-core/src/main/java/jadx/api/JadxArgs.java index 220f5700..5641f14d 100644 --- a/jadx-core/src/main/java/jadx/api/JadxArgs.java +++ b/jadx-core/src/main/java/jadx/api/JadxArgs.java @@ -17,6 +17,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jadx.api.args.GeneratedRenamesMappingFileMode; +import jadx.api.args.IntegerFormat; import jadx.api.args.ResourceNameSource; import jadx.api.args.UserRenamesMappingsMode; import jadx.api.data.ICodeData; @@ -132,6 +133,8 @@ public class JadxArgs implements Closeable { private CommentsLevel commentsLevel = CommentsLevel.INFO; + private IntegerFormat integerFormat = IntegerFormat.AUTO; + private boolean useDxInput = false; public enum UseKotlinMethodsForVarNames { @@ -591,6 +594,14 @@ public class JadxArgs implements Closeable { this.commentsLevel = commentsLevel; } + public IntegerFormat getIntegerFormat() { + return integerFormat; + } + + public void setIntegerFormat(IntegerFormat format) { + this.integerFormat = format; + } + public boolean isUseDxInput() { return useDxInput; } @@ -635,7 +646,7 @@ public class JadxArgs implements Closeable { + insertDebugLines + extractFinally + debugInfo + useSourceNameAsClassAlias + escapeUnicode + replaceConsts + respectBytecodeAccModifiers + fsCaseSensitive + renameFlags - + commentsLevel + useDxInput; + + commentsLevel + useDxInput + integerFormat; return FileUtils.md5Sum(argStr); } diff --git a/jadx-core/src/main/java/jadx/api/args/IntegerFormat.java b/jadx-core/src/main/java/jadx/api/args/IntegerFormat.java new file mode 100644 index 00000000..4c29c829 --- /dev/null +++ b/jadx-core/src/main/java/jadx/api/args/IntegerFormat.java @@ -0,0 +1,11 @@ +package jadx.api.args; + +public enum IntegerFormat { + AUTO, + DECIMAL, + HEXADECIMAL; + + public boolean isHexadecimal() { + return this == HEXADECIMAL; + } +} diff --git a/jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java b/jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java index 4b4a7e1c..82ff104e 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java @@ -146,6 +146,8 @@ public class AnnotationGen { code.add("null"); return; } + + StringUtils stringUtils = getStringUtils(); Object value = encodedValue.getValue(); switch (encodedValue.getType()) { case ENCODED_NULL: @@ -155,28 +157,28 @@ public class AnnotationGen { code.add(Boolean.TRUE.equals(value) ? "true" : "false"); break; case ENCODED_BYTE: - code.add(TypeGen.formatByte((Byte) value, false)); + code.add(stringUtils.formatByte((Byte) value, false)); break; case ENCODED_SHORT: - code.add(TypeGen.formatShort((Short) value, false)); + code.add(stringUtils.formatShort((Short) value, false)); break; case ENCODED_CHAR: - code.add(getStringUtils().unescapeChar((Character) value)); + code.add(stringUtils.unescapeChar((Character) value)); break; case ENCODED_INT: - code.add(TypeGen.formatInteger((Integer) value, false)); + code.add(stringUtils.formatInteger((Integer) value, false)); break; case ENCODED_LONG: - code.add(TypeGen.formatLong((Long) value, false)); + code.add(stringUtils.formatLong((Long) value, false)); break; case ENCODED_FLOAT: - code.add(TypeGen.formatFloat((Float) value)); + code.add(StringUtils.formatFloat((Float) value)); break; case ENCODED_DOUBLE: - code.add(TypeGen.formatDouble((Double) value)); + code.add(StringUtils.formatDouble((Double) value)); break; case ENCODED_STRING: - code.add(getStringUtils().unescapeString((String) value)); + code.add(stringUtils.unescapeString((String) value)); break; case ENCODED_TYPE: classGen.useType(code, ArgType.parse((String) value)); diff --git a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java index 74350adf..ae9d097f 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java @@ -19,6 +19,7 @@ import jadx.api.CommentsLevel; import jadx.api.ICodeInfo; import jadx.api.ICodeWriter; import jadx.api.JadxArgs; +import jadx.api.args.IntegerFormat; import jadx.api.metadata.annotations.NodeEnd; import jadx.api.plugins.input.data.AccessFlags; import jadx.api.plugins.input.data.annotations.EncodedType; @@ -59,6 +60,7 @@ public class ClassGen { private final boolean fallback; private final boolean useImports; private final boolean showInconsistentCode; + private final IntegerFormat integerFormat; private final Set imports = new HashSet<>(); private int clsDeclOffset; @@ -69,19 +71,22 @@ public class ClassGen { private NameGen outerNameGen; public ClassGen(ClassNode cls, JadxArgs jadxArgs) { - this(cls, null, jadxArgs.isUseImports(), jadxArgs.isFallbackMode(), jadxArgs.isShowInconsistentCode()); + this(cls, null, jadxArgs.isUseImports(), jadxArgs.isFallbackMode(), jadxArgs.isShowInconsistentCode(), jadxArgs.getIntegerFormat()); } public ClassGen(ClassNode cls, ClassGen parentClsGen) { - this(cls, parentClsGen, parentClsGen.useImports, parentClsGen.fallback, parentClsGen.showInconsistentCode); + this(cls, parentClsGen, parentClsGen.useImports, parentClsGen.fallback, parentClsGen.showInconsistentCode, + parentClsGen.integerFormat); } - public ClassGen(ClassNode cls, ClassGen parentClsGen, boolean useImports, boolean fallback, boolean showBadCode) { + public ClassGen(ClassNode cls, ClassGen parentClsGen, boolean useImports, boolean fallback, boolean showBadCode, + IntegerFormat integerFormat) { this.cls = cls; this.parentGen = parentClsGen; this.fallback = fallback; this.useImports = useImports; this.showInconsistentCode = showBadCode; + this.integerFormat = integerFormat; this.annotationGen = new AnnotationGen(cls, this); } @@ -424,10 +429,7 @@ public class ClassGen { Object val = EncodedValueUtils.convertToConstValue(constVal); if (val instanceof LiteralArg) { long lit = ((LiteralArg) val).getLiteral(); - if (!AndroidResourcesUtils.handleResourceFieldValue(cls, code, lit, f.getType())) { - // force literal type to be same as field (java bytecode can use different type) - code.add(TypeGen.literalToString(lit, f.getType(), cls, fallback)); - } + code.add(getIntegerString(lit, f.getType())); } else { annotationGen.encodeValue(cls.root(), code, constVal); } @@ -437,6 +439,14 @@ public class ClassGen { code.add(';'); } + private String getIntegerString(long lit, ArgType type) { + if (integerFormat != IntegerFormat.DECIMAL && AndroidResourcesUtils.isResourceFieldValue(cls, type)) { + return String.format("0x%08x", lit); + } + // force literal type to be same as field (java bytecode can use different type) + return TypeGen.literalToString(lit, type, cls, fallback); + } + private boolean isFieldsPresents() { for (FieldNode field : cls.getFields()) { if (!field.contains(AFlag.DONT_GENERATE)) { diff --git a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java index 2c5ae339..f71d4a95 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java @@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory; import jadx.api.CommentsLevel; import jadx.api.ICodeWriter; import jadx.api.JadxArgs; +import jadx.api.args.IntegerFormat; import jadx.api.metadata.annotations.InsnCodeOffset; import jadx.api.metadata.annotations.VarNode; import jadx.api.plugins.input.data.AccessFlags; @@ -548,7 +549,7 @@ public class MethodGen { * Return fallback variant of method codegen */ public static MethodGen getFallbackMethodGen(MethodNode mth) { - ClassGen clsGen = new ClassGen(mth.getParentClass(), null, false, true, true); + ClassGen clsGen = new ClassGen(mth.getParentClass(), null, false, true, true, IntegerFormat.AUTO); return new MethodGen(clsGen, mth); } diff --git a/jadx-core/src/main/java/jadx/core/codegen/TypeGen.java b/jadx-core/src/main/java/jadx/core/codegen/TypeGen.java index a7c76e65..693fbce8 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/TypeGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/TypeGen.java @@ -73,17 +73,17 @@ public class TypeGen { case CHAR: return stringUtils.unescapeChar((char) lit, cast); case BYTE: - return formatByte(lit, cast); + return stringUtils.formatByte(lit, cast); case SHORT: - return formatShort(lit, cast); + return stringUtils.formatShort(lit, cast); case INT: - return formatInteger(lit, cast); + return stringUtils.formatInteger(lit, cast); case LONG: - return formatLong(lit, cast); + return stringUtils.formatLong(lit, cast); case FLOAT: - return formatFloat(Float.intBitsToFloat((int) lit)); + return StringUtils.formatFloat(Float.intBitsToFloat((int) lit)); case DOUBLE: - return formatDouble(Double.longBitsToDouble(lit)); + return StringUtils.formatDouble(Double.longBitsToDouble(lit)); case OBJECT: case ARRAY: @@ -134,95 +134,4 @@ public class TypeGen { return null; } } - - public static String formatShort(long l, boolean cast) { - if (l == Short.MAX_VALUE) { - return "Short.MAX_VALUE"; - } - if (l == Short.MIN_VALUE) { - return "Short.MIN_VALUE"; - } - String str = Long.toString(l); - return cast ? "(short) " + str : str; - } - - public static String formatByte(long l, boolean cast) { - if (l == Byte.MAX_VALUE) { - return "Byte.MAX_VALUE"; - } - if (l == Byte.MIN_VALUE) { - return "Byte.MIN_VALUE"; - } - String str = Long.toString(l); - return cast ? "(byte) " + str : str; - } - - public static String formatInteger(long l, boolean cast) { - if (l == Integer.MAX_VALUE) { - return "Integer.MAX_VALUE"; - } - if (l == Integer.MIN_VALUE) { - return "Integer.MIN_VALUE"; - } - String str = Long.toString(l); - return cast ? "(int) " + str : str; - } - - public static String formatLong(long l, boolean cast) { - if (l == Long.MAX_VALUE) { - return "Long.MAX_VALUE"; - } - if (l == Long.MIN_VALUE) { - return "Long.MIN_VALUE"; - } - String str = Long.toString(l); - if (cast || Math.abs(l) >= Integer.MAX_VALUE) { - return str + 'L'; - } - return str; - } - - public static String formatDouble(double d) { - if (Double.isNaN(d)) { - return "Double.NaN"; - } - if (d == Double.NEGATIVE_INFINITY) { - return "Double.NEGATIVE_INFINITY"; - } - if (d == Double.POSITIVE_INFINITY) { - return "Double.POSITIVE_INFINITY"; - } - if (d == Double.MIN_VALUE) { - return "Double.MIN_VALUE"; - } - if (d == Double.MAX_VALUE) { - return "Double.MAX_VALUE"; - } - if (d == Double.MIN_NORMAL) { - return "Double.MIN_NORMAL"; - } - return Double.toString(d) + 'd'; - } - - public static String formatFloat(float f) { - if (Float.isNaN(f)) { - return "Float.NaN"; - } - if (f == Float.NEGATIVE_INFINITY) { - return "Float.NEGATIVE_INFINITY"; - } - if (f == Float.POSITIVE_INFINITY) { - return "Float.POSITIVE_INFINITY"; - } - if (f == Float.MIN_VALUE) { - return "Float.MIN_VALUE"; - } - if (f == Float.MAX_VALUE) { - return "Float.MAX_VALUE"; - } - if (f == Float.MIN_NORMAL) { - return "Float.MIN_NORMAL"; - } - return Float.toString(f) + 'f'; - } } diff --git a/jadx-core/src/main/java/jadx/core/utils/StringUtils.java b/jadx-core/src/main/java/jadx/core/utils/StringUtils.java index a1ad0716..62e969cc 100644 --- a/jadx-core/src/main/java/jadx/core/utils/StringUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/StringUtils.java @@ -7,6 +7,7 @@ import java.util.function.IntConsumer; import org.jetbrains.annotations.Nullable; import jadx.api.JadxArgs; +import jadx.api.args.IntegerFormat; import jadx.core.deobf.NameMapper; public class StringUtils { @@ -19,9 +20,15 @@ public class StringUtils { } private final boolean escapeUnicode; + private final IntegerFormat integerFormat; public StringUtils(JadxArgs args) { this.escapeUnicode = args.isEscapeUnicode(); + this.integerFormat = args.getIntegerFormat(); + } + + public IntegerFormat getIntegerFormat() { + return integerFormat; } public static void visitCodePoints(String str, IntConsumer visitor) { @@ -370,4 +377,102 @@ public class StringUtils { public static String getDateText() { return new SimpleDateFormat("HH:mm:ss").format(new Date()); } + + private String toFormatString(long l) { + if (integerFormat.isHexadecimal()) { + return "0x" + Long.toHexString(l); + } + return Long.toString(l); + } + + public String formatShort(long l, boolean cast) { + if (l == Short.MAX_VALUE) { + return "Short.MAX_VALUE"; + } + if (l == Short.MIN_VALUE) { + return "Short.MIN_VALUE"; + } + String str = toFormatString(l); + return cast ? "(short) " + str : str; + } + + public String formatByte(long l, boolean cast) { + if (l == Byte.MAX_VALUE) { + return "Byte.MAX_VALUE"; + } + if (l == Byte.MIN_VALUE) { + return "Byte.MIN_VALUE"; + } + String str = toFormatString(l); + return cast ? "(byte) " + str : str; + } + + public String formatInteger(long l, boolean cast) { + if (l == Integer.MAX_VALUE) { + return "Integer.MAX_VALUE"; + } + if (l == Integer.MIN_VALUE) { + return "Integer.MIN_VALUE"; + } + String str = toFormatString(l); + return cast ? "(int) " + str : str; + } + + public String formatLong(long l, boolean cast) { + if (l == Long.MAX_VALUE) { + return "Long.MAX_VALUE"; + } + if (l == Long.MIN_VALUE) { + return "Long.MIN_VALUE"; + } + String str = toFormatString(l); + if (cast || Math.abs(l) >= Integer.MAX_VALUE) { + return str + 'L'; + } + return str; + } + + public static String formatDouble(double d) { + if (Double.isNaN(d)) { + return "Double.NaN"; + } + if (d == Double.NEGATIVE_INFINITY) { + return "Double.NEGATIVE_INFINITY"; + } + if (d == Double.POSITIVE_INFINITY) { + return "Double.POSITIVE_INFINITY"; + } + if (d == Double.MIN_VALUE) { + return "Double.MIN_VALUE"; + } + if (d == Double.MAX_VALUE) { + return "Double.MAX_VALUE"; + } + if (d == Double.MIN_NORMAL) { + return "Double.MIN_NORMAL"; + } + return Double.toString(d) + 'd'; + } + + public static String formatFloat(float f) { + if (Float.isNaN(f)) { + return "Float.NaN"; + } + if (f == Float.NEGATIVE_INFINITY) { + return "Float.NEGATIVE_INFINITY"; + } + if (f == Float.POSITIVE_INFINITY) { + return "Float.POSITIVE_INFINITY"; + } + if (f == Float.MIN_VALUE) { + return "Float.MIN_VALUE"; + } + if (f == Float.MAX_VALUE) { + return "Float.MAX_VALUE"; + } + if (f == Float.MIN_NORMAL) { + return "Float.MIN_NORMAL"; + } + return Float.toString(f) + 'f'; + } } diff --git a/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java b/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java index 3791c33f..df786a01 100644 --- a/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java @@ -76,12 +76,8 @@ public class AndroidResourcesUtils { /** * Force hex format for Android resources ids */ - public static boolean handleResourceFieldValue(ClassNode cls, ICodeWriter code, long lit, ArgType type) { - if (type.equals(ArgType.INT) && isResourceClass(cls)) { - code.add(String.format("0x%08x", lit)); - return true; - } - return false; + public static boolean isResourceFieldValue(ClassNode cls, ArgType type) { + return type.equals(ArgType.INT) && isResourceClass(cls); } public static boolean isResourceClass(ClassNode cls) { diff --git a/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/Smali.java b/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/Smali.java index f3a1103d..4a45eb66 100644 --- a/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/Smali.java +++ b/jadx-gui/src/main/java/jadx/gui/device/debugger/smali/Smali.java @@ -37,7 +37,6 @@ import jadx.api.plugins.input.insns.InsnData; import jadx.api.plugins.input.insns.InsnIndexType; import jadx.api.plugins.input.insns.Opcode; import jadx.api.plugins.input.insns.custom.ISwitchPayload; -import jadx.core.codegen.TypeGen; import jadx.core.dex.attributes.AttributeStorage; import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InsnDecoder; @@ -48,6 +47,7 @@ import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.MethodNode; +import jadx.core.utils.StringUtils; import jadx.core.utils.Utils; import jadx.core.utils.exceptions.JadxRuntimeException; @@ -593,6 +593,7 @@ public class Smali { } private void writeEncodedValue(SmaliWriter smali, EncodedValue value, boolean wrapArray) { + StringUtils stringUtils = smali.getClassNode().root().getStringUtils(); switch (value.getType()) { case ENCODED_ARRAY: smali.add("{"); @@ -624,28 +625,28 @@ public class Smali { writeAnnotation(smali, (IAnnotation) value.getValue()); break; case ENCODED_BYTE: - smali.add(TypeGen.formatByte((Byte) value.getValue(), false)); + smali.add(stringUtils.formatByte((Byte) value.getValue(), false)); break; case ENCODED_SHORT: - smali.add(TypeGen.formatShort((Short) value.getValue(), false)); + smali.add(stringUtils.formatShort((Short) value.getValue(), false)); break; case ENCODED_CHAR: - smali.add(smali.getClassNode().root().getStringUtils().unescapeChar((Character) value.getValue())); + smali.add(stringUtils.unescapeChar((Character) value.getValue())); break; case ENCODED_INT: - smali.add(TypeGen.formatInteger((Integer) value.getValue(), false)); + smali.add(stringUtils.formatInteger((Integer) value.getValue(), false)); break; case ENCODED_LONG: - smali.add(TypeGen.formatLong((Long) value.getValue(), false)); + smali.add(stringUtils.formatLong((Long) value.getValue(), false)); break; case ENCODED_FLOAT: - smali.add(TypeGen.formatFloat((Float) value.getValue())); + smali.add(StringUtils.formatFloat((Float) value.getValue())); break; case ENCODED_DOUBLE: - smali.add(TypeGen.formatDouble((Double) value.getValue())); + smali.add(StringUtils.formatDouble((Double) value.getValue())); break; case ENCODED_STRING: - smali.add(smali.getClassNode().root().getStringUtils().unescapeString((String) value.getValue())); + smali.add(stringUtils.unescapeString((String) value.getValue())); break; case ENCODED_TYPE: smali.add(ArgType.parse((String) value.getValue()) + ".class"); diff --git a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java index 21b1f0eb..1bbfd54b 100644 --- a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java +++ b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java @@ -26,6 +26,7 @@ import jadx.api.CommentsLevel; import jadx.api.DecompilationMode; import jadx.api.JadxArgs; import jadx.api.args.GeneratedRenamesMappingFileMode; +import jadx.api.args.IntegerFormat; import jadx.api.args.ResourceNameSource; import jadx.api.args.UserRenamesMappingsMode; import jadx.cli.JadxCLIArgs; @@ -652,6 +653,10 @@ public class JadxSettings extends JadxCLIArgs { return lineNumbersMode; } + public void setIntegerFormat(IntegerFormat format) { + this.integerFormat = format; + } + public void setLineNumbersMode(LineNumbersMode lineNumbersMode) { this.lineNumbersMode = lineNumbersMode; } diff --git a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java index d7494de2..fa7315ac 100644 --- a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java @@ -63,6 +63,7 @@ import jadx.api.DecompilationMode; import jadx.api.JadxArgs; import jadx.api.JadxArgs.UseKotlinMethodsForVarNames; import jadx.api.args.GeneratedRenamesMappingFileMode; +import jadx.api.args.IntegerFormat; import jadx.api.args.ResourceNameSource; import jadx.api.plugins.options.JadxPluginOptions; import jadx.api.plugins.options.OptionDescription; @@ -758,6 +759,13 @@ public class JadxSettingsWindow extends JDialog { needReload(); }); + JComboBox integerFormat = new JComboBox<>(IntegerFormat.values()); + integerFormat.setSelectedItem(settings.getIntegerFormat()); + integerFormat.addActionListener(e -> { + settings.setIntegerFormat((IntegerFormat) integerFormat.getSelectedItem()); + needReload(); + }); + SettingsGroup group = new SettingsGroup(NLS.str("preferences.other")); group.addRow(NLS.str("preferences.language"), languageCbx); group.addRow(NLS.str("preferences.lineNumbersMode"), lineNumbersMode); @@ -766,6 +774,7 @@ public class JadxSettingsWindow extends JDialog { group.addRow(NLS.str("preferences.check_for_updates"), update); group.addRow(NLS.str("preferences.cfg"), cfg); group.addRow(NLS.str("preferences.raw_cfg"), rawCfg); + group.addRow(NLS.str("preferences.integerFormat"), integerFormat); return group; } diff --git a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties index da04c715..6038a30a 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties @@ -192,6 +192,7 @@ preferences.excludedPackages.button=Bearbeiten preferences.excludedPackages.editDialog=Liste der durch Leerzeichen getrennten Paketnamen, die nicht dekompiliert oder indiziert werden. (spart RAM)
z.B. android.support preferences.cfg=CFG-Grafiken für Methoden generieren (im 'dot'-Format) preferences.raw_cfg=RAW CFG-Grafiken generieren +#preferences.integerFormat=Integer format preferences.font=Schrift ändern preferences.smali_font=Schrifteditor preferences.laf_theme=Thema diff --git a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties index 9b2c1bac..e628ec47 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties @@ -192,6 +192,7 @@ preferences.excludedPackages.button=Edit preferences.excludedPackages.editDialog=List of space separated package names that will not be decompiled or indexed (saves RAM)
e.g. android.support preferences.cfg=Generate methods CFG graphs (in 'dot' format) preferences.raw_cfg=Generate RAW CFG graphs +preferences.integerFormat=Integer format preferences.font=Editor font preferences.smali_font=Smali Editor font preferences.laf_theme=Theme diff --git a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties index 989a765d..6b52e998 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties @@ -192,6 +192,7 @@ preferences.threads=Número de hilos a procesar #preferences.excludedPackages.editDialog= preferences.cfg=Generar methods CFG graphs (in 'dot' format) preferences.raw_cfg=Generate RAW CFG graphs +#preferences.integerFormat=Integer format preferences.font=Fuente del editor #preferences.smali_font= #preferences.laf_theme=Theme diff --git a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties index f07a8a57..ba1e1ac4 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties @@ -192,6 +192,7 @@ preferences.excludedPackages.button=Edit preferences.excludedPackages.editDialog=RAM 절약을 위해 디컴파일되거나 인덱싱하지 않을 패키지 이름 목록 (공백으로 항목 구분)
예: android.support preferences.cfg=메소드 CFG 그래프 생성 ('dot' 포맷) preferences.raw_cfg=RAW CFG 그래프 생성 +#preferences.integerFormat=Integer format preferences.font=에디터 글씨체 preferences.smali_font=Smali 에디터 글씨체 preferences.laf_theme=테마 diff --git a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties index 3176a0df..781e441e 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties @@ -192,6 +192,7 @@ preferences.excludedPackages.button=Editar preferences.excludedPackages.editDialog=Lista espaço de pacotes que não vão ser descompilados ou indexados (economiza RAM)
ex: android.support preferences.cfg=Gera gráficos de métodos CFG no formato de pontos ('dot') preferences.raw_cfg=Gera gráficos CFG no formato RAW +#preferences.integerFormat=Integer format preferences.font=Fonte do editor preferences.smali_font=Fonte do editor de smali preferences.laf_theme=Tema diff --git a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties index 79c030db..55751a46 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties @@ -192,6 +192,7 @@ preferences.excludedPackages.button=Изменить preferences.excludedPackages.editDialog=Список пакетов, которые не будут декомпилироваться и индексироваться (экономит ОЗУ)
например: android.support
Разделитель - одинарный пробел preferences.cfg=Методы генерации графиков CFG (в "dot" формате) preferences.raw_cfg=Генерировать необработанные графики CFG +#preferences.integerFormat=Integer format preferences.font=Шрифт редактора Java preferences.smali_font=Шрифт редактора smali preferences.laf_theme=Тема приложения diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties index c0da897e..63d5f5fc 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties @@ -192,6 +192,7 @@ preferences.excludedPackages.button=编辑 preferences.excludedPackages.editDialog=排除于反编译或索引的以空格分隔的包名列表(节省 RAM)
例如android.support preferences.cfg=生成方法的 CFG 图('.dot') preferences.raw_cfg=生成原始的 CFG 图 +#preferences.integerFormat=Integer format preferences.font=编辑器字体 preferences.smali_font=Smali编辑器字体 preferences.laf_theme=主题 diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties index 377efcb4..739cf94c 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties @@ -192,6 +192,7 @@ preferences.excludedPackages.button=編輯 preferences.excludedPackages.editDialog=排除於索引或反編譯外的套件列表 (以空格分隔) (節省 RAM)
例如 android.support preferences.cfg=產生方法 CFG 圖表 ('dot' 格式) preferences.raw_cfg=產生 RAW CFG 圖表 +#preferences.integerFormat=Integer format preferences.font=編輯器字型 preferences.smali_font=Smali 編輯器字型 preferences.laf_theme=主題