mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GT-3547 - Patch dir fix - review fixes
This commit is contained in:
parent
3dced733df
commit
87bda2b34d
14 changed files with 149 additions and 531 deletions
|
@ -1,205 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* 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 ghidra.framework.main;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.*;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import docking.DockingUtils;
|
||||
import docking.options.editor.ButtonPanelFactory;
|
||||
import docking.widgets.filechooser.GhidraFileChooser;
|
||||
|
||||
/**
|
||||
* Helper class that restricts the width of the textField to the size of the
|
||||
* scrolled paths list; also provides the listener for the textfield if user
|
||||
* presses Enter or Tab in a textfield.
|
||||
*
|
||||
*/
|
||||
class BrowsePathPanel extends JPanel {
|
||||
|
||||
private boolean changed;
|
||||
private GhidraFileChooser fileChooser;
|
||||
private JTextField pathTextField;
|
||||
private EditPluginPathDialog dialog;
|
||||
private JButton browseButton;
|
||||
|
||||
/**
|
||||
* Construct a new BrowsePathPanel.
|
||||
* @param editDialog parent dialog
|
||||
* @param sizeComp component to use for size in creating text field
|
||||
* @param button browse button
|
||||
* @param dirOnly
|
||||
* @param textFieldLabel
|
||||
* @param fieldName name of text field component
|
||||
*/
|
||||
BrowsePathPanel(EditPluginPathDialog editDialog, ActionListener buttonListener, String fieldName) {
|
||||
|
||||
super();
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
dialog = editDialog;
|
||||
create(fieldName);
|
||||
addListeners(buttonListener);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the components
|
||||
* @param sizeComp component to use when creating the text field to get the
|
||||
* size
|
||||
* @param textFieldLabel label for the field
|
||||
*/
|
||||
private void create(String fieldName) {
|
||||
pathTextField = new JTextField();
|
||||
pathTextField.setName(fieldName);
|
||||
pathTextField.setEditable(false);
|
||||
pathTextField.setBackground(getBackground());
|
||||
|
||||
browseButton = ButtonPanelFactory.createButton(ButtonPanelFactory.BROWSE_TYPE);
|
||||
browseButton.setToolTipText("Choose Directory");
|
||||
|
||||
// construct the panel with text field and browse button
|
||||
JPanel browsePathPanel = new JPanel(new BorderLayout(5, 5));
|
||||
browsePathPanel.add(pathTextField, BorderLayout.CENTER);
|
||||
browsePathPanel.add(browseButton, BorderLayout.EAST);
|
||||
add(browsePathPanel);
|
||||
|
||||
}
|
||||
|
||||
private void createFileChooser() {
|
||||
// create the fileChooser this panel will use based on its input criteria
|
||||
fileChooser = new GhidraFileChooser(dialog.getComponent());
|
||||
fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
|
||||
fileChooser.setFileSelectionMode(GhidraFileChooser.DIRECTORIES_ONLY);
|
||||
fileChooser.setApproveButtonToolTipText("Choose Directory With Plugin JAR Files");
|
||||
fileChooser.setApproveButtonText("Choose JAR Directory");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add listeners.
|
||||
* @param listener listener for the browse button
|
||||
*/
|
||||
private void addListeners(ActionListener listener) {
|
||||
browseButton.addActionListener(listener);
|
||||
|
||||
pathTextField.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
int keyCode = e.getKeyCode();
|
||||
|
||||
// when Esc or Ctrl-C is pressed, reset the plugin
|
||||
// jar directory to what is saved in preferences
|
||||
if (keyCode == KeyEvent.VK_ESCAPE ||
|
||||
(DockingUtils.isControlModifier(e) && keyCode == KeyEvent.VK_C)) {
|
||||
dialog.initJarDirectory();
|
||||
}
|
||||
else {
|
||||
dialog.setApplyEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
String getPath() {
|
||||
return pathTextField.getText().trim();
|
||||
}
|
||||
|
||||
boolean isChanged() {
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFocus() {
|
||||
return pathTextField.hasFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestFocus() {
|
||||
pathTextField.requestFocus();
|
||||
pathTextField.selectAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop up the file chooser.
|
||||
*/
|
||||
void showFileChooser() {
|
||||
if (fileChooser == null) {
|
||||
createFileChooser();
|
||||
}
|
||||
// reset the status message
|
||||
dialog.setStatusMessage(EditPluginPathDialog.EMPTY_STATUS);
|
||||
|
||||
File pluginFile = fileChooser.getSelectedFile();
|
||||
if (pluginFile != null) {
|
||||
setPath(pluginFile);
|
||||
}
|
||||
else {
|
||||
pathTextField.requestFocus();
|
||||
pathTextField.selectAll();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether something has changed.
|
||||
* @param changed true if something changed
|
||||
*/
|
||||
void setChanged(boolean changed) {
|
||||
this.changed = changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path field.
|
||||
* @param path filename for the path field
|
||||
* @return boolean true if the path is valid
|
||||
*/
|
||||
private boolean setPath(File path) {
|
||||
boolean pathOK = false;
|
||||
dialog.setStatusMessage(EditPluginPathDialog.EMPTY_STATUS);
|
||||
|
||||
if (!path.canRead()) {
|
||||
pathTextField.selectAll();
|
||||
dialog.setStatusMessage("Cannot read path: " + path.toString());
|
||||
}
|
||||
else {
|
||||
pathTextField.setText(path.getAbsolutePath());
|
||||
pathOK = (pathTextField.getText().trim().length() > 0);
|
||||
}
|
||||
|
||||
if (pathOK) {
|
||||
dialog.setStatusMessage("Press Apply or OK to set JAR directory.");
|
||||
}
|
||||
|
||||
changed = changed || pathOK;
|
||||
|
||||
dialog.enableApply();
|
||||
|
||||
return pathOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the text of the text field of the panel without
|
||||
* any error checking
|
||||
*/
|
||||
void setText(String text) {
|
||||
pathTextField.setText(text);
|
||||
}
|
||||
|
||||
}
|
|
@ -18,8 +18,6 @@
|
|||
package ghidra.framework.main;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -34,6 +32,7 @@ import javax.swing.event.ListSelectionListener;
|
|||
import docking.DialogComponentProvider;
|
||||
import docking.options.editor.ButtonPanelFactory;
|
||||
import docking.widgets.filechooser.GhidraFileChooser;
|
||||
import docking.widgets.filechooser.GhidraFileChooserMode;
|
||||
import docking.widgets.label.GDLabel;
|
||||
import docking.widgets.list.GListCellRenderer;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
|
@ -45,20 +44,18 @@ import ghidra.util.filechooser.GhidraFileFilter;
|
|||
|
||||
/**
|
||||
* Dialog for editing the Plugin path and Jar directory path preferences.
|
||||
*
|
||||
* <p>The Plugin Path and Jar directory path are locations where Ghidra searches
|
||||
* for plugins to load. The Plugin Path is specified exactly as a Java Classpath
|
||||
* is specified. The Jar directory is searched only for Jar files containing
|
||||
* Plugins. When changes are made to these fields in the dialog, the
|
||||
* is specified. When changes are made to these fields in the dialog, the
|
||||
* preferences file is updated and written to disk. The preferences file is
|
||||
* located in the .ghidra directory in the user's home directory.
|
||||
* </P>
|
||||
* <p> The preferences file also contains the last project that was opened,
|
||||
* and the positions of the Ghidra Project Window and other tools that were
|
||||
* running when the user last exited Ghidra.
|
||||
* </P>
|
||||
*
|
||||
*/
|
||||
class EditPluginPathDialog extends DialogComponentProvider {
|
||||
|
||||
static final String ADD_DIR_BUTTON_TEXT = "Add Dir ...";
|
||||
static final String ADD_JAR_BUTTON_TEXT = "Add Jar ...";
|
||||
private final static int SIDE_MARGIN = 5;
|
||||
private final static Color INVALID_PATH_COLOR = Color.red.brighter();
|
||||
private final static Color INVALID_SELECTED_PATH_COLOR = Color.pink;
|
||||
|
@ -80,7 +77,6 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
// gui members needed for dis/enabling and other state-dependent actions
|
||||
private JScrollPane scrollPane; // need for preferred size when resizing
|
||||
private JList<String> pluginPathsList;
|
||||
private BrowsePathPanel jarPathPanel;
|
||||
private GhidraFileChooser fileChooser;
|
||||
private JButton upButton;
|
||||
private JButton downButton;
|
||||
|
@ -94,7 +90,6 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
* Creates a non-modal dialog with OK, Apply, Cancel buttons.
|
||||
* The OK and Apply buttons will be enabled when user makes unapplied
|
||||
* changes to the UserPluginPath or UserPluginJarDirectory property values.
|
||||
* @param parent parent to this dialog
|
||||
*/
|
||||
EditPluginPathDialog() {
|
||||
super("Edit Plugin Path", true, false, true, false);
|
||||
|
@ -134,8 +129,6 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
// subsequent panels
|
||||
mainPanel.add(buildPluginPathsPanel());
|
||||
mainPanel.add(Box.createVerticalStrut(10));
|
||||
mainPanel.add(buildJarDirectoryPanel());
|
||||
mainPanel.add(Box.createVerticalStrut(10));
|
||||
mainPanel.add(Box.createVerticalGlue());
|
||||
mainPanel.add(statusMessagePanel);
|
||||
mainPanel.invalidate();
|
||||
|
@ -147,33 +140,15 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
return mainPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets called when the user selects Apply
|
||||
*/
|
||||
@Override
|
||||
protected void applyCallback() {
|
||||
// validate the jar path before applying changes, since the user
|
||||
// is pressing the Apply button to save this setting
|
||||
String jarPathname = jarPathPanel.getPath();
|
||||
if (jarPathname.length() > 0) {
|
||||
File jarPath = new File(jarPathname);
|
||||
if (!jarPath.isDirectory() || !jarPath.canRead()) {
|
||||
setStatusMessage("Bad Jar Directory: " + jarPathname);
|
||||
jarPathPanel.requestFocus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// do the things we need to do to handle the applied changes
|
||||
handleApply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets called when the user selects Cancel
|
||||
*/
|
||||
@Override
|
||||
protected void cancelCallback() {
|
||||
close();
|
||||
|
||||
// reset original state of dialog for next display of dialog
|
||||
enableButtons(false);
|
||||
setStatusMessage(EMPTY_STATUS);
|
||||
|
@ -181,17 +156,6 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
errorMsg = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* if the jar directory field has focus, don't let the base dialog
|
||||
* handle it.
|
||||
*/
|
||||
@Override
|
||||
protected void escapeCallback() {
|
||||
if (!jarPathPanel.hasFocus()) {
|
||||
super.escapeCallback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets called when the user selects Ok
|
||||
*/
|
||||
|
@ -206,30 +170,21 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* re-set the list of paths each time the dialog is shown
|
||||
* Reset the list of paths each time the dialog is shown
|
||||
* @param tool the tool
|
||||
*/
|
||||
public void show(PluginTool tool) {
|
||||
setPluginPathsListData(Preferences.getPluginPaths());
|
||||
initJarDirectory();
|
||||
setApplyEnabled(pluginPathsChanged);
|
||||
setStatusMessage(EMPTY_STATUS);
|
||||
|
||||
// setting the path enables the apply, but we know we haven't
|
||||
// made any changes yet, so disable
|
||||
setApplyEnabled(false);
|
||||
tool.showDialog(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method enableApply.
|
||||
*/
|
||||
void enableApply() {
|
||||
setApplyEnabled(pluginPathsChanged || jarPathPanel.isChanged());
|
||||
}
|
||||
|
||||
void initJarDirectory() {
|
||||
setApplyEnabled(pluginPathsChanged);
|
||||
setStatusMessage(EMPTY_STATUS);
|
||||
}
|
||||
|
||||
void setStatusMessage(String msg) {
|
||||
private void setStatusMessage(String msg) {
|
||||
if (msg == null || msg.length() == 0) {
|
||||
msg = EMPTY_STATUS;
|
||||
}
|
||||
|
@ -237,15 +192,7 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
statusMessage.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.util.bean.GhidraDialog#setApplyEnabled(boolean)
|
||||
*/
|
||||
@Override
|
||||
protected void setApplyEnabled(boolean state) {
|
||||
super.setApplyEnabled(state);
|
||||
}
|
||||
|
||||
void addJarCallback() {
|
||||
private void addJarCallback() {
|
||||
|
||||
setStatusMessage(EditPluginPathDialog.EMPTY_STATUS);
|
||||
|
||||
|
@ -253,7 +200,7 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
fileChooser = new GhidraFileChooser(getComponent());
|
||||
fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
|
||||
}
|
||||
fileChooser.setFileSelectionMode(GhidraFileChooser.FILES_ONLY);
|
||||
fileChooser.setFileSelectionMode(GhidraFileChooserMode.FILES_ONLY);
|
||||
fileChooser.setFileFilter(JAR_FILTER);
|
||||
fileChooser.setApproveButtonToolTipText("Choose Plugin Jar File");
|
||||
fileChooser.setApproveButtonText("Add Jar File");
|
||||
|
@ -277,7 +224,7 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
}
|
||||
}
|
||||
|
||||
void addDirCallback() {
|
||||
private void addDirCallback() {
|
||||
|
||||
setStatusMessage(EditPluginPathDialog.EMPTY_STATUS);
|
||||
|
||||
|
@ -285,7 +232,7 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
fileChooser = new GhidraFileChooser(getComponent());
|
||||
fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
|
||||
}
|
||||
fileChooser.setFileSelectionMode(GhidraFileChooser.DIRECTORIES_ONLY);
|
||||
fileChooser.setFileSelectionMode(GhidraFileChooserMode.DIRECTORIES_ONLY);
|
||||
fileChooser.setFileFilter(GhidraFileFilter.ALL);
|
||||
fileChooser.setApproveButtonToolTipText("Choose Directory with Plugin class Files");
|
||||
fileChooser.setApproveButtonText("Add Directory");
|
||||
|
@ -310,63 +257,31 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of pathnames where plugins can be found; used by custom
|
||||
* class loader when searching for plugins.
|
||||
*/
|
||||
private String[] getUserPluginPaths() {
|
||||
String[] pluginsArray = new String[listModel.size()];
|
||||
listModel.copyInto(pluginsArray);
|
||||
return pluginsArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* construct the plugin paths button panel
|
||||
*/
|
||||
private JPanel buildPluginPathsPanel() {
|
||||
// create the UP and DOWN arrows panel
|
||||
upButton = ButtonPanelFactory.createButton(ButtonPanelFactory.ARROW_UP_TYPE);
|
||||
upButton.setName("UpArrow");
|
||||
upButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
handleSelection(UP);
|
||||
}
|
||||
});
|
||||
upButton.addActionListener(e -> handleSelection(UP));
|
||||
downButton = ButtonPanelFactory.createButton(ButtonPanelFactory.ARROW_DOWN_TYPE);
|
||||
downButton.setName("DownArrow");
|
||||
downButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
handleSelection(DOWN);
|
||||
}
|
||||
});
|
||||
downButton.addActionListener(e -> handleSelection(DOWN));
|
||||
JPanel arrowButtonsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 10));
|
||||
arrowButtonsPanel.add(upButton);
|
||||
arrowButtonsPanel.add(downButton);
|
||||
|
||||
// create the Add and Remove panel
|
||||
JButton addJarButton = ButtonPanelFactory.createButton("Add Jar...");
|
||||
addJarButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
addJarCallback();
|
||||
}
|
||||
});
|
||||
JButton addDirButton = ButtonPanelFactory.createButton("Add Dir...");
|
||||
addDirButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
addDirCallback();
|
||||
}
|
||||
});
|
||||
JButton addJarButton = ButtonPanelFactory.createButton(ADD_JAR_BUTTON_TEXT);
|
||||
addJarButton.addActionListener(e -> addJarCallback());
|
||||
JButton addDirButton = ButtonPanelFactory.createButton(ADD_DIR_BUTTON_TEXT);
|
||||
addDirButton.addActionListener(e -> addDirCallback());
|
||||
removeButton = ButtonPanelFactory.createButton("Remove");
|
||||
removeButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
handleSelection(REMOVE);
|
||||
}
|
||||
});
|
||||
removeButton.addActionListener(e -> handleSelection(REMOVE));
|
||||
Dimension d = addJarButton.getPreferredSize();
|
||||
addDirButton.setPreferredSize(d);
|
||||
removeButton.setPreferredSize(d);
|
||||
|
@ -415,26 +330,6 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
return pluginPathListPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* construct the jar directory panel
|
||||
*/
|
||||
private JPanel buildJarDirectoryPanel() {
|
||||
|
||||
ActionListener listener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
jarPathPanel.showFileChooser();
|
||||
enableApply();
|
||||
}
|
||||
};
|
||||
|
||||
jarPathPanel = new BrowsePathPanel(this, listener, "UserPluginJarDirectory");
|
||||
jarPathPanel.setText(Preferences.getProperty(Preferences.USER_PLUGIN_JAR_DIRECTORY));
|
||||
jarPathPanel.setBorder(new TitledBorder("User Plugin Jar Directory"));
|
||||
|
||||
return jarPathPanel;
|
||||
}
|
||||
|
||||
private void enableButtons(boolean enabled) {
|
||||
upButton.setEnabled(enabled);
|
||||
downButton.setEnabled(enabled);
|
||||
|
@ -452,22 +347,12 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
// update Ghidra Preferences with new paths
|
||||
Preferences.setPluginPaths(userPluginPaths);
|
||||
|
||||
// Get user Jar directory
|
||||
String jarDirectoryName = jarPathPanel.getPath();
|
||||
if (jarDirectoryName.trim().length() == 0) {
|
||||
jarDirectoryName = null;
|
||||
}
|
||||
|
||||
// update Ghidra Preferences with new Jar path
|
||||
Preferences.setProperty(Preferences.USER_PLUGIN_JAR_DIRECTORY, jarDirectoryName);
|
||||
|
||||
errorMsg = null;
|
||||
// save the new values
|
||||
if (Preferences.store()) {
|
||||
setStatusMessage("Saved plugin paths successfully!");
|
||||
// indicate to user all changes have been applied
|
||||
setApplyEnabled(false);
|
||||
jarPathPanel.setChanged(false);
|
||||
|
||||
Msg.showInfo(getClass(), rootPanel, "Restart Ghidra",
|
||||
"You must restart Ghidra in order\n" + "for path changes to take effect.");
|
||||
|
@ -479,10 +364,6 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dispatched method for handling button actions on the
|
||||
* dialog
|
||||
*/
|
||||
private void handleSelection(byte whichAction) {
|
||||
// if nothing selected, nothing to do
|
||||
if (selectedInList == null) {
|
||||
|
@ -574,8 +455,8 @@ class EditPluginPathDialog extends DialogComponentProvider {
|
|||
|
||||
private void setPluginPathsListData(String[] pluginPathNames) {
|
||||
listModel.clear();
|
||||
for (int p = 0; p < pluginPathNames.length; p++) {
|
||||
listModel.addElement(pluginPathNames[p]);
|
||||
for (String pluginPathName : pluginPathNames) {
|
||||
listModel.addElement(pluginPathName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue