feat(gui): show loaded mapping file in input nodes

This commit is contained in:
Skylot
2023-02-28 16:04:13 +00:00
parent 7d69e5aaab
commit 9f7432134c
9 changed files with 151 additions and 11 deletions
@@ -7,4 +7,6 @@ public interface ICodeData {
List<ICodeComment> getComments();
List<ICodeRename> getRenames();
boolean isEmpty();
}
@@ -28,4 +28,9 @@ public class JadxCodeData implements ICodeData {
public void setRenames(List<ICodeRename> renames) {
this.renames = renames;
}
@Override
public boolean isEmpty() {
return comments.isEmpty() && renames.isEmpty();
}
}
@@ -40,4 +40,9 @@ public class JInputFile extends JNode {
public String makeString() {
return filePath.getFileName().toString();
}
@Override
public String getTooltip() {
return filePath.normalize().toAbsolutePath().toString();
}
}
@@ -0,0 +1,99 @@
package jadx.gui.treemodel;
import java.nio.file.Path;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JPopupMenu;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.ICodeInfo;
import jadx.api.impl.SimpleCodeInfo;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.utils.files.FileUtils;
import jadx.gui.ui.MainWindow;
import jadx.gui.ui.TabbedPane;
import jadx.gui.ui.codearea.CodeContentPanel;
import jadx.gui.ui.panel.ContentPanel;
import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
import jadx.gui.utils.ui.SimpleMenuItem;
public class JInputMapping extends JEditableNode {
private static final Logger LOG = LoggerFactory.getLogger(JInputMapping.class);
private static final ImageIcon MAPPING_ICON = UiUtils.openSvgIcon("nodes/abbreviatePackageNames");
private final Path mappingPath;
private final String name;
public JInputMapping(Path mappingPath) {
this.mappingPath = mappingPath;
this.name = mappingPath.getFileName().toString();
}
@Override
public ContentPanel getContentPanel(TabbedPane tabbedPane) {
return new CodeContentPanel(tabbedPane, this);
}
@Override
public @NotNull ICodeInfo getCodeInfo() {
try {
return new SimpleCodeInfo(FileUtils.readFile(mappingPath));
} catch (Exception e) {
throw new JadxRuntimeException("Failed to read mapping file: " + mappingPath.toAbsolutePath(), e);
}
}
@Override
public void save(String newContent) {
try {
FileUtils.writeFile(mappingPath, newContent);
LOG.debug("Mapping saved: {}", mappingPath.toAbsolutePath());
} catch (Exception e) {
throw new JadxRuntimeException("Failed to write mapping file: " + mappingPath.toAbsolutePath(), e);
}
}
@Override
public JPopupMenu onTreePopupMenu(MainWindow mainWindow) {
JPopupMenu menu = new JPopupMenu();
menu.add(new SimpleMenuItem(NLS.str("popup.remove"), mainWindow::closeMappingsAndRemoveFromProject));
return menu;
}
@Override
public String getSyntaxName() {
return SyntaxConstants.SYNTAX_STYLE_NONE;
}
@Override
public JClass getJParent() {
return null;
}
@Override
public Icon getIcon() {
return MAPPING_ICON;
}
@Override
public String getName() {
return name;
}
@Override
public String makeString() {
return name;
}
@Override
public String getTooltip() {
return mappingPath.normalize().toAbsolutePath().toString();
}
}
@@ -93,4 +93,9 @@ public class JInputScript extends JEditableNode {
public String makeString() {
return name;
}
@Override
public String getTooltip() {
return scriptPath.normalize().toAbsolutePath().toString();
}
}
@@ -1,5 +1,6 @@
package jadx.gui.treemodel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Iterator;
@@ -10,6 +11,7 @@ import javax.swing.ImageIcon;
import jadx.core.utils.files.FileUtils;
import jadx.gui.JadxWrapper;
import jadx.gui.settings.JadxProject;
import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
@@ -17,7 +19,8 @@ public class JInputs extends JNode {
private static final ImageIcon INPUTS_ICON = UiUtils.openSvgIcon("nodes/projectStructure");
public JInputs(JadxWrapper wrapper) {
List<Path> inputs = wrapper.getProject().getFilePaths();
JadxProject project = wrapper.getProject();
List<Path> inputs = project.getFilePaths();
List<Path> files = FileUtils.expandDirs(inputs);
List<Path> scripts = new ArrayList<>();
Iterator<Path> it = files.iterator();
@@ -31,6 +34,11 @@ public class JInputs extends JNode {
add(new JInputFiles(files));
add(new JInputScripts(scripts));
Path mappingsPath = project.getMappingsPath();
if (mappingsPath != null && Files.isRegularFile(mappingsPath)) {
add(new JInputMapping(mappingsPath));
}
}
@Override
@@ -410,7 +410,7 @@ public class MainWindow extends JFrame {
reopen();
}
private void closeMappingsAndRemoveFromProject() {
public void closeMappingsAndRemoveFromProject() {
project.setMappingsPath(null);
currentMappingFormat = null;
}
@@ -718,9 +718,8 @@ public class MainWindow extends JFrame {
saveProjectAction.setEnabled(loaded && !project.isSaved());
openMappingsMenu.setEnabled(loaded);
saveMappingsAction.setEnabled(loaded && renamesChanged && project.getMappingsPath() != null);
saveMappingsAsMenu.setEnabled(loaded
&& (!project.getCodeData().getRenames().isEmpty() || !project.getCodeData().getComments().isEmpty()));
closeMappingsAction.setEnabled(loaded && project.getMappingsPath() != null);
saveMappingsAsMenu.setEnabled(loaded && !project.getCodeData().isEmpty());
closeMappingsAction.setEnabled(project.getMappingsPath() != null);
deobfToggleBtn.setSelected(settings.isDeobfuscationOn());
Path projectPath = project.getProjectPath();
@@ -1013,6 +1012,9 @@ public class MainWindow extends JFrame {
liveReloadMenuItem = new JCheckBoxMenuItem(liveReload);
liveReloadMenuItem.setState(project.isEnableLiveReload());
ActionHandler openProGuardMappings = new ActionHandler(ev -> openMappings(MappingFormat.PROGUARD));
openProGuardMappings.setNameAndDesc("Proguard");
Action openTiny2Mappings = new AbstractAction("Tiny v2 file") {
@Override
public void actionPerformed(ActionEvent e) {
@@ -1038,6 +1040,7 @@ public class MainWindow extends JFrame {
openEnigmaDirMappings.putValue(Action.SHORT_DESCRIPTION, "Enigma directory");
openMappingsMenu = new JMenu(NLS.str("file.open_mappings"));
openMappingsMenu.add(openProGuardMappings);
openMappingsMenu.add(openTiny2Mappings);
openMappingsMenu.add(openEnigmaMappings);
openMappingsMenu.add(openEnigmaDirMappings);
@@ -1050,6 +1053,9 @@ public class MainWindow extends JFrame {
};
saveMappingsAction.putValue(Action.SHORT_DESCRIPTION, NLS.str("file.save_mappings"));
ActionHandler saveProGuardMappings = new ActionHandler(ev -> saveMappingsAs(MappingFormat.PROGUARD));
saveProGuardMappings.setNameAndDesc("Proguard");
Action saveMappingsAsTiny2 = new AbstractAction("Tiny v2 file") {
@Override
public void actionPerformed(ActionEvent e) {
@@ -1075,6 +1081,7 @@ public class MainWindow extends JFrame {
saveMappingsAsEnigmaDir.putValue(Action.SHORT_DESCRIPTION, "Enigma directory");
saveMappingsAsMenu = new JMenu(NLS.str("file.save_mappings_as"));
saveMappingsAsMenu.add(saveProGuardMappings);
saveMappingsAsMenu.add(saveMappingsAsTiny2);
saveMappingsAsMenu.add(saveMappingsAsEnigma);
saveMappingsAsMenu.add(saveMappingsAsEnigmaDir);
@@ -1765,8 +1772,10 @@ public class MainWindow extends JFrame {
public void destroyDebuggerPanel() {
saveSplittersInfo();
debuggerPanel.setVisible(false);
debuggerPanel = null;
if (debuggerPanel != null) {
debuggerPanel.setVisible(false);
debuggerPanel = null;
}
}
public void showHeapUsageBar() {
@@ -0,0 +1,7 @@
<!-- Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<g fill="none" fill-rule="evenodd">
<path fill="#6E6E6E" d="M8.5,13 L3,13 L3,8 L14,8 L14,13 L8.5,13 L2,13 L2,5 L2,3 L6.60006714,3 L7.75640322,5 L14,5 L14,13 L8.5,13 Z"/>
<path fill="#6E6E6E" d="M5.684,15.088 C4.892,15.088 4.18,14.632 4.18,13.784 L4.18,13.768 C4.18,12.856 4.9,12.408 5.932,12.408 C6.404,12.408 6.74,12.48 7.068,12.584 L7.068,12.48 C7.068,11.88 6.7,11.56 6.02,11.56 C5.548,11.56 5.196,11.664 4.812,11.824 L4.548,11.064 C5.02,10.856 5.476,10.72 6.148,10.72 C6.78,10.72 7.252,10.888 7.548,11.192 C7.86,11.496 8.004,11.944 8.004,12.496 L8.004,15 L7.06,15 L7.06,14.472 C6.772,14.816 6.332,15.088 5.684,15.088 Z M5.924,14.384 C6.564,14.384 7.052,14.016 7.052,13.48 L7.052,13.192 C6.804,13.096 6.476,13.024 6.092,13.024 C5.468,13.024 5.1,13.288 5.1,13.728 L5.1,13.744 C5.1,14.152 5.46,14.384 5.924,14.384 Z M9,15 L9,14 L10,14 L10,15 L9,15 Z M13.416,15.088 C12.712,15.088 12.272,14.736 11.976,14.344 L11.976,15 L11,15 L11,9 L11.976,9 L11.976,11.48 C12.288,11.04 12.728,10.688 13.416,10.688 C14.408,10.688 15.376,11.472 15.376,12.88 L15.376,12.896 C15.376,14.296 14.416,15.088 13.416,15.088 Z M13.332,14.248 C13.996,14.248 14.54,13.728 14.54,12.896 L14.54,12.88 C14.54,12.064 13.98,11.528 13.332,11.528 C12.676,11.528 12.1,12.072 12.1,12.88 L12.1,12.896 C12.1,13.704 12.676,14.248 13.332,14.248 Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -40,11 +40,11 @@ public class MappingsVisitor implements JadxPreparePass {
private void process(RootNode root) {
for (ClassNode cls : root.getClasses()) {
ClassMapping mapping = mappingTree.getClass(cls.getClassInfo().makeRawFullName().replace('.', '/'));
if (mapping == null) {
continue;
String clsRawName = cls.getClassInfo().makeRawFullName().replace('.', '/');
ClassMapping mapping = mappingTree.getClass(clsRawName);
if (mapping != null) {
processClass(cls, mapping);
}
processClass(cls, mapping);
}
}