2018-01-31 15:03:53 +00:00
|
|
|
package the.bytecode.club.bytecodeviewer.gui;
|
|
|
|
|
|
|
|
import java.awt.BorderLayout;
|
|
|
|
import java.awt.GridLayout;
|
|
|
|
import java.awt.event.ItemListener;
|
2021-04-12 22:31:22 +00:00
|
|
|
import java.util.Objects;
|
2018-01-31 15:03:53 +00:00
|
|
|
import java.util.regex.Pattern;
|
|
|
|
import java.util.regex.PatternSyntaxException;
|
|
|
|
import javax.swing.DefaultComboBoxModel;
|
|
|
|
import javax.swing.JButton;
|
|
|
|
import javax.swing.JCheckBox;
|
|
|
|
import javax.swing.JComboBox;
|
|
|
|
import javax.swing.JLabel;
|
|
|
|
import javax.swing.JPanel;
|
|
|
|
import javax.swing.JScrollPane;
|
|
|
|
import javax.swing.JTree;
|
|
|
|
import javax.swing.tree.DefaultMutableTreeNode;
|
|
|
|
import javax.swing.tree.TreePath;
|
|
|
|
import org.objectweb.asm.tree.ClassNode;
|
2021-04-12 20:19:12 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
|
|
|
import the.bytecode.club.bytecodeviewer.searching.BackgroundSearchThread;
|
|
|
|
import the.bytecode.club.bytecodeviewer.searching.FieldCallSearch;
|
|
|
|
import the.bytecode.club.bytecodeviewer.searching.LDCSearch;
|
|
|
|
import the.bytecode.club.bytecodeviewer.searching.MethodCallSearch;
|
|
|
|
import the.bytecode.club.bytecodeviewer.searching.RegexInsnFinder;
|
|
|
|
import the.bytecode.club.bytecodeviewer.searching.RegexSearch;
|
|
|
|
import the.bytecode.club.bytecodeviewer.searching.SearchResultNotifier;
|
|
|
|
import the.bytecode.club.bytecodeviewer.searching.SearchTypeDetails;
|
2019-04-17 06:45:15 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.util.FileChangeNotifier;
|
|
|
|
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
2018-01-31 15:03:53 +00:00
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
|
|
|
* Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
|
|
|
|
* *
|
|
|
|
* This program is free software: you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A pane dedicating to searching the loaded files.
|
2018-01-31 15:41:24 +00:00
|
|
|
*
|
2018-01-31 15:03:53 +00:00
|
|
|
* @author Konloch
|
|
|
|
* @author WaterWolf
|
|
|
|
*/
|
|
|
|
|
|
|
|
@SuppressWarnings("rawtypes")
|
2021-04-12 20:19:12 +00:00
|
|
|
public class SearchingPane extends VisibleComponent {
|
2018-01-31 15:03:53 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
private static final long serialVersionUID = -1098524689236993932L;
|
2021-04-12 22:31:22 +00:00
|
|
|
public static final SearchRadius[] SEARCH_RADII = SearchRadius.values();
|
|
|
|
public static final SearchType[] SEARCH_TYPES = SearchType.values();
|
2018-01-31 15:03:53 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
FileChangeNotifier fcn;
|
2018-01-31 15:03:53 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
JCheckBox exact = new JCheckBox("Exact");
|
2019-04-17 06:45:15 +00:00
|
|
|
DefaultMutableTreeNode treeRoot = new DefaultMutableTreeNode("Results");
|
2018-01-31 15:41:24 +00:00
|
|
|
JTree tree;
|
2019-04-17 06:45:15 +00:00
|
|
|
JComboBox typeBox;
|
2018-01-31 15:03:53 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
SearchType searchType = null;
|
|
|
|
JComboBox searchRadiusBox;
|
2018-01-31 15:03:53 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
public JButton search = new JButton("Search");
|
2021-04-12 20:19:12 +00:00
|
|
|
BackgroundSearchThread t = new BackgroundSearchThread(true) {
|
2018-01-31 15:41:24 +00:00
|
|
|
@Override
|
2021-04-12 20:19:12 +00:00
|
|
|
public void doSearch() {
|
2018-01-31 15:41:24 +00:00
|
|
|
// empty
|
|
|
|
}
|
2018-01-31 15:03:53 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
};
|
2018-01-31 15:03:53 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
@SuppressWarnings("unchecked")
|
2021-04-12 20:19:12 +00:00
|
|
|
public SearchingPane(final FileChangeNotifier fcn) {
|
2018-01-31 15:41:24 +00:00
|
|
|
super("Search");
|
2018-01-31 15:03:53 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
this.fcn = fcn;
|
2018-01-31 15:03:53 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
final JPanel optionPanel = new JPanel(new BorderLayout());
|
|
|
|
|
|
|
|
final JPanel searchRadiusOpt = new JPanel(new BorderLayout());
|
|
|
|
|
|
|
|
final JPanel searchOpts = new JPanel(new GridLayout(2, 1));
|
|
|
|
|
|
|
|
searchRadiusOpt.add(new JLabel("Search from "), BorderLayout.WEST);
|
|
|
|
|
|
|
|
DefaultComboBoxModel model = new DefaultComboBoxModel();
|
2021-04-12 22:31:22 +00:00
|
|
|
for (final SearchRadius st : SEARCH_RADII) {
|
2018-01-31 15:41:24 +00:00
|
|
|
model.addElement(st);
|
|
|
|
}
|
|
|
|
|
|
|
|
searchRadiusBox = new JComboBox(model);
|
|
|
|
|
|
|
|
searchRadiusOpt.add(searchRadiusBox, BorderLayout.CENTER);
|
|
|
|
|
|
|
|
searchOpts.add(searchRadiusOpt);
|
|
|
|
|
|
|
|
model = new DefaultComboBoxModel();
|
2021-04-12 22:31:22 +00:00
|
|
|
for (final SearchType st : SEARCH_TYPES) {
|
2018-01-31 15:41:24 +00:00
|
|
|
model.addElement(st);
|
|
|
|
}
|
|
|
|
|
2019-04-17 06:45:15 +00:00
|
|
|
typeBox = new JComboBox(model);
|
2018-01-31 15:41:24 +00:00
|
|
|
final JPanel searchOptPanel = new JPanel();
|
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
final ItemListener il = arg0 -> {
|
|
|
|
searchOptPanel.removeAll();
|
|
|
|
searchType = (SearchType) typeBox.getSelectedItem();
|
|
|
|
searchOptPanel.add(Objects.requireNonNull(searchType).details.getPanel());
|
2018-01-31 15:41:24 +00:00
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
searchOptPanel.revalidate();
|
|
|
|
searchOptPanel.repaint();
|
2018-01-31 15:41:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
typeBox.addItemListener(il);
|
|
|
|
|
2019-04-17 06:45:15 +00:00
|
|
|
typeBox.setSelectedItem(SearchType.Strings);
|
2018-01-31 15:41:24 +00:00
|
|
|
il.itemStateChanged(null);
|
|
|
|
|
|
|
|
searchOpts.add(typeBox);
|
|
|
|
|
|
|
|
optionPanel.add(searchOpts, BorderLayout.NORTH);
|
|
|
|
|
|
|
|
JPanel p2 = new JPanel();
|
|
|
|
p2.setLayout(new BorderLayout());
|
|
|
|
p2.add(searchOptPanel, BorderLayout.NORTH);
|
|
|
|
p2.add(exact, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
optionPanel.add(p2, BorderLayout.CENTER);
|
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
search.addActionListener(arg0 -> search());
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
optionPanel.add(search, BorderLayout.SOUTH);
|
|
|
|
|
|
|
|
this.tree = new JTree(treeRoot);
|
|
|
|
|
|
|
|
getContentPane().setLayout(new BorderLayout());
|
|
|
|
|
|
|
|
getContentPane().add(new JScrollPane(optionPanel), BorderLayout.NORTH);
|
|
|
|
getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
|
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
this.tree.addTreeSelectionListener(arg0 -> {
|
|
|
|
if (arg0.getPath().getPathComponent(0).equals("Results"))
|
|
|
|
return;
|
2019-04-17 06:45:15 +00:00
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
arg0.getPath().getPathComponent(1);
|
2019-04-17 06:45:15 +00:00
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
String path = arg0.getPath().getPathComponent(1).toString();
|
2018-01-31 15:41:24 +00:00
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
String containerName = path.split(">", 2)[0];
|
|
|
|
String className = path.split(">", 2)[1].split("\\.")[0];
|
|
|
|
FileContainer container = BytecodeViewer.getFileContainer(containerName);
|
2019-04-17 06:45:15 +00:00
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
final ClassNode fN = Objects.requireNonNull(container).getClassNode(className);
|
2019-04-17 06:45:15 +00:00
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
if (fN != null) {
|
|
|
|
Objects.requireNonNull(MainViewerGUI.getComponent(FileNavigationPane.class))
|
|
|
|
.openClassFileToWorkSpace(container, className + ".class", fN);
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this.setVisible(true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-04-12 20:19:12 +00:00
|
|
|
public void search() {
|
2019-04-17 06:45:15 +00:00
|
|
|
treeRoot.removeAllChildren();
|
|
|
|
searchType = (SearchType) typeBox.getSelectedItem();
|
|
|
|
final SearchRadius radius = (SearchRadius) searchRadiusBox
|
|
|
|
.getSelectedItem();
|
2021-04-12 22:31:22 +00:00
|
|
|
final SearchResultNotifier srn = debug -> treeRoot.add(new DefaultMutableTreeNode(debug));
|
2019-04-17 06:45:15 +00:00
|
|
|
if (radius == SearchRadius.All_Classes) {
|
|
|
|
if (t.finished) {
|
|
|
|
t = new BackgroundSearchThread() {
|
|
|
|
@Override
|
|
|
|
public void doSearch() {
|
|
|
|
|
|
|
|
try {
|
2021-04-12 20:19:12 +00:00
|
|
|
Pattern.compile(RegexInsnFinder.processRegex(RegexSearch.searchText.getText()),
|
|
|
|
Pattern.MULTILINE);
|
2019-04-17 06:45:15 +00:00
|
|
|
} catch (PatternSyntaxException ex) {
|
|
|
|
BytecodeViewer.showMessage("You have an error in your regex syntax.");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (FileContainer container : BytecodeViewer.files)
|
|
|
|
for (ClassNode c : container.classes)
|
|
|
|
searchType.details.search(container, c, srn, exact.isSelected());
|
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
Objects.requireNonNull(MainViewerGUI.getComponent(SearchingPane.class)).search.setEnabled(true);
|
|
|
|
Objects.requireNonNull(MainViewerGUI.getComponent(SearchingPane.class)).search.setText(
|
|
|
|
"Search");
|
2019-04-17 06:45:15 +00:00
|
|
|
tree.expandPath(new TreePath(tree.getModel().getRoot()));
|
|
|
|
tree.updateUI();
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
2021-04-12 22:31:22 +00:00
|
|
|
Objects.requireNonNull(MainViewerGUI.getComponent(SearchingPane.class)).search
|
2019-04-17 06:45:15 +00:00
|
|
|
.setEnabled(false);
|
2021-04-12 22:31:22 +00:00
|
|
|
Objects.requireNonNull(MainViewerGUI.getComponent(SearchingPane.class)).search
|
2019-04-17 06:45:15 +00:00
|
|
|
.setText("Searching, please wait..");
|
|
|
|
t.start();
|
|
|
|
} else { // this should really never be called.
|
|
|
|
BytecodeViewer
|
2021-04-12 20:19:12 +00:00
|
|
|
.showMessage("You currently have a search performing in the background, please wait for that "
|
|
|
|
+ "to finish.");
|
2019-04-17 06:45:15 +00:00
|
|
|
}
|
|
|
|
} else if (radius == SearchRadius.Current_Class) {
|
2021-04-12 22:31:22 +00:00
|
|
|
final Viewer cv = Objects.requireNonNull(MainViewerGUI.getComponent(WorkPane.class)).getCurrentViewer();
|
2019-04-17 06:45:15 +00:00
|
|
|
if (cv != null) {
|
|
|
|
searchType.details.search(cv.container, cv.cn, srn, exact.isSelected());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
public enum SearchType {
|
2019-04-17 06:45:15 +00:00
|
|
|
Strings(new LDCSearch()),
|
|
|
|
Regex(new RegexSearch()),
|
|
|
|
MethodCall(new MethodCallSearch()),
|
|
|
|
FieldCall(new FieldCallSearch());
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
public final SearchTypeDetails details;
|
|
|
|
|
|
|
|
SearchType(final SearchTypeDetails details) {
|
|
|
|
this.details = details;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public enum SearchRadius {
|
2021-04-12 20:19:12 +00:00
|
|
|
All_Classes, Current_Class
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void resetWorkspace() {
|
|
|
|
treeRoot.removeAllChildren();
|
|
|
|
tree.updateUI();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2019-04-17 06:45:15 +00:00
|
|
|
public void openFile(final FileContainer container, String name, byte[] contents) {
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
2018-01-31 15:03:53 +00:00
|
|
|
}
|