fix: rename all related overridden methods in deobf map file (#1058)
This commit is contained in:
@@ -1,38 +1,62 @@
|
||||
package jadx.core.deobf;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.core.dex.info.ClassInfo;
|
||||
import jadx.core.dex.info.FieldInfo;
|
||||
import jadx.core.dex.info.MethodInfo;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
class DeobfPresets {
|
||||
public class DeobfPresets {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DeobfPresets.class);
|
||||
|
||||
private static final Charset MAP_FILE_CHARSET = UTF_8;
|
||||
|
||||
private final Deobfuscator deobfuscator;
|
||||
private final Path deobfMapFile;
|
||||
|
||||
private final Map<String, String> pkgPresetMap = new HashMap<>();
|
||||
private final Map<String, String> clsPresetMap = new HashMap<>();
|
||||
private final Map<String, String> fldPresetMap = new HashMap<>();
|
||||
private final Map<String, String> mthPresetMap = new HashMap<>();
|
||||
|
||||
public DeobfPresets(Deobfuscator deobfuscator, Path deobfMapFile) {
|
||||
this.deobfuscator = deobfuscator;
|
||||
@Nullable
|
||||
public static DeobfPresets build(RootNode root) {
|
||||
Path deobfMapPath = getPathDeobfMapPath(root);
|
||||
if (deobfMapPath == null) {
|
||||
return null;
|
||||
}
|
||||
return new DeobfPresets(deobfMapPath);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Path getPathDeobfMapPath(RootNode root) {
|
||||
List<File> inputFiles = root.getArgs().getInputFiles();
|
||||
if (inputFiles.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Path inputFilePath = inputFiles.get(0).getAbsoluteFile().toPath();
|
||||
String baseName = FileUtils.getPathBaseName(inputFilePath);
|
||||
return inputFilePath.getParent().resolve(baseName + ".jobf");
|
||||
}
|
||||
|
||||
private DeobfPresets(Path deobfMapFile) {
|
||||
this.deobfMapFile = deobfMapFile;
|
||||
}
|
||||
|
||||
@@ -57,17 +81,22 @@ class DeobfPresets {
|
||||
}
|
||||
String origName = va[0];
|
||||
String alias = va[1];
|
||||
if (l.startsWith("p ")) {
|
||||
deobfuscator.addPackagePreset(origName, alias);
|
||||
} else if (l.startsWith("c ")) {
|
||||
clsPresetMap.put(origName, alias);
|
||||
} else if (l.startsWith("f ")) {
|
||||
fldPresetMap.put(origName, alias);
|
||||
} else if (l.startsWith("m ")) {
|
||||
mthPresetMap.put(origName, alias);
|
||||
switch (l.charAt(0)) {
|
||||
case 'p':
|
||||
pkgPresetMap.put(origName, alias);
|
||||
break;
|
||||
case 'c':
|
||||
clsPresetMap.put(origName, alias);
|
||||
break;
|
||||
case 'f':
|
||||
fldPresetMap.put(origName, alias);
|
||||
break;
|
||||
case 'm':
|
||||
mthPresetMap.put(origName, alias);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to load deobfuscation map file '{}'", deobfMapFile.toAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
@@ -80,66 +109,28 @@ class DeobfPresets {
|
||||
return v;
|
||||
}
|
||||
|
||||
public void save(boolean forceSave) {
|
||||
try {
|
||||
if (Files.exists(deobfMapFile)) {
|
||||
if (forceSave) {
|
||||
dumpMapping();
|
||||
} else {
|
||||
LOG.warn("Deobfuscation map file '{}' exists. Use command line option '--deobf-rewrite-cfg' to rewrite it",
|
||||
deobfMapFile.toAbsolutePath());
|
||||
}
|
||||
} else {
|
||||
dumpMapping();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to load deobfuscation map file '{}'", deobfMapFile.toAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves DefaultDeobfuscator presets
|
||||
*/
|
||||
private void dumpMapping() throws IOException {
|
||||
public void save() throws IOException {
|
||||
List<String> list = new ArrayList<>();
|
||||
// packages
|
||||
for (PackageNode p : deobfuscator.getRootPackage().getInnerPackages()) {
|
||||
for (PackageNode pp : p.getInnerPackages()) {
|
||||
dfsPackageName(list, p.getName(), pp);
|
||||
}
|
||||
if (p.hasAlias()) {
|
||||
list.add(String.format("p %s = %s", p.getName(), p.getAlias()));
|
||||
}
|
||||
for (Map.Entry<String, String> pkgEntry : pkgPresetMap.entrySet()) {
|
||||
list.add(String.format("p %s = %s", pkgEntry.getKey(), pkgEntry.getValue()));
|
||||
}
|
||||
// classes
|
||||
for (DeobfClsInfo deobfClsInfo : deobfuscator.getClsMap().values()) {
|
||||
if (deobfClsInfo.getAlias() != null) {
|
||||
list.add(String.format("c %s = %s",
|
||||
deobfClsInfo.getCls().getClassInfo().makeRawFullName(), deobfClsInfo.getAlias()));
|
||||
}
|
||||
for (Map.Entry<String, String> clsEntry : clsPresetMap.entrySet()) {
|
||||
list.add(String.format("c %s = %s", clsEntry.getKey(), clsEntry.getValue()));
|
||||
}
|
||||
for (FieldInfo fld : deobfuscator.getFldMap().keySet()) {
|
||||
list.add(String.format("f %s = %s", fld.getRawFullId(), fld.getAlias()));
|
||||
for (Map.Entry<String, String> fldEntry : fldPresetMap.entrySet()) {
|
||||
list.add(String.format("f %s = %s", fldEntry.getKey(), fldEntry.getValue()));
|
||||
}
|
||||
for (MethodInfo mth : deobfuscator.getMthMap().keySet()) {
|
||||
list.add(String.format("m %s = %s", mth.getRawFullId(), mth.getAlias()));
|
||||
for (Map.Entry<String, String> mthEntry : mthPresetMap.entrySet()) {
|
||||
list.add(String.format("m %s = %s", mthEntry.getKey(), mthEntry.getValue()));
|
||||
}
|
||||
Collections.sort(list);
|
||||
Files.write(deobfMapFile, list, MAP_FILE_CHARSET);
|
||||
Files.write(deobfMapFile, list, MAP_FILE_CHARSET,
|
||||
StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Deobfuscation map file saved as: {}", deobfMapFile);
|
||||
}
|
||||
}
|
||||
|
||||
private static void dfsPackageName(List<String> list, String prefix, PackageNode node) {
|
||||
for (PackageNode pp : node.getInnerPackages()) {
|
||||
dfsPackageName(list, prefix + '.' + node.getName(), pp);
|
||||
}
|
||||
if (node.hasAlias()) {
|
||||
list.add(String.format("p %s.%s = %s", prefix, node.getName(), node.getAlias()));
|
||||
}
|
||||
}
|
||||
|
||||
public String getForCls(ClassInfo cls) {
|
||||
return clsPresetMap.get(cls.makeRawFullName());
|
||||
}
|
||||
@@ -158,6 +149,14 @@ class DeobfPresets {
|
||||
mthPresetMap.clear();
|
||||
}
|
||||
|
||||
public Path getDeobfMapFile() {
|
||||
return deobfMapFile;
|
||||
}
|
||||
|
||||
public Map<String, String> getPkgPresetMap() {
|
||||
return pkgPresetMap;
|
||||
}
|
||||
|
||||
public Map<String, String> getClsPresetMap() {
|
||||
return clsPresetMap;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package jadx.core.deobf;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -58,28 +59,75 @@ public class Deobfuscator {
|
||||
private int fldIndex = 0;
|
||||
private int mthIndex = 0;
|
||||
|
||||
public Deobfuscator(JadxArgs args, RootNode root, Path deobfMapFile) {
|
||||
this.args = args;
|
||||
public Deobfuscator(RootNode root) {
|
||||
this.root = root;
|
||||
this.args = root.getArgs();
|
||||
|
||||
this.minLength = args.getDeobfuscationMinLength();
|
||||
this.maxLength = args.getDeobfuscationMaxLength();
|
||||
this.useSourceNameAsAlias = args.isUseSourceNameAsClassAlias();
|
||||
this.parseKotlinMetadata = args.isParseKotlinMetadata();
|
||||
|
||||
this.deobfPresets = new DeobfPresets(this, deobfMapFile);
|
||||
this.deobfPresets = DeobfPresets.build(root);
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
if (!args.isDeobfuscationForceSave()) {
|
||||
deobfPresets.load();
|
||||
for (Map.Entry<String, String> pkgEntry : deobfPresets.getPkgPresetMap().entrySet()) {
|
||||
addPackagePreset(pkgEntry.getKey(), pkgEntry.getValue());
|
||||
}
|
||||
deobfPresets.getPkgPresetMap().clear(); // not needed anymore
|
||||
initIndexes();
|
||||
}
|
||||
process();
|
||||
}
|
||||
|
||||
public void savePresets() {
|
||||
deobfPresets.save(args.isDeobfuscationForceSave());
|
||||
Path deobfMapFile = deobfPresets.getDeobfMapFile();
|
||||
if (Files.exists(deobfMapFile) && !args.isDeobfuscationForceSave()) {
|
||||
LOG.warn("Deobfuscation map file '{}' exists. Use command line option '--deobf-rewrite-cfg' to rewrite it",
|
||||
deobfMapFile.toAbsolutePath());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
deobfPresets.clear();
|
||||
fillDeobfPresets();
|
||||
deobfPresets.save();
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to save deobfuscation map file '{}'", deobfMapFile.toAbsolutePath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillDeobfPresets() {
|
||||
for (PackageNode p : getRootPackage().getInnerPackages()) {
|
||||
for (PackageNode pp : p.getInnerPackages()) {
|
||||
dfsPackageName(p.getName(), pp);
|
||||
}
|
||||
if (p.hasAlias()) {
|
||||
deobfPresets.getPkgPresetMap().put(p.getName(), p.getAlias());
|
||||
}
|
||||
}
|
||||
for (DeobfClsInfo deobfClsInfo : clsMap.values()) {
|
||||
if (deobfClsInfo.getAlias() != null) {
|
||||
deobfPresets.getClsPresetMap().put(deobfClsInfo.getCls().getClassInfo().makeRawFullName(), deobfClsInfo.getAlias());
|
||||
}
|
||||
}
|
||||
for (FieldInfo fld : fldMap.keySet()) {
|
||||
deobfPresets.getFldPresetMap().put(fld.getRawFullId(), fld.getAlias());
|
||||
}
|
||||
for (MethodInfo mth : mthMap.keySet()) {
|
||||
deobfPresets.getMthPresetMap().put(mth.getRawFullId(), mth.getAlias());
|
||||
}
|
||||
}
|
||||
|
||||
private void dfsPackageName(String prefix, PackageNode node) {
|
||||
for (PackageNode pp : node.getInnerPackages()) {
|
||||
dfsPackageName(prefix + '.' + node.getName(), pp);
|
||||
}
|
||||
if (node.hasAlias()) {
|
||||
deobfPresets.getPkgPresetMap().put(node.getName(), node.getAlias());
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
|
||||
@@ -2,10 +2,12 @@ package jadx.core.dex.visitors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -74,16 +76,12 @@ public class OverrideMethodVisitor extends AbstractVisitor {
|
||||
for (ArgType superType : superTypes) {
|
||||
ClassNode classNode = cls.root().resolveClass(superType);
|
||||
if (classNode != null) {
|
||||
for (MethodNode supMth : classNode.getMethods()) {
|
||||
String mthShortId = supMth.getMethodInfo().getShortId();
|
||||
if (!supMth.getAccessFlags().isStatic()
|
||||
&& mthShortId.startsWith(signature)
|
||||
&& isMethodVisibleInCls(supMth, cls)) {
|
||||
overrideList.add(supMth);
|
||||
MethodOverrideAttr attr = supMth.get(AType.METHOD_OVERRIDE);
|
||||
if (attr != null) {
|
||||
return buildOverrideAttr(mth, overrideList, attr);
|
||||
}
|
||||
MethodNode ovrdMth = searchOverriddenMethod(classNode, signature);
|
||||
if (ovrdMth != null && isMethodVisibleInCls(ovrdMth, cls)) {
|
||||
overrideList.add(ovrdMth);
|
||||
MethodOverrideAttr attr = ovrdMth.get(AType.METHOD_OVERRIDE);
|
||||
if (attr != null) {
|
||||
return buildOverrideAttr(mth, overrideList, attr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -102,25 +100,50 @@ public class OverrideMethodVisitor extends AbstractVisitor {
|
||||
return buildOverrideAttr(mth, overrideList, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private MethodNode searchOverriddenMethod(ClassNode cls, String signature) {
|
||||
for (MethodNode supMth : cls.getMethods()) {
|
||||
if (!supMth.getAccessFlags().isStatic() && supMth.getMethodInfo().getShortId().startsWith(signature)) {
|
||||
return supMth;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private MethodOverrideAttr buildOverrideAttr(MethodNode mth, List<IMethodDetails> overrideList, @Nullable MethodOverrideAttr attr) {
|
||||
if (overrideList.isEmpty() && attr == null) {
|
||||
return null;
|
||||
}
|
||||
List<IMethodDetails> cleanOverrideList = overrideList.stream().distinct().collect(Collectors.toList());
|
||||
if (attr == null) {
|
||||
// traced to base method
|
||||
List<IMethodDetails> cleanOverrideList = overrideList.stream().distinct().collect(Collectors.toList());
|
||||
return applyOverrideAttr(mth, cleanOverrideList, false);
|
||||
}
|
||||
// trace stopped at already processed method -> start merging
|
||||
List<IMethodDetails> mergedOverrideList = Utils.mergeLists(cleanOverrideList, attr.getOverrideList());
|
||||
return applyOverrideAttr(mth, mergedOverrideList, true);
|
||||
List<IMethodDetails> mergedOverrideList = Utils.mergeLists(overrideList, attr.getOverrideList());
|
||||
List<IMethodDetails> cleanOverrideList = mergedOverrideList.stream().distinct().collect(Collectors.toList());
|
||||
return applyOverrideAttr(mth, cleanOverrideList, true);
|
||||
}
|
||||
|
||||
private MethodOverrideAttr applyOverrideAttr(MethodNode mth, List<IMethodDetails> overrideList, boolean update) {
|
||||
// don't rename method if override list contains not resolved method
|
||||
boolean dontRename = overrideList.stream().anyMatch(m -> !(m instanceof MethodNode));
|
||||
List<MethodNode> mthNodes = getMethodNodes(mth, overrideList);
|
||||
if (update) {
|
||||
// merge related methods from all override attributes
|
||||
Set<MethodNode> relatedMthSet = new HashSet<>(mthNodes);
|
||||
for (MethodNode mthNode : mthNodes) {
|
||||
MethodOverrideAttr ovrdAttr = mthNode.get(AType.METHOD_OVERRIDE);
|
||||
if (ovrdAttr != null) {
|
||||
relatedMthSet.addAll(ovrdAttr.getRelatedMthNodes());
|
||||
}
|
||||
}
|
||||
if (relatedMthSet.size() != mthNodes.size()) {
|
||||
mthNodes = new ArrayList<>(relatedMthSet);
|
||||
Collections.sort(mthNodes);
|
||||
}
|
||||
}
|
||||
int depth = 0;
|
||||
for (MethodNode mthNode : mthNodes) {
|
||||
if (dontRename) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package jadx.core.dex.visitors;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -23,7 +22,6 @@ import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.FieldNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
|
||||
public class RenameVisitor extends AbstractVisitor {
|
||||
|
||||
@@ -33,12 +31,8 @@ public class RenameVisitor extends AbstractVisitor {
|
||||
if (inputFiles.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Path inputFilePath = inputFiles.get(0).getAbsoluteFile().toPath();
|
||||
String baseName = FileUtils.getPathBaseName(inputFilePath);
|
||||
Path deobfMapPath = inputFilePath.getParent().resolve(baseName + ".jobf");
|
||||
|
||||
Deobfuscator deobfuscator = new Deobfuscator(root);
|
||||
JadxArgs args = root.getArgs();
|
||||
Deobfuscator deobfuscator = new Deobfuscator(args, root, deobfMapPath);
|
||||
if (args.isDeobfuscationOn()) {
|
||||
deobfuscator.execute();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package jadx.tests.integration.deobf;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
public class TestRenameOverriddenMethod2 extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
public interface I {
|
||||
int call();
|
||||
}
|
||||
|
||||
public static class A implements I {
|
||||
@Override
|
||||
public int call() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static class B implements I {
|
||||
@Override
|
||||
public int call() {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
enableDeobfuscation();
|
||||
args.setDeobfuscationMinLength(100); // rename everything
|
||||
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
assertThat(cls)
|
||||
.code()
|
||||
.countString(2, "@Override")
|
||||
.countString(3, "int mo0call()");
|
||||
|
||||
assertThat(searchCls(cls.getInnerClasses(), "I")).isNotNull()
|
||||
.extracting(c -> c.searchMethodByShortName("call")).isNotNull()
|
||||
.extracting(m -> m.get(AType.METHOD_OVERRIDE)).isNotNull()
|
||||
.satisfies(ovrdAttr -> {
|
||||
assertThat(ovrdAttr.getRelatedMthNodes()).hasSize(3);
|
||||
assertThat(ovrdAttr.getOverrideList()).isEmpty();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,6 @@ import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -39,6 +32,7 @@ import jadx.api.JavaField;
|
||||
import jadx.api.JavaMethod;
|
||||
import jadx.api.JavaNode;
|
||||
import jadx.core.codegen.CodeWriter;
|
||||
import jadx.core.deobf.DeobfPresets;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.attributes.nodes.MethodOverrideAttr;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
@@ -117,85 +111,25 @@ public class RenameDialog extends JDialog {
|
||||
return false; // TODO: can't open dialog, 'node' is replaced with new one after reopen
|
||||
}
|
||||
|
||||
private Path getDeobfMapPath(RootNode root) {
|
||||
List<File> inputFiles = root.getArgs().getInputFiles();
|
||||
if (inputFiles.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
File firstInputFile = inputFiles.get(0);
|
||||
Path inputFilePath = firstInputFile.getAbsoluteFile().toPath();
|
||||
|
||||
String inputName = inputFilePath.getFileName().toString();
|
||||
String baseName = inputName.substring(0, inputName.lastIndexOf('.'));
|
||||
return inputFilePath.getParent().resolve(baseName + ".jobf");
|
||||
}
|
||||
|
||||
private String getNodeAlias(String renameText) {
|
||||
String type = "";
|
||||
String id = "";
|
||||
private void updateDeobfMap(DeobfPresets deobfPresets, String renameText) {
|
||||
if (node instanceof JMethod) {
|
||||
JavaMethod javaMethod = (JavaMethod) node.getJavaNode();
|
||||
type = "m";
|
||||
MethodNode mthNode = javaMethod.getMethodNode();
|
||||
MethodNode mthNode = ((JavaMethod) node.getJavaNode()).getMethodNode();
|
||||
MethodOverrideAttr overrideAttr = mthNode.get(AType.METHOD_OVERRIDE);
|
||||
if (overrideAttr != null) {
|
||||
// use method closest to base method
|
||||
mthNode = Objects.requireNonNull(Utils.last(overrideAttr.getRelatedMthNodes()));
|
||||
for (MethodNode relatedMth : overrideAttr.getRelatedMthNodes()) {
|
||||
deobfPresets.getMthPresetMap().put(relatedMth.getMethodInfo().getRawFullId(), renameText);
|
||||
}
|
||||
}
|
||||
id = mthNode.getMethodInfo().getRawFullId();
|
||||
deobfPresets.getMthPresetMap().put(mthNode.getMethodInfo().getRawFullId(), renameText);
|
||||
} else if (node instanceof JField) {
|
||||
JavaField javaField = (JavaField) node.getJavaNode();
|
||||
type = "f";
|
||||
id = javaField.getFieldNode().getFieldInfo().getRawFullId();
|
||||
deobfPresets.getFldPresetMap().put(javaField.getFieldNode().getFieldInfo().getRawFullId(), renameText);
|
||||
} else if (node instanceof JClass) {
|
||||
JavaClass javaClass = (JavaClass) node.getJavaNode();
|
||||
type = "c";
|
||||
id = javaClass.getRawName();
|
||||
deobfPresets.getClsPresetMap().put(javaClass.getRawName(), renameText);
|
||||
} else if (node instanceof JPackage) {
|
||||
type = "p";
|
||||
id = ((JPackage) node).getFullName();
|
||||
deobfPresets.getPkgPresetMap().put(((JPackage) node).getFullName(), renameText);
|
||||
}
|
||||
return String.format("%s %s = %s", type, id, renameText);
|
||||
}
|
||||
|
||||
private void writeDeobfMapFile(Path deobfMapPath, List<String> deobfMap) throws IOException {
|
||||
if (deobfMapPath == null) {
|
||||
LOG.error("updateDeobfMapFile(): deobfMapPath is null!");
|
||||
return;
|
||||
}
|
||||
Path deobfMapDir = deobfMapPath.getParent();
|
||||
Path tmpFile = Files.createTempFile(deobfMapDir, "deobf_tmp_", ".txt");
|
||||
|
||||
try (Writer writer = Files.newBufferedWriter(tmpFile, StandardCharsets.UTF_8)) {
|
||||
for (String entry : deobfMap) {
|
||||
writer.write(entry);
|
||||
writer.write(System.lineSeparator());
|
||||
}
|
||||
}
|
||||
Files.move(tmpFile, deobfMapPath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
|
||||
LOG.info("Updated deobf file {}", deobfMapPath);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<String> readDeobfMap(Path deobfMapPath) throws IOException {
|
||||
return Files.readAllLines(deobfMapPath, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private List<String> updateDeobfMap(List<String> deobfMap, String alias) {
|
||||
String id = alias.substring(0, alias.indexOf('=') + 1);
|
||||
int i = 0;
|
||||
while (i < deobfMap.size()) {
|
||||
String entry = deobfMap.get(i);
|
||||
if (entry.startsWith(id)) {
|
||||
LOG.debug("updateDeobfMap(): Removing entry {}", entry);
|
||||
deobfMap.remove(i);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
LOG.debug("updateDeobfMap(): placing alias = {}", alias);
|
||||
deobfMap.add(alias);
|
||||
return deobfMap;
|
||||
}
|
||||
|
||||
private void rename() {
|
||||
@@ -223,18 +157,20 @@ public class RenameDialog extends JDialog {
|
||||
}
|
||||
|
||||
private boolean refreshDeobfMapFile(String renameText, RootNode root) {
|
||||
List<String> deobfMap;
|
||||
Path deobfMapPath = getDeobfMapPath(root);
|
||||
DeobfPresets deobfPresets = DeobfPresets.build(root);
|
||||
if (deobfPresets == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
deobfMap = readDeobfMap(deobfMapPath);
|
||||
} catch (IOException e) {
|
||||
deobfPresets.load();
|
||||
} catch (Exception e) {
|
||||
LOG.error("rename(): readDeobfMap() failed");
|
||||
return false;
|
||||
}
|
||||
updateDeobfMap(deobfMap, getNodeAlias(renameText));
|
||||
updateDeobfMap(deobfPresets, renameText);
|
||||
try {
|
||||
writeDeobfMapFile(deobfMapPath, deobfMap);
|
||||
} catch (IOException e) {
|
||||
deobfPresets.save();
|
||||
} catch (Exception e) {
|
||||
LOG.error("rename(): writeDeobfMap() failed");
|
||||
return false;
|
||||
}
|
||||
@@ -301,7 +237,7 @@ public class RenameDialog extends JDialog {
|
||||
cls.reload();
|
||||
IndexJob.refreshIndex(cache, cls.getCls());
|
||||
} catch (Exception e) {
|
||||
LOG.error("Failed to reload class: {}", cls, e);
|
||||
LOG.error("Failed to reload class: {}", cls.getFullName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user