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

Commit

Permalink
Merge pull request #1 from Enaium/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
Enaium authored Jul 23, 2022
2 parents 5ac5d6d + 504560b commit 7b064df
Show file tree
Hide file tree
Showing 19 changed files with 672 additions and 80 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
}

group 'cn.enaium'
version '0.3.0'
version '0.4.0'

sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/cn/enaium/joe/JavaOctetEditor.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import cn.enaium.joe.gui.panel.file.tree.FileTreePanel;
import cn.enaium.joe.gui.panel.menu.FileMenu;
import cn.enaium.joe.gui.panel.menu.HelpMenu;
import cn.enaium.joe.gui.panel.menu.SearchMenu;
import cn.enaium.joe.jar.Jar;
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
Expand Down Expand Up @@ -58,6 +59,7 @@ public void run() {
window.setJMenuBar(new JMenuBar() {{
add(new FileMenu());
add(new HelpMenu());
add(new SearchMenu());
}});

window.setContentPane(new JPanel(new BorderLayout()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,22 @@
* limitations under the License.
*/

package cn.enaium.joe.gui.panel;
package cn.enaium.joe.dialog;

import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.Theme;
import cn.enaium.joe.gui.panel.search.Result;

import java.io.IOException;
import java.awt.*;

/**
* @author Enaium
*/
public class CodeArea extends RSyntaxTextArea {
public CodeArea() {
setCodeFoldingEnabled(true);
setEditable(false);
Theme theme = null;
try {
theme = Theme.load(getClass().getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml"));
} catch (IOException e) {
throw new RuntimeException(e);
}
theme.apply(this);
public class SearchDialog extends Dialog {
public Result result = new Result();

public SearchDialog() {
super("Search");
setLayout(new BorderLayout());
setSize(400, 300);
add(result, BorderLayout.CENTER);
}
}
76 changes: 76 additions & 0 deletions src/main/java/cn/enaium/joe/dialog/search/SearchLdcDialog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2022 Enaium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package cn.enaium.joe.dialog.search;

import cn.enaium.joe.JavaOctetEditor;
import cn.enaium.joe.dialog.SearchDialog;
import cn.enaium.joe.gui.panel.search.ResultNode;
import cn.enaium.joe.jar.Jar;
import cn.enaium.joe.util.ASyncUtil;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodNode;

import javax.swing.*;
import java.awt.*;
import java.util.Map;

/**
* @author Enaium
*/
public class SearchLdcDialog extends SearchDialog {
public SearchLdcDialog() {
setTitle("Search LDC");
add(new JPanel(new FlowLayout()) {{
JTextField text = new JTextField(15);
add(text);
add(new JButton("Search") {{
addActionListener(e -> {
if (!text.getText().replace(" ", "").isEmpty()) {
Jar jar = JavaOctetEditor.getInstance().jar;
ASyncUtil.execute(() -> {
float loaded = 0;
float total = 0;
for (Map.Entry<String, ClassNode> stringClassNodeEntry : jar.classes.entrySet()) {
for (MethodNode method : stringClassNodeEntry.getValue().methods) {
total += method.instructions.size();
}
}

for (Map.Entry<String, ClassNode> stringClassNodeEntry : jar.classes.entrySet()) {
for (MethodNode method : stringClassNodeEntry.getValue().methods) {

for (AbstractInsnNode instruction : method.instructions) {
if (instruction instanceof LdcInsnNode) {
String ldc = ((LdcInsnNode) instruction).cst.toString();
if (ldc.contains(text.getText())) {
((DefaultListModel<ResultNode>) result.getList().getModel()).addElement(new ResultNode(stringClassNodeEntry.getValue(), ldc));
}
}
JavaOctetEditor.getInstance().bottomPanel.setProcess((int) ((loaded++ / total) * 100f));
}
}
}
JavaOctetEditor.getInstance().bottomPanel.setProcess(0);
});
}
});
}});
}}, BorderLayout.SOUTH);
}
}
99 changes: 99 additions & 0 deletions src/main/java/cn/enaium/joe/gui/panel/CodeAreaPanel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright 2022 Enaium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package cn.enaium.joe.gui.panel;

import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.Theme;
import org.fife.ui.rtextarea.RTextScrollPane;
import org.fife.ui.rtextarea.SearchContext;
import org.fife.ui.rtextarea.SearchEngine;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;

/**
* @author Enaium
*/
public class CodeAreaPanel extends JPanel implements ActionListener {

private RSyntaxTextArea textArea;
private JTextField searchField;
private JCheckBox regexCB;
private JCheckBox matchCaseCB;

public CodeAreaPanel() {
super(new BorderLayout());
textArea = new RSyntaxTextArea();
textArea.setCodeFoldingEnabled(true);
textArea.setEditable(false);
Theme theme = null;
try {
theme = Theme.load(getClass().getResourceAsStream("/org/fife/ui/rsyntaxtextarea/themes/dark.xml"));
} catch (IOException e) {
throw new RuntimeException(e);
}
theme.apply(textArea);

add(new RTextScrollPane(textArea), BorderLayout.CENTER);
JToolBar toolBar = new JToolBar();
searchField = new JTextField(30);
toolBar.add(searchField);
final JButton nextButton = new JButton("Find Next");
nextButton.setActionCommand("FindNext");
nextButton.addActionListener(this);
toolBar.add(nextButton);
searchField.addActionListener(e -> nextButton.doClick(0));
JButton prevButton = new JButton("Find Previous");
prevButton.setActionCommand("FindPrev");
prevButton.addActionListener(this);
toolBar.add(prevButton);
regexCB = new JCheckBox("Regex");
toolBar.add(regexCB);
matchCaseCB = new JCheckBox("Match Case");
toolBar.add(matchCaseCB);
add(toolBar, BorderLayout.NORTH);
}

@Override
public void actionPerformed(ActionEvent e) {

// "FindNext" => search forward, "FindPrev" => search backward
String command = e.getActionCommand();
boolean forward = "FindNext".equals(command);

// Create an object defining our search parameters.
SearchContext context = new SearchContext();
String text = searchField.getText();
if (text.length() == 0) {
return;
}
context.setSearchFor(text);
context.setMatchCase(matchCaseCB.isSelected());
context.setRegularExpression(regexCB.isSelected());
context.setSearchForward(forward);
context.setWholeWord(false);

SearchEngine.find(textArea, context);
}

public RSyntaxTextArea getTextArea() {
return textArea;
}
}
20 changes: 18 additions & 2 deletions src/main/java/cn/enaium/joe/gui/panel/LeftPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import cn.enaium.joe.JavaOctetEditor;
import cn.enaium.joe.gui.panel.file.tree.FileTreePanel;
import cn.enaium.joe.jar.Jar;
import cn.enaium.joe.util.JTreeUtil;

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

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));
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));
searchedJar.classes = searchedJar.classes.entrySet().stream().filter(stringClassNodeEntry -> {
String key = stringClassNodeEntry.getKey();

if (!key.contains("/")) {
key = key.substring(key.lastIndexOf("/") + 1);
}

return key.toLowerCase(Locale.ROOT).contains(jTextField.getText().toLowerCase(Locale.ROOT));
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
searchedJar.resources = searchedJar.resources.entrySet().stream().filter(stringEntry -> {
String key = stringEntry.getKey();
if (!key.contains("/")) {
key = key.substring(key.lastIndexOf("/") + 1);
}
return key.toLowerCase(Locale.ROOT).contains(jTextField.getText().toLowerCase(Locale.ROOT));
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

JavaOctetEditor.getInstance().fileTreePanel.refresh(searchedJar);
JTreeUtil.setTreeExpandedState(JavaOctetEditor.getInstance().fileTreePanel, true);
} else {
JavaOctetEditor.getInstance().fileTreePanel.refresh(jar);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package cn.enaium.joe.gui.panel.file.tabbed.tab;

import cn.enaium.joe.JavaOctetEditor;
import cn.enaium.joe.gui.panel.CodeArea;
import cn.enaium.joe.gui.panel.CodeAreaPanel;
import cn.enaium.joe.util.ASyncUtil;
import javassist.ClassPool;
import javassist.CtClass;
Expand All @@ -44,18 +44,7 @@ public class ASMifierTablePanel extends ClassNodeTabPanel {
public ASMifierTablePanel(ClassNode classNode) {
super(classNode);
setLayout(new BorderLayout());
CodeArea codeArea = new CodeArea();
codeArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
codeArea.setEditable(true);
StringWriter stringWriter = new StringWriter();
ASyncUtil.execute(() -> {
classNode.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(stringWriter)));
}, () -> {
String trim = getMiddle(getMiddle(stringWriter.toString())).trim();
codeArea.setText(trim.substring(0, trim.lastIndexOf("\n")));
codeArea.setCaretPosition(0);
});
add(new RTextScrollPane(codeArea) {{
CodeAreaPanel codeAreaPanel = new CodeAreaPanel(){{
getTextArea().addKeyListener(new KeyAdapter() {

boolean control = false;
Expand Down Expand Up @@ -87,7 +76,7 @@ public void keyPressed(KeyEvent e) {
classPool.importPackage("org.objectweb.asm.TypePath");
CtClass ctClass = classPool.makeClass(ASMifier.class.getSimpleName());
ctClass.addInterface(classPool.get("org.objectweb.asm.Opcodes"));
ctClass.addMethod(CtMethod.make("public static byte[] dump() throws Exception {" + codeArea.getText() + "return classWriter.toByteArray();}", ctClass));
ctClass.addMethod(CtMethod.make("public static byte[] dump() throws Exception {" + getTextArea().getText() + "return classWriter.toByteArray();}", ctClass));
byte[] dumps = (byte[]) new Loader(classPool).loadClass(ASMifier.class.getSimpleName()).getMethod("dump").invoke(null);
ClassNode newClassNode = new ClassNode();
new ClassReader(dumps).accept(newClassNode, ClassReader.EXPAND_FRAMES);
Expand All @@ -107,7 +96,18 @@ public void keyReleased(KeyEvent e) {
}
}
});
}});
}};
codeAreaPanel.getTextArea().setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
codeAreaPanel.getTextArea().setEditable(true);
StringWriter stringWriter = new StringWriter();
ASyncUtil.execute(() -> {
classNode.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(stringWriter)));
}, () -> {
String trim = getMiddle(getMiddle(stringWriter.toString())).trim();
codeAreaPanel.getTextArea().setText(trim.substring(0, trim.lastIndexOf("\n")));
codeAreaPanel.getTextArea().setCaretPosition(0);
});
add(codeAreaPanel);
}

public String getMiddle(String s) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
package cn.enaium.joe.gui.panel.file.tabbed.tab;

import cn.enaium.joe.gui.panel.CodeArea;
import cn.enaium.joe.gui.panel.CodeAreaPanel;
import cn.enaium.joe.util.ASyncUtil;
import org.benf.cfr.reader.PluginRunner;
import org.benf.cfr.reader.api.ClassFileSource;
import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair;
import cn.enaium.joe.util.CfrUtil;
import org.fife.ui.rtextarea.RTextScrollPane;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;

import java.awt.*;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;

/**
* @author Enaium
Expand All @@ -21,39 +15,12 @@ public class DecompileTabPanel extends ClassNodeTabPanel {
public DecompileTabPanel(ClassNode classNode) {
super(classNode);
setLayout(new BorderLayout());
CodeArea codeArea = new CodeArea();
codeArea.setSyntaxEditingStyle("text/java");
CodeAreaPanel codeAreaPanel = new CodeAreaPanel();
codeAreaPanel.getTextArea().setSyntaxEditingStyle("text/java");
ASyncUtil.execute(() -> {
ClassFileSource cfs = new ClassFileSource() {
@Override
public void informAnalysisRelativePathDetail(String a, String b) {
}

@Override
public String getPossiblyRenamedPath(String path) {
return path;
}

@Override
public Pair<byte[], String> getClassFileContent(String path) throws IOException {
String name = path.substring(0, path.length() - 6);
if (name.equals(classNode.name)) {
ClassWriter classWriter = new ClassWriter(0);
classNode.accept(classWriter);
return Pair.make(classWriter.toByteArray(), name);
}
return null;
}

@Override
public Collection<String> addJar(String arg0) {
throw new RuntimeException();
}
};

codeArea.setText(new PluginRunner(new HashMap<>(), cfs).getDecompilationFor(classNode.name));
codeAreaPanel.getTextArea().setText(CfrUtil.getSource(classNode));
});
codeArea.setCaretPosition(0);
add(new RTextScrollPane(codeArea));
codeAreaPanel.getTextArea().setCaretPosition(0);
add(codeAreaPanel);
}
}
Loading

0 comments on commit 7b064df

Please sign in to comment.