@@ -3,7 +3,9 @@ package jadx.api;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class JadxArgs {
|
||||
|
||||
@@ -30,11 +32,11 @@ public class JadxArgs {
|
||||
private boolean useImports = true;
|
||||
private boolean debugInfo = true;
|
||||
|
||||
private boolean isSkipResources = false;
|
||||
private boolean isSkipSources = false;
|
||||
private boolean skipResources = false;
|
||||
private boolean skipSources = false;
|
||||
|
||||
private boolean isDeobfuscationOn = false;
|
||||
private boolean isDeobfuscationForceSave = false;
|
||||
private boolean deobfuscationOn = false;
|
||||
private boolean deobfuscationForceSave = false;
|
||||
private boolean useSourceNameAsClassAlias = false;
|
||||
|
||||
private int deobfuscationMinLength = 0;
|
||||
@@ -45,7 +47,11 @@ public class JadxArgs {
|
||||
private boolean respectBytecodeAccModifiers = false;
|
||||
private boolean exportAsGradleProject = false;
|
||||
|
||||
private boolean isFsCaseSensitive;
|
||||
private boolean fsCaseSensitive;
|
||||
|
||||
public enum RENAME {CASE, VALID, PRINTABLE}
|
||||
|
||||
private Set<RENAME> renameFlags = EnumSet.allOf(RENAME.class);
|
||||
|
||||
public JadxArgs() {
|
||||
// use default options
|
||||
@@ -150,35 +156,35 @@ public class JadxArgs {
|
||||
}
|
||||
|
||||
public boolean isSkipResources() {
|
||||
return isSkipResources;
|
||||
return skipResources;
|
||||
}
|
||||
|
||||
public void setSkipResources(boolean skipResources) {
|
||||
isSkipResources = skipResources;
|
||||
this.skipResources = skipResources;
|
||||
}
|
||||
|
||||
public boolean isSkipSources() {
|
||||
return isSkipSources;
|
||||
return skipSources;
|
||||
}
|
||||
|
||||
public void setSkipSources(boolean skipSources) {
|
||||
isSkipSources = skipSources;
|
||||
this.skipSources = skipSources;
|
||||
}
|
||||
|
||||
public boolean isDeobfuscationOn() {
|
||||
return isDeobfuscationOn;
|
||||
return deobfuscationOn;
|
||||
}
|
||||
|
||||
public void setDeobfuscationOn(boolean deobfuscationOn) {
|
||||
isDeobfuscationOn = deobfuscationOn;
|
||||
this.deobfuscationOn = deobfuscationOn;
|
||||
}
|
||||
|
||||
public boolean isDeobfuscationForceSave() {
|
||||
return isDeobfuscationForceSave;
|
||||
return deobfuscationForceSave;
|
||||
}
|
||||
|
||||
public void setDeobfuscationForceSave(boolean deobfuscationForceSave) {
|
||||
isDeobfuscationForceSave = deobfuscationForceSave;
|
||||
this.deobfuscationForceSave = deobfuscationForceSave;
|
||||
}
|
||||
|
||||
public boolean isUseSourceNameAsClassAlias() {
|
||||
@@ -238,11 +244,47 @@ public class JadxArgs {
|
||||
}
|
||||
|
||||
public boolean isFsCaseSensitive() {
|
||||
return isFsCaseSensitive;
|
||||
return fsCaseSensitive;
|
||||
}
|
||||
|
||||
public void setFsCaseSensitive(boolean fsCaseSensitive) {
|
||||
isFsCaseSensitive = fsCaseSensitive;
|
||||
this.fsCaseSensitive = fsCaseSensitive;
|
||||
}
|
||||
|
||||
public boolean isRenameCaseSensitive() {
|
||||
return renameFlags.contains(RENAME.CASE);
|
||||
}
|
||||
|
||||
public void setRenameCaseSensitive(boolean renameCaseSensitive) {
|
||||
if (renameCaseSensitive && !isRenameCaseSensitive()) {
|
||||
renameFlags.add(RENAME.CASE);
|
||||
} else if (!renameCaseSensitive && isRenameCaseSensitive()) {
|
||||
renameFlags.remove(RENAME.CASE);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRenameValid() {
|
||||
return renameFlags.contains(RENAME.VALID);
|
||||
}
|
||||
|
||||
public void setRenameValid(boolean renameValid) {
|
||||
if (renameValid && !isRenameValid()) {
|
||||
renameFlags.add(RENAME.VALID);
|
||||
} else if (!renameValid && isRenameValid()) {
|
||||
renameFlags.remove(RENAME.VALID);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRenamePrintable() {
|
||||
return renameFlags.contains(RENAME.PRINTABLE);
|
||||
}
|
||||
|
||||
public void setRenamePrintable(boolean renamePrintable) {
|
||||
if (renamePrintable && !isRenamePrintable()) {
|
||||
renameFlags.add(RENAME.PRINTABLE);
|
||||
} else if (!renamePrintable && isRenamePrintable()) {
|
||||
renameFlags.remove(RENAME.PRINTABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -257,10 +299,10 @@ public class JadxArgs {
|
||||
", fallbackMode=" + fallbackMode +
|
||||
", showInconsistentCode=" + showInconsistentCode +
|
||||
", useImports=" + useImports +
|
||||
", isSkipResources=" + isSkipResources +
|
||||
", isSkipSources=" + isSkipSources +
|
||||
", isDeobfuscationOn=" + isDeobfuscationOn +
|
||||
", isDeobfuscationForceSave=" + isDeobfuscationForceSave +
|
||||
", skipResources=" + skipResources +
|
||||
", skipSources=" + skipSources +
|
||||
", deobfuscationOn=" + deobfuscationOn +
|
||||
", deobfuscationForceSave=" + deobfuscationForceSave +
|
||||
", useSourceNameAsClassAlias=" + useSourceNameAsClassAlias +
|
||||
", deobfuscationMinLength=" + deobfuscationMinLength +
|
||||
", deobfuscationMaxLength=" + deobfuscationMaxLength +
|
||||
@@ -268,6 +310,8 @@ public class JadxArgs {
|
||||
", replaceConsts=" + replaceConsts +
|
||||
", respectBytecodeAccModifiers=" + respectBytecodeAccModifiers +
|
||||
", exportAsGradleProject=" + exportAsGradleProject +
|
||||
", fsCaseSensitive=" + fsCaseSensitive +
|
||||
", renameFlags=" + renameFlags +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,15 +80,13 @@ public class NameMapper {
|
||||
public static boolean isValidIdentifier(String str) {
|
||||
return notEmpty(str)
|
||||
&& !isReserved(str)
|
||||
&& VALID_JAVA_IDENTIFIER.matcher(str).matches()
|
||||
&& isAllCharsPrintable(str);
|
||||
&& VALID_JAVA_IDENTIFIER.matcher(str).matches();
|
||||
}
|
||||
|
||||
public static boolean isValidFullIdentifier(String str) {
|
||||
return notEmpty(str)
|
||||
&& !isReserved(str)
|
||||
&& VALID_JAVA_FULL_IDENTIFIER.matcher(str).matches()
|
||||
&& isAllCharsPrintable(str);
|
||||
&& VALID_JAVA_FULL_IDENTIFIER.matcher(str).matches();
|
||||
}
|
||||
|
||||
public static boolean isValidIdentifierStart(int codePoint) {
|
||||
|
||||
@@ -43,17 +43,17 @@ public class RenameVisitor extends AbstractVisitor {
|
||||
if (deobfuscationOn) {
|
||||
deobfuscator.execute();
|
||||
}
|
||||
checkClasses(root, args.isFsCaseSensitive());
|
||||
checkClasses(root, args);
|
||||
}
|
||||
|
||||
private void checkClasses(RootNode root, boolean caseSensitive) {
|
||||
private void checkClasses(RootNode root, JadxArgs args) {
|
||||
List<ClassNode> classes = root.getClasses(true);
|
||||
for (ClassNode cls : classes) {
|
||||
checkClassName(cls);
|
||||
checkFields(cls);
|
||||
checkMethods(cls);
|
||||
checkClassName(cls, args);
|
||||
checkFields(cls, args);
|
||||
checkMethods(cls, args);
|
||||
}
|
||||
if (!caseSensitive) {
|
||||
if (!args.isFsCaseSensitive() && args.isRenameCaseSensitive()) {
|
||||
Set<String> clsFullPaths = new HashSet<>(classes.size());
|
||||
for (ClassNode cls : classes) {
|
||||
ClassInfo clsInfo = cls.getClassInfo();
|
||||
@@ -69,12 +69,12 @@ public class RenameVisitor extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkClassName(ClassNode cls) {
|
||||
private void checkClassName(ClassNode cls, JadxArgs args) {
|
||||
ClassInfo classInfo = cls.getClassInfo();
|
||||
ClassInfo alias = classInfo.getAlias();
|
||||
String clsName = alias.getShortName();
|
||||
|
||||
String newShortName = fixClsShortName(clsName);
|
||||
String newShortName = fixClsShortName(args, clsName);
|
||||
if (!newShortName.equals(clsName)) {
|
||||
classInfo.rename(cls.root(), alias.makeFullClsName(newShortName, true));
|
||||
alias = classInfo.getAlias();
|
||||
@@ -86,35 +86,42 @@ public class RenameVisitor extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private String fixClsShortName(String clsName) {
|
||||
private String fixClsShortName(JadxArgs args, String clsName) {
|
||||
char firstChar = clsName.charAt(0);
|
||||
if (Character.isDigit(firstChar)) {
|
||||
boolean renameValid = args.isRenameValid();
|
||||
if (Character.isDigit(firstChar) && renameValid) {
|
||||
return Consts.ANONYMOUS_CLASS_PREFIX + NameMapper.removeInvalidCharsMiddle(clsName);
|
||||
}
|
||||
if (firstChar == '$') {
|
||||
if (firstChar == '$' && renameValid) {
|
||||
return 'C' + NameMapper.removeInvalidCharsMiddle(clsName);
|
||||
}
|
||||
String cleanClsName = NameMapper.removeInvalidChars(clsName, "C");
|
||||
if (!NameMapper.isValidIdentifier(cleanClsName)) {
|
||||
String cleanClsName = args.isRenamePrintable()
|
||||
? NameMapper.removeInvalidChars(clsName, "C")
|
||||
: clsName;
|
||||
if (renameValid && !NameMapper.isValidIdentifier(cleanClsName)) {
|
||||
return 'C' + cleanClsName;
|
||||
}
|
||||
return cleanClsName;
|
||||
}
|
||||
|
||||
private void checkFields(ClassNode cls) {
|
||||
private void checkFields(ClassNode cls, JadxArgs args) {
|
||||
Set<String> names = new HashSet<>();
|
||||
for (FieldNode field : cls.getFields()) {
|
||||
FieldInfo fieldInfo = field.getFieldInfo();
|
||||
String fieldName = fieldInfo.getAlias();
|
||||
if (!names.add(fieldName) || !NameMapper.isValidIdentifier(fieldName)) {
|
||||
if (!names.add(fieldName)
|
||||
|| (args.isRenameValid() && !NameMapper.isValidIdentifier(fieldName))
|
||||
|| (args.isRenamePrintable() && !NameMapper.isAllCharsPrintable(fieldName))) {
|
||||
deobfuscator.forceRenameField(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkMethods(ClassNode cls) {
|
||||
private void checkMethods(ClassNode cls, JadxArgs args) {
|
||||
for (MethodNode mth : cls.getMethods()) {
|
||||
if (!NameMapper.isValidIdentifier(mth.getAlias())) {
|
||||
String alias = mth.getAlias();
|
||||
if (args.isRenameValid() && !NameMapper.isValidIdentifier(alias)
|
||||
|| (args.isRenamePrintable() && !NameMapper.isAllCharsPrintable(alias))) {
|
||||
deobfuscator.forceRenameMethod(mth);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user