Skip to content
This repository was archived by the owner on Jan 2, 2023. It is now read-only.

Commit 7b064df

Browse files
authored
Merge pull request #1 from Enaium/develop
Develop
2 parents 5ac5d6d + 504560b commit 7b064df

19 files changed

+672
-80
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
}
77

88
group 'cn.enaium'
9-
version '0.3.0'
9+
version '0.4.0'
1010

1111
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
1212

src/main/java/cn/enaium/joe/JavaOctetEditor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import cn.enaium.joe.gui.panel.file.tree.FileTreePanel;
2323
import cn.enaium.joe.gui.panel.menu.FileMenu;
2424
import cn.enaium.joe.gui.panel.menu.HelpMenu;
25+
import cn.enaium.joe.gui.panel.menu.SearchMenu;
2526
import cn.enaium.joe.jar.Jar;
2627
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
2728
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
@@ -58,6 +59,7 @@ public void run() {
5859
window.setJMenuBar(new JMenuBar() {{
5960
add(new FileMenu());
6061
add(new HelpMenu());
62+
add(new SearchMenu());
6163
}});
6264

6365
window.setContentPane(new JPanel(new BorderLayout()) {

src/main/java/cn/enaium/joe/gui/panel/CodeArea.java renamed to src/main/java/cn/enaium/joe/dialog/SearchDialog.java

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,22 @@
1414
* limitations under the License.
1515
*/
1616

17-
package cn.enaium.joe.gui.panel;
17+
package cn.enaium.joe.dialog;
1818

19-
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
20-
import org.fife.ui.rsyntaxtextarea.Theme;
19+
import cn.enaium.joe.gui.panel.search.Result;
2120

22-
import java.io.IOException;
21+
import java.awt.*;
2322

2423
/**
2524
* @author Enaium
2625
*/
27-
public class CodeArea extends RSyntaxTextArea {
28-
public CodeArea() {
29-
setCodeFoldingEnabled(true);
30-
setEditable(false);
31-
Theme theme = null;
32-
try {
33-
theme = Theme.load(getClass().getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml"));
34-
} catch (IOException e) {
35-
throw new RuntimeException(e);
36-
}
37-
theme.apply(this);
26+
public class SearchDialog extends Dialog {
27+
public Result result = new Result();
28+
29+
public SearchDialog() {
30+
super("Search");
31+
setLayout(new BorderLayout());
32+
setSize(400, 300);
33+
add(result, BorderLayout.CENTER);
3834
}
3935
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2022 Enaium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package cn.enaium.joe.dialog.search;
18+
19+
import cn.enaium.joe.JavaOctetEditor;
20+
import cn.enaium.joe.dialog.SearchDialog;
21+
import cn.enaium.joe.gui.panel.search.ResultNode;
22+
import cn.enaium.joe.jar.Jar;
23+
import cn.enaium.joe.util.ASyncUtil;
24+
import org.objectweb.asm.tree.AbstractInsnNode;
25+
import org.objectweb.asm.tree.ClassNode;
26+
import org.objectweb.asm.tree.LdcInsnNode;
27+
import org.objectweb.asm.tree.MethodNode;
28+
29+
import javax.swing.*;
30+
import java.awt.*;
31+
import java.util.Map;
32+
33+
/**
34+
* @author Enaium
35+
*/
36+
public class SearchLdcDialog extends SearchDialog {
37+
public SearchLdcDialog() {
38+
setTitle("Search LDC");
39+
add(new JPanel(new FlowLayout()) {{
40+
JTextField text = new JTextField(15);
41+
add(text);
42+
add(new JButton("Search") {{
43+
addActionListener(e -> {
44+
if (!text.getText().replace(" ", "").isEmpty()) {
45+
Jar jar = JavaOctetEditor.getInstance().jar;
46+
ASyncUtil.execute(() -> {
47+
float loaded = 0;
48+
float total = 0;
49+
for (Map.Entry<String, ClassNode> stringClassNodeEntry : jar.classes.entrySet()) {
50+
for (MethodNode method : stringClassNodeEntry.getValue().methods) {
51+
total += method.instructions.size();
52+
}
53+
}
54+
55+
for (Map.Entry<String, ClassNode> stringClassNodeEntry : jar.classes.entrySet()) {
56+
for (MethodNode method : stringClassNodeEntry.getValue().methods) {
57+
58+
for (AbstractInsnNode instruction : method.instructions) {
59+
if (instruction instanceof LdcInsnNode) {
60+
String ldc = ((LdcInsnNode) instruction).cst.toString();
61+
if (ldc.contains(text.getText())) {
62+
((DefaultListModel<ResultNode>) result.getList().getModel()).addElement(new ResultNode(stringClassNodeEntry.getValue(), ldc));
63+
}
64+
}
65+
JavaOctetEditor.getInstance().bottomPanel.setProcess((int) ((loaded++ / total) * 100f));
66+
}
67+
}
68+
}
69+
JavaOctetEditor.getInstance().bottomPanel.setProcess(0);
70+
});
71+
}
72+
});
73+
}});
74+
}}, BorderLayout.SOUTH);
75+
}
76+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright 2022 Enaium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package cn.enaium.joe.gui.panel;
18+
19+
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
20+
import org.fife.ui.rsyntaxtextarea.Theme;
21+
import org.fife.ui.rtextarea.RTextScrollPane;
22+
import org.fife.ui.rtextarea.SearchContext;
23+
import org.fife.ui.rtextarea.SearchEngine;
24+
25+
import javax.swing.*;
26+
import java.awt.*;
27+
import java.awt.event.ActionEvent;
28+
import java.awt.event.ActionListener;
29+
import java.io.IOException;
30+
31+
/**
32+
* @author Enaium
33+
*/
34+
public class CodeAreaPanel extends JPanel implements ActionListener {
35+
36+
private RSyntaxTextArea textArea;
37+
private JTextField searchField;
38+
private JCheckBox regexCB;
39+
private JCheckBox matchCaseCB;
40+
41+
public CodeAreaPanel() {
42+
super(new BorderLayout());
43+
textArea = new RSyntaxTextArea();
44+
textArea.setCodeFoldingEnabled(true);
45+
textArea.setEditable(false);
46+
Theme theme = null;
47+
try {
48+
theme = Theme.load(getClass().getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml"));
49+
} catch (IOException e) {
50+
throw new RuntimeException(e);
51+
}
52+
theme.apply(textArea);
53+
54+
add(new RTextScrollPane(textArea), BorderLayout.CENTER);
55+
JToolBar toolBar = new JToolBar();
56+
searchField = new JTextField(30);
57+
toolBar.add(searchField);
58+
final JButton nextButton = new JButton("Find Next");
59+
nextButton.setActionCommand("FindNext");
60+
nextButton.addActionListener(this);
61+
toolBar.add(nextButton);
62+
searchField.addActionListener(e -> nextButton.doClick(0));
63+
JButton prevButton = new JButton("Find Previous");
64+
prevButton.setActionCommand("FindPrev");
65+
prevButton.addActionListener(this);
66+
toolBar.add(prevButton);
67+
regexCB = new JCheckBox("Regex");
68+
toolBar.add(regexCB);
69+
matchCaseCB = new JCheckBox("Match Case");
70+
toolBar.add(matchCaseCB);
71+
add(toolBar, BorderLayout.NORTH);
72+
}
73+
74+
@Override
75+
public void actionPerformed(ActionEvent e) {
76+
77+
// "FindNext" => search forward, "FindPrev" => search backward
78+
String command = e.getActionCommand();
79+
boolean forward = "FindNext".equals(command);
80+
81+
// Create an object defining our search parameters.
82+
SearchContext context = new SearchContext();
83+
String text = searchField.getText();
84+
if (text.length() == 0) {
85+
return;
86+
}
87+
context.setSearchFor(text);
88+
context.setMatchCase(matchCaseCB.isSelected());
89+
context.setRegularExpression(regexCB.isSelected());
90+
context.setSearchForward(forward);
91+
context.setWholeWord(false);
92+
93+
SearchEngine.find(textArea, context);
94+
}
95+
96+
public RSyntaxTextArea getTextArea() {
97+
return textArea;
98+
}
99+
}

src/main/java/cn/enaium/joe/gui/panel/LeftPanel.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import cn.enaium.joe.JavaOctetEditor;
2020
import cn.enaium.joe.gui.panel.file.tree.FileTreePanel;
2121
import cn.enaium.joe.jar.Jar;
22+
import cn.enaium.joe.util.JTreeUtil;
2223

2324
import javax.swing.*;
2425
import javax.swing.border.EmptyBorder;
@@ -50,10 +51,25 @@ public void keyPressed(KeyEvent e) {
5051
if (!jTextField.getText().replace(" ", "").isEmpty()) {
5152
Jar searchedJar = jar.copy();
5253

53-
searchedJar.classes = searchedJar.classes.entrySet().stream().filter(stringClassNodeEntry -> stringClassNodeEntry.getKey().toLowerCase(Locale.ROOT).contains(jTextField.getText().toLowerCase(Locale.ROOT))).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
54-
searchedJar.resources = searchedJar.resources.entrySet().stream().filter(stringEntry -> stringEntry.getKey().toLowerCase(Locale.ROOT).contains(jTextField.getText().toLowerCase(Locale.ROOT))).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
54+
searchedJar.classes = searchedJar.classes.entrySet().stream().filter(stringClassNodeEntry -> {
55+
String key = stringClassNodeEntry.getKey();
56+
57+
if (!key.contains("/")) {
58+
key = key.substring(key.lastIndexOf("/") + 1);
59+
}
60+
61+
return key.toLowerCase(Locale.ROOT).contains(jTextField.getText().toLowerCase(Locale.ROOT));
62+
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
63+
searchedJar.resources = searchedJar.resources.entrySet().stream().filter(stringEntry -> {
64+
String key = stringEntry.getKey();
65+
if (!key.contains("/")) {
66+
key = key.substring(key.lastIndexOf("/") + 1);
67+
}
68+
return key.toLowerCase(Locale.ROOT).contains(jTextField.getText().toLowerCase(Locale.ROOT));
69+
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
5570

5671
JavaOctetEditor.getInstance().fileTreePanel.refresh(searchedJar);
72+
JTreeUtil.setTreeExpandedState(JavaOctetEditor.getInstance().fileTreePanel, true);
5773
} else {
5874
JavaOctetEditor.getInstance().fileTreePanel.refresh(jar);
5975
}

src/main/java/cn/enaium/joe/gui/panel/file/tabbed/tab/ASMifierTablePanel.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
package cn.enaium.joe.gui.panel.file.tabbed.tab;
1818

1919
import cn.enaium.joe.JavaOctetEditor;
20-
import cn.enaium.joe.gui.panel.CodeArea;
20+
import cn.enaium.joe.gui.panel.CodeAreaPanel;
2121
import cn.enaium.joe.util.ASyncUtil;
2222
import javassist.ClassPool;
2323
import javassist.CtClass;
@@ -44,18 +44,7 @@ public class ASMifierTablePanel extends ClassNodeTabPanel {
4444
public ASMifierTablePanel(ClassNode classNode) {
4545
super(classNode);
4646
setLayout(new BorderLayout());
47-
CodeArea codeArea = new CodeArea();
48-
codeArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
49-
codeArea.setEditable(true);
50-
StringWriter stringWriter = new StringWriter();
51-
ASyncUtil.execute(() -> {
52-
classNode.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(stringWriter)));
53-
}, () -> {
54-
String trim = getMiddle(getMiddle(stringWriter.toString())).trim();
55-
codeArea.setText(trim.substring(0, trim.lastIndexOf("\n")));
56-
codeArea.setCaretPosition(0);
57-
});
58-
add(new RTextScrollPane(codeArea) {{
47+
CodeAreaPanel codeAreaPanel = new CodeAreaPanel(){{
5948
getTextArea().addKeyListener(new KeyAdapter() {
6049

6150
boolean control = false;
@@ -87,7 +76,7 @@ public void keyPressed(KeyEvent e) {
8776
classPool.importPackage("org.objectweb.asm.TypePath");
8877
CtClass ctClass = classPool.makeClass(ASMifier.class.getSimpleName());
8978
ctClass.addInterface(classPool.get("org.objectweb.asm.Opcodes"));
90-
ctClass.addMethod(CtMethod.make("public static byte[] dump() throws Exception {" + codeArea.getText() + "return classWriter.toByteArray();}", ctClass));
79+
ctClass.addMethod(CtMethod.make("public static byte[] dump() throws Exception {" + getTextArea().getText() + "return classWriter.toByteArray();}", ctClass));
9180
byte[] dumps = (byte[]) new Loader(classPool).loadClass(ASMifier.class.getSimpleName()).getMethod("dump").invoke(null);
9281
ClassNode newClassNode = new ClassNode();
9382
new ClassReader(dumps).accept(newClassNode, ClassReader.EXPAND_FRAMES);
@@ -107,7 +96,18 @@ public void keyReleased(KeyEvent e) {
10796
}
10897
}
10998
});
110-
}});
99+
}};
100+
codeAreaPanel.getTextArea().setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
101+
codeAreaPanel.getTextArea().setEditable(true);
102+
StringWriter stringWriter = new StringWriter();
103+
ASyncUtil.execute(() -> {
104+
classNode.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(stringWriter)));
105+
}, () -> {
106+
String trim = getMiddle(getMiddle(stringWriter.toString())).trim();
107+
codeAreaPanel.getTextArea().setText(trim.substring(0, trim.lastIndexOf("\n")));
108+
codeAreaPanel.getTextArea().setCaretPosition(0);
109+
});
110+
add(codeAreaPanel);
111111
}
112112

113113
public String getMiddle(String s) {
Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
package cn.enaium.joe.gui.panel.file.tabbed.tab;
22

3-
import cn.enaium.joe.gui.panel.CodeArea;
3+
import cn.enaium.joe.gui.panel.CodeAreaPanel;
44
import cn.enaium.joe.util.ASyncUtil;
5-
import org.benf.cfr.reader.PluginRunner;
6-
import org.benf.cfr.reader.api.ClassFileSource;
7-
import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair;
5+
import cn.enaium.joe.util.CfrUtil;
86
import org.fife.ui.rtextarea.RTextScrollPane;
9-
import org.objectweb.asm.ClassWriter;
107
import org.objectweb.asm.tree.ClassNode;
118

129
import java.awt.*;
13-
import java.io.IOException;
14-
import java.util.Collection;
15-
import java.util.HashMap;
1610

1711
/**
1812
* @author Enaium
@@ -21,39 +15,12 @@ public class DecompileTabPanel extends ClassNodeTabPanel {
2115
public DecompileTabPanel(ClassNode classNode) {
2216
super(classNode);
2317
setLayout(new BorderLayout());
24-
CodeArea codeArea = new CodeArea();
25-
codeArea.setSyntaxEditingStyle("text/java");
18+
CodeAreaPanel codeAreaPanel = new CodeAreaPanel();
19+
codeAreaPanel.getTextArea().setSyntaxEditingStyle("text/java");
2620
ASyncUtil.execute(() -> {
27-
ClassFileSource cfs = new ClassFileSource() {
28-
@Override
29-
public void informAnalysisRelativePathDetail(String a, String b) {
30-
}
31-
32-
@Override
33-
public String getPossiblyRenamedPath(String path) {
34-
return path;
35-
}
36-
37-
@Override
38-
public Pair<byte[], String> getClassFileContent(String path) throws IOException {
39-
String name = path.substring(0, path.length() - 6);
40-
if (name.equals(classNode.name)) {
41-
ClassWriter classWriter = new ClassWriter(0);
42-
classNode.accept(classWriter);
43-
return Pair.make(classWriter.toByteArray(), name);
44-
}
45-
return null;
46-
}
47-
48-
@Override
49-
public Collection<String> addJar(String arg0) {
50-
throw new RuntimeException();
51-
}
52-
};
53-
54-
codeArea.setText(new PluginRunner(new HashMap<>(), cfs).getDecompilationFor(classNode.name));
21+
codeAreaPanel.getTextArea().setText(CfrUtil.getSource(classNode));
5522
});
56-
codeArea.setCaretPosition(0);
57-
add(new RTextScrollPane(codeArea));
23+
codeAreaPanel.getTextArea().setCaretPosition(0);
24+
add(codeAreaPanel);
5825
}
5926
}

0 commit comments

Comments
 (0)