mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-09-18 01:31:53 +00:00
improve model/view split in bundle status, more nomenclature fixes
This commit is contained in:
parent
ad897f263c
commit
d8610b00be
|
@ -52,7 +52,7 @@ class GhidraScriptActionManager {
|
|||
private GhidraScriptComponentProvider provider;
|
||||
private GhidraScriptMgrPlugin plugin;
|
||||
private DockingAction refreshAction;
|
||||
private DockingAction scriptDirsAction;
|
||||
private DockingAction bundlePathsAction;
|
||||
private DockingAction newAction;
|
||||
private DockingAction runAction;
|
||||
private DockingAction runLastAction;
|
||||
|
@ -349,10 +349,10 @@ class GhidraScriptActionManager {
|
|||
refreshAction.setEnabled(true);
|
||||
plugin.getTool().addLocalAction(provider, refreshAction);
|
||||
|
||||
scriptDirsAction = new DockingAction("Bundle Status", plugin.getName()) {
|
||||
bundlePathsAction = new DockingAction("Bundle Status", plugin.getName()) {
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
provider.showBundleStatusDialog();
|
||||
provider.showBundleStatusComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -361,14 +361,14 @@ class GhidraScriptActionManager {
|
|||
return (contextObject instanceof GTable) || (contextObject instanceof ResourceFile);
|
||||
}
|
||||
};
|
||||
scriptDirsAction.setPopupMenuData(new MenuData(new String[] { "Bundle Status" },
|
||||
bundlePathsAction.setPopupMenuData(new MenuData(new String[] { "Bundle Status" },
|
||||
ResourceManager.loadImage("images/text_list_bullets.png"), null));
|
||||
scriptDirsAction.setToolBarData(
|
||||
bundlePathsAction.setToolBarData(
|
||||
new ToolBarData(ResourceManager.loadImage("images/text_list_bullets.png"), null));
|
||||
|
||||
scriptDirsAction.setDescription("Bundle Status");
|
||||
scriptDirsAction.setEnabled(true);
|
||||
plugin.getTool().addLocalAction(provider, scriptDirsAction);
|
||||
bundlePathsAction.setDescription("Bundle Status");
|
||||
bundlePathsAction.setEnabled(true);
|
||||
plugin.getTool().addLocalAction(provider, bundlePathsAction);
|
||||
|
||||
helpAction = new DockingAction("Ghidra API Help", plugin.getName()) {
|
||||
@Override
|
||||
|
@ -437,7 +437,7 @@ class GhidraScriptActionManager {
|
|||
}
|
||||
|
||||
HelpLocation getPathHelpLocation() {
|
||||
return new HelpLocation(plugin.getName(), scriptDirsAction.getName());
|
||||
return new HelpLocation(plugin.getName(), bundlePathsAction.getName());
|
||||
}
|
||||
|
||||
HelpLocation getKeyBindingHelpLocation() {
|
||||
|
|
|
@ -42,7 +42,6 @@ import generic.jar.ResourceFile;
|
|||
import generic.util.Path;
|
||||
import ghidra.app.plugin.core.script.osgi.*;
|
||||
import ghidra.app.script.*;
|
||||
import ghidra.app.script.osgi.BundleHost;
|
||||
import ghidra.app.services.ConsoleService;
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||
|
@ -131,12 +130,12 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
|||
return editorMap;
|
||||
}
|
||||
|
||||
void showBundleStatusDialog() {
|
||||
void showBundleStatusComponent() {
|
||||
bundleStatusProvider.setVisible(true);
|
||||
}
|
||||
|
||||
private void performRefresh() {
|
||||
GhidraScriptUtil.setScriptDirectories(bundleStatusProvider.getPaths());
|
||||
GhidraScriptUtil.setScriptBundlePaths(bundleStatusProvider.getModel().getPaths());
|
||||
GhidraScriptUtil.clearMetadata();
|
||||
refresh();
|
||||
}
|
||||
|
@ -341,12 +340,12 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
|||
}
|
||||
|
||||
public List<BundlePath> getScriptDirectories() {
|
||||
return bundleStatusProvider.getPaths().stream().filter(BundlePath::isDirectory).collect(
|
||||
Collectors.toList());
|
||||
return bundleStatusProvider.getModel().getPaths().stream().filter(
|
||||
BundlePath::isDirectory).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void enableScriptDirectory(ResourceFile scriptDir) {
|
||||
if (bundleStatusProvider.enablePath(scriptDir)) {
|
||||
if (bundleStatusProvider.getModel().enablePath(scriptDir)) {
|
||||
Msg.showInfo(this, getComponent(), "Script Path Added/Enabled",
|
||||
"The directory has been automatically enabled for use:\n" +
|
||||
scriptDir.getAbsolutePath());
|
||||
|
@ -397,7 +396,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
|||
}
|
||||
|
||||
void runScript(String scriptName, TaskListener listener) {
|
||||
List<BundlePath> dirPaths = bundleStatusProvider.getPaths();
|
||||
List<BundlePath> dirPaths = bundleStatusProvider.getModel().getPaths();
|
||||
for (Path dir : dirPaths) {
|
||||
ResourceFile scriptSource = new ResourceFile(dir.getPath(), scriptName);
|
||||
if (scriptSource.exists()) {
|
||||
|
@ -537,7 +536,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
|||
private void updateAvailableScriptFilesForAllPaths() {
|
||||
List<ResourceFile> scriptsToRemove = tableModel.getScripts();
|
||||
List<ResourceFile> scriptAccumulator = new ArrayList<>();
|
||||
List<BundlePath> bundlePaths = bundleStatusProvider.getPaths();
|
||||
List<BundlePath> bundlePaths = bundleStatusProvider.getModel().getPaths();
|
||||
for (BundlePath bundlePath : bundlePaths) {
|
||||
if (bundlePath.isDirectory()) {
|
||||
updateAvailableScriptFilesForDirectory(scriptsToRemove, scriptAccumulator,
|
||||
|
@ -733,11 +732,8 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
|||
}
|
||||
|
||||
private void build() {
|
||||
|
||||
bundleStatusProvider =
|
||||
new BundleStatusProvider(plugin.getTool(), plugin.getName(), BundleHost.getInstance());
|
||||
bundleStatusProvider.setFileChooserProperties("Select Script Bundle",
|
||||
"LastGhidraScriptBundle");
|
||||
|
||||
bundleStatusProvider = new BundleStatusProvider(plugin.getTool(), plugin.getName());
|
||||
|
||||
bundleStatusProvider.addListener(new BundlePathManagerListener() {
|
||||
@Override
|
||||
|
@ -745,6 +741,21 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
|||
plugin.getTool().setConfigChanged(true);
|
||||
performRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bundleEnablementChanged(BundlePath path, boolean enabled) {
|
||||
System.err.printf("XXXX %s is now %s\n", path.toString(),
|
||||
enabled ? "enabled" : "disabled");
|
||||
if (path.isDirectory()) {
|
||||
performRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bundleActivationChanged(BundlePath path, boolean newValue) {
|
||||
System.err.printf("XXXX %s is now %s\n", path.toString(),
|
||||
newValue ? "active" : "inactive");
|
||||
}
|
||||
});
|
||||
|
||||
scriptRoot = new RootNode();
|
||||
|
@ -1015,8 +1026,8 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
|||
bundleStatusProvider.restoreState(saveState);
|
||||
|
||||
// pull in the just-loaded paths
|
||||
List<BundlePath> paths = bundleStatusProvider.getPaths();
|
||||
GhidraScriptUtil.setScriptDirectories(paths);
|
||||
List<BundlePath> paths = bundleStatusProvider.getModel().getPaths();
|
||||
GhidraScriptUtil.setScriptBundlePaths(paths);
|
||||
actionManager.restoreUserDefinedKeybindings(saveState);
|
||||
actionManager.restoreScriptsThatAreInTool(saveState);
|
||||
|
||||
|
|
|
@ -18,22 +18,12 @@ package ghidra.app.plugin.core.script.osgi;
|
|||
|
||||
public interface BundlePathManagerListener {
|
||||
|
||||
default public void pathMessage(String message) {
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the list of bundle paths changes
|
||||
*/
|
||||
default public void bundlesChanged() {
|
||||
//
|
||||
}
|
||||
public void bundlesChanged();
|
||||
|
||||
/**
|
||||
* called when a bundle path changes
|
||||
* @param path that whose attributes changed
|
||||
*/
|
||||
default public void bundlePathChanged(BundlePath path) {
|
||||
//
|
||||
}
|
||||
public void bundleEnablementChanged(BundlePath path, boolean newValue);
|
||||
public void bundleActivationChanged(BundlePath path, boolean newValue);
|
||||
|
||||
}
|
||||
|
|
|
@ -16,67 +16,29 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.script.osgi;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import docking.widgets.table.AbstractSortedTableModel;
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.app.script.GhidraScriptUtil;
|
||||
import ghidra.framework.preferences.Preferences;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
||||
private static int column_counter = 0;
|
||||
|
||||
static enum COLUMN {
|
||||
Enabled(Boolean.class) {
|
||||
@Override
|
||||
Object getValue(BundlePath path) {
|
||||
return path.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValue(BundlePath path, Object aValue) {
|
||||
path.setEnabled((Boolean) aValue);
|
||||
}
|
||||
},
|
||||
Active(Boolean.class) {
|
||||
@Override
|
||||
Object getValue(BundlePath path) {
|
||||
return path.isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValue(BundlePath path, Object aValue) {
|
||||
path.setActive((Boolean) aValue);
|
||||
}
|
||||
},
|
||||
Type(String.class) {
|
||||
@Override
|
||||
boolean editable(BundlePath path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
Object getValue(BundlePath path) {
|
||||
return path.getType().toString();
|
||||
}
|
||||
|
||||
},
|
||||
Path(BundlePath.class) {
|
||||
@Override
|
||||
boolean editable(BundlePath path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValue(BundlePath path, Object aValue) {
|
||||
if (path.isEditable()) {
|
||||
BundlePath newpath = (BundlePath) aValue;
|
||||
path.setPath(newpath.getPath());
|
||||
}
|
||||
}
|
||||
},
|
||||
__badcolumnindex__(Object.class);
|
||||
public class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
||||
List<Column> columns = new ArrayList<>();
|
||||
|
||||
class Column {
|
||||
final Class<?> clazz;
|
||||
final int index;
|
||||
final String name;
|
||||
|
||||
Column(String name, Class<?> clazz) {
|
||||
this.name = name;
|
||||
this.index = columns.size();
|
||||
columns.add(this);
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
boolean editable(BundlePath path) {
|
||||
return true;
|
||||
|
@ -86,26 +48,73 @@ class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
|||
return path;
|
||||
}
|
||||
|
||||
COLUMN(Class<?> clazz) {
|
||||
this.index = column_counter++;
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
static COLUMN[] vals = values();
|
||||
static {
|
||||
vals = Arrays.copyOf(vals, vals.length - 1);
|
||||
}
|
||||
|
||||
static COLUMN val(int i) {
|
||||
if (i >= 0 && i < vals.length) {
|
||||
return vals[i];
|
||||
}
|
||||
return __badcolumnindex__;
|
||||
}
|
||||
|
||||
void setValue(BundlePath path, Object aValue) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Column enabledColumn = new Column("Enabled", Boolean.class) {
|
||||
@Override
|
||||
Object getValue(BundlePath path) {
|
||||
return path.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValue(BundlePath path, Object newValue) {
|
||||
path.setEnabled((Boolean) newValue);
|
||||
provider.fireBundleEnablementChanged(path, (Boolean) newValue);
|
||||
}
|
||||
};
|
||||
Column activeColumn = new Column("Active", Boolean.class) {
|
||||
@Override
|
||||
Object getValue(BundlePath path) {
|
||||
return path.isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValue(BundlePath path, Object newValue) {
|
||||
path.setActive((Boolean) newValue);
|
||||
provider.fireBundleActivationChanged(path, (Boolean) newValue);
|
||||
}
|
||||
};
|
||||
Column typeColumn = new Column("Type", String.class) {
|
||||
@Override
|
||||
boolean editable(BundlePath path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
Object getValue(BundlePath path) {
|
||||
return path.getType().toString();
|
||||
}
|
||||
};
|
||||
|
||||
Column pathColumn = new Column("Path", BundlePath.class) {
|
||||
@Override
|
||||
boolean editable(BundlePath path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValue(BundlePath path, Object aValue) {
|
||||
if (path.isEditable()) {
|
||||
BundlePath newpath = (BundlePath) aValue;
|
||||
path.setPath(newpath.getPath());
|
||||
}
|
||||
}
|
||||
};
|
||||
Column badColumn = new Column("INVALID", Object.class);
|
||||
{
|
||||
columns.remove(columns.size() - 1); // pop badColumn
|
||||
|
||||
}
|
||||
|
||||
Column getColumn(int i) {
|
||||
if (i >= 0 && i < columns.size()) {
|
||||
return columns.get(i);
|
||||
}
|
||||
return badColumn;
|
||||
}
|
||||
|
||||
private BundleStatusProvider provider;
|
||||
|
@ -115,6 +124,7 @@ class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
|||
super();
|
||||
this.provider = provider;
|
||||
this.paths.addAll(dedupPaths(GhidraScriptUtil.getDefaultScriptBundles()));
|
||||
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
|
@ -136,7 +146,7 @@ class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
|||
return new ArrayList<BundlePath>(paths);
|
||||
}
|
||||
|
||||
List<BundlePath> getPaths() {
|
||||
public List<BundlePath> getPaths() {
|
||||
List<BundlePath> list = new ArrayList<>();
|
||||
for (BundlePath path : paths) {
|
||||
if (path.isEnabled()) {
|
||||
|
@ -146,20 +156,11 @@ class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
|||
return list;
|
||||
}
|
||||
|
||||
void setPaths(List<BundlePath> paths) {
|
||||
public void setPaths(List<BundlePath> paths) {
|
||||
this.paths = new ArrayList<>(paths);
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
void setPaths(BundlePath[] pathsArr) {
|
||||
paths.clear();
|
||||
paths = new ArrayList<>();
|
||||
for (BundlePath element : pathsArr) {
|
||||
paths.add(element);
|
||||
}
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
void addPath(BundlePath path) {
|
||||
if (paths.contains(path)) {
|
||||
return;
|
||||
|
@ -169,20 +170,6 @@ class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
|||
fireTableRowsInserted(index, index);
|
||||
}
|
||||
|
||||
void removePath(BundlePath path) {
|
||||
int index = paths.indexOf(path);
|
||||
if (path.isEditable()) {
|
||||
paths.remove(path);
|
||||
}
|
||||
else {
|
||||
List<BundlePathManagerListener> listeners = provider.getListeners();
|
||||
for (BundlePathManagerListener listener : listeners) {
|
||||
listener.pathMessage("Unable to remove path.");
|
||||
}
|
||||
}
|
||||
fireTableRowsDeleted(index, index);
|
||||
}
|
||||
|
||||
void remove(int[] selectedRows) {
|
||||
List<BundlePath> list = new ArrayList<>();
|
||||
for (int selectedRow : selectedRows) {
|
||||
|
@ -193,56 +180,18 @@ class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
|||
paths.remove(path);
|
||||
}
|
||||
else {
|
||||
List<BundlePathManagerListener> listeners = provider.getListeners();
|
||||
for (BundlePathManagerListener listener : listeners) {
|
||||
listener.pathMessage("Unable to remove path.");
|
||||
}
|
||||
Msg.showInfo(this, this.provider.getComponent(), "Unabled to remove path",
|
||||
"System path cannot be removed: " + path.toString());
|
||||
}
|
||||
}
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
int moveUp(int index) {
|
||||
if (index < 0 || index >= paths.size()) {
|
||||
return -1;
|
||||
}
|
||||
BundlePath path = paths.remove(index);
|
||||
if (index == 0) {
|
||||
paths.add(path);//place it last in the list
|
||||
}
|
||||
else {
|
||||
paths.add(index - 1, path);
|
||||
}
|
||||
fireTableDataChanged();
|
||||
return paths.indexOf(path);
|
||||
}
|
||||
|
||||
int moveDown(int index) {
|
||||
if (index < 0 || index >= paths.size()) {
|
||||
return -1;
|
||||
}
|
||||
int size = paths.size();
|
||||
BundlePath path = paths.remove(index);
|
||||
if (index == size - 1) {
|
||||
paths.add(0, path);//move to the top of the list
|
||||
}
|
||||
else {
|
||||
paths.add(index + 1, path);
|
||||
}
|
||||
fireTableDataChanged();
|
||||
return paths.indexOf(path);
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
|
||||
@Override
|
||||
public java.lang.Class<?> getColumnClass(int columnIndex) {
|
||||
return COLUMN.val(columnIndex).clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return COLUMN.vals.length;
|
||||
return columns.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -250,23 +199,31 @@ class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
|||
return paths.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.lang.Class<?> getColumnClass(int columnIndex) {
|
||||
return getColumn(columnIndex).clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||
BundlePath path = paths.get(rowIndex);
|
||||
return COLUMN.val(columnIndex).editable(path);
|
||||
return getColumn(columnIndex).editable(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int columnIndex) {
|
||||
return COLUMN.val(columnIndex).toString();
|
||||
return getColumn(columnIndex).name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||
BundlePath path = paths.get(rowIndex);
|
||||
COLUMN.val(columnIndex).setValue(path, aValue);
|
||||
fireTableDataChanged();
|
||||
provider.fireBundlePathChanged(path);
|
||||
getColumn(columnIndex).setValue(path, aValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getColumnValueForRow(BundlePath path, int columnIndex) {
|
||||
return getColumn(columnIndex).getValue(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -284,8 +241,29 @@ class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
|||
return paths;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getColumnValueForRow(BundlePath path, int columnIndex) {
|
||||
return COLUMN.val(columnIndex).getValue(path);
|
||||
/**
|
||||
* (add and) enable a path
|
||||
* @param file path to enable
|
||||
* @return true if the path is new
|
||||
*/
|
||||
public boolean enablePath(ResourceFile file) {
|
||||
ResourceFile dir = file.isDirectory() ? file : file.getParentFile();
|
||||
for (BundlePath path : getAllPaths()) {
|
||||
if (path.getPath().equals(dir)) {
|
||||
if (!path.isEnabled()) {
|
||||
path.setEnabled(true);
|
||||
fireTableDataChanged();
|
||||
provider.fireBundlesChanged();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
BundlePath p = new BundlePath(dir);
|
||||
p.setEnabled(true);
|
||||
addPath(p);
|
||||
Preferences.setProperty(BundleStatusProvider.preferenceForLastSelectedBundle, dir.getAbsolutePath());
|
||||
provider.fireBundlesChanged();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,14 +22,11 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.TableModelListener;
|
||||
import javax.swing.table.TableColumn;
|
||||
|
||||
import docking.widgets.filechooser.GhidraFileChooser;
|
||||
import docking.widgets.filechooser.GhidraFileChooserMode;
|
||||
import docking.widgets.table.*;
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.app.script.osgi.BundleHost;
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
|
@ -42,38 +39,40 @@ import resources.ResourceManager;
|
|||
* component for managing OSGi bundle status
|
||||
*/
|
||||
public class BundleStatusProvider extends ComponentProviderAdapter {
|
||||
static String preferenceForLastSelectedBundle = "LastGhidraScriptBundle";
|
||||
|
||||
private JPanel panel;
|
||||
private GTable bundlePathTable;
|
||||
private BundleStatusModel bundleStatusModel;
|
||||
private TableModelListener bundlePathModelListener;
|
||||
private final BundleStatusModel bundleStatusModel;
|
||||
private JButton addButton;
|
||||
private JButton removeButton;
|
||||
private Color selectionColor;
|
||||
private GhidraFileChooser fileChooser;
|
||||
private String preferenceForLastSelectedBundle = Preferences.LAST_IMPORT_DIRECTORY;
|
||||
private String title = "Select File";
|
||||
private GhidraFileFilter filter;
|
||||
private ArrayList<BundlePathManagerListener> listeners = new ArrayList<>();
|
||||
|
||||
private BundleHost bundleHost;
|
||||
|
||||
public BundleStatusProvider(PluginTool tool, String owner, BundleHost bundleHost) {
|
||||
super(tool, "Bundle Status Manager", "my owner");
|
||||
this.bundleHost = bundleHost;
|
||||
build();
|
||||
addToTool();
|
||||
void fireBundlesChanged() {
|
||||
for (BundlePathManagerListener listener : listeners) {
|
||||
listener.bundlesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set properties on the file chooser that is displayed when the "Add" button is pressed.
|
||||
* @param title title of the file chooser
|
||||
* @param preferenceForLastSelectedBundle Preference to use as the starting selection in the
|
||||
* file chooser
|
||||
*/
|
||||
void fireBundleEnablementChanged(BundlePath path, boolean newValue) {
|
||||
for (BundlePathManagerListener listener : listeners) {
|
||||
listener.bundleEnablementChanged(path, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
void fireBundleActivationChanged(BundlePath path, boolean newValue) {
|
||||
for (BundlePathManagerListener listener : listeners) {
|
||||
listener.bundleActivationChanged(path, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
public BundleStatusProvider(PluginTool tool, String owner) {
|
||||
super(tool, "Bundle Status Manager", owner);
|
||||
this.bundleStatusModel = new BundleStatusModel(this);
|
||||
|
||||
public void setFileChooserProperties(String title, String preferenceForLastSelectedBundle) {
|
||||
this.title = title;
|
||||
this.preferenceForLastSelectedBundle = preferenceForLastSelectedBundle;
|
||||
this.filter = new GhidraFileFilter() {
|
||||
@Override
|
||||
public String getDescription() {
|
||||
|
@ -86,51 +85,13 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
|||
}
|
||||
};
|
||||
this.fileChooser = null;
|
||||
|
||||
build();
|
||||
addToTool();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return enabled paths in the table.
|
||||
* @return enabled paths
|
||||
*/
|
||||
public List<BundlePath> getPaths() {
|
||||
return bundleStatusModel.getPaths();
|
||||
}
|
||||
|
||||
/**
|
||||
* (add and) enable a path
|
||||
* @param file path to enable
|
||||
* @return true if the path is new
|
||||
*/
|
||||
public boolean enablePath(ResourceFile file) {
|
||||
ResourceFile dir = file.isDirectory() ? file : file.getParentFile();
|
||||
for (BundlePath path : bundleStatusModel.getAllPaths()) {
|
||||
if (path.getPath().equals(dir)) {
|
||||
if (!path.isEnabled()) {
|
||||
path.setEnabled(true);
|
||||
bundleStatusModel.fireTableDataChanged();
|
||||
fireBundlesChanged();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
BundlePath p = new BundlePath(dir);
|
||||
p.setEnabled(true);
|
||||
bundleStatusModel.addPath(p);
|
||||
Preferences.setProperty(preferenceForLastSelectedBundle, dir.getAbsolutePath());
|
||||
fireBundlesChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setPaths(List<BundlePath> paths) {
|
||||
bundleStatusModel.setPaths(paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the paths in the table.
|
||||
*/
|
||||
public void clear() {
|
||||
bundleStatusModel.clear();
|
||||
public BundleStatusModel getModel() {
|
||||
return bundleStatusModel;
|
||||
}
|
||||
|
||||
public void addListener(BundlePathManagerListener listener) {
|
||||
|
@ -143,27 +104,11 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
|||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
public List<BundlePathManagerListener> getListeners() {
|
||||
return new ArrayList<>(listeners);
|
||||
}
|
||||
|
||||
void fireBundlesChanged() {
|
||||
for (BundlePathManagerListener listener : listeners) {
|
||||
listener.bundlesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void fireBundlePathChanged(BundlePath path) {
|
||||
for (BundlePathManagerListener listener : listeners) {
|
||||
listener.bundlePathChanged(path);
|
||||
}
|
||||
}
|
||||
|
||||
private void build() {
|
||||
panel = new JPanel(new BorderLayout(5, 5));
|
||||
|
||||
selectionColor = new Color(204, 204, 255);
|
||||
|
||||
|
||||
addButton = new JButton(ResourceManager.loadImage("images/Plus.png"));
|
||||
addButton.setName("AddBundle");
|
||||
addButton.setToolTipText("Display file chooser to add bundles to list");
|
||||
|
@ -187,13 +132,6 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
|||
++gbc.gridy;
|
||||
buttonPanel.add(removeButton, gbc);
|
||||
|
||||
bundlePathModelListener = e -> {
|
||||
fireBundlesChanged();
|
||||
};
|
||||
|
||||
bundleStatusModel = new BundleStatusModel(this);
|
||||
bundleStatusModel.addTableModelListener(bundlePathModelListener);
|
||||
|
||||
bundlePathTable = new GTable(bundleStatusModel);
|
||||
bundlePathTable.setName("BUNDLEPATH_TABLE");
|
||||
bundlePathTable.setSelectionBackground(selectionColor);
|
||||
|
@ -203,25 +141,25 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
|||
int skinnyWidth = 50;
|
||||
|
||||
TableColumn column =
|
||||
bundlePathTable.getColumnModel().getColumn(BundleStatusModel.COLUMN.Enabled.index);
|
||||
bundlePathTable.getColumnModel().getColumn(bundleStatusModel.enabledColumn.index);
|
||||
column.setPreferredWidth(skinnyWidth);
|
||||
column.setMinWidth(skinnyWidth);
|
||||
column.setMaxWidth(skinnyWidth);
|
||||
column.setWidth(skinnyWidth);
|
||||
|
||||
column = bundlePathTable.getColumnModel().getColumn(BundleStatusModel.COLUMN.Active.index);
|
||||
column = bundlePathTable.getColumnModel().getColumn(bundleStatusModel.activeColumn.index);
|
||||
column.setPreferredWidth(skinnyWidth);
|
||||
column.setMinWidth(skinnyWidth);
|
||||
column.setMaxWidth(skinnyWidth);
|
||||
column.setWidth(skinnyWidth);
|
||||
|
||||
column = bundlePathTable.getColumnModel().getColumn(BundleStatusModel.COLUMN.Type.index);
|
||||
column = bundlePathTable.getColumnModel().getColumn(bundleStatusModel.typeColumn.index);
|
||||
|
||||
FontMetrics fontmetrics = panel.getFontMetrics(panel.getFont());
|
||||
column.setMaxWidth(10 +
|
||||
SwingUtilities.computeStringWidth(fontmetrics, BundlePath.Type.SourceDir.toString()));
|
||||
|
||||
column = bundlePathTable.getColumnModel().getColumn(BundleStatusModel.COLUMN.Path.index);
|
||||
column = bundlePathTable.getColumnModel().getColumn(bundleStatusModel.pathColumn.index);
|
||||
column.setCellRenderer(new GTableCellRenderer() {
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
|
||||
|
@ -265,7 +203,7 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
|||
|
||||
private void remove() {
|
||||
int[] selectedRows = bundlePathTable.getSelectedRows();
|
||||
if (selectedRows == null) {
|
||||
if (selectedRows == null || selectedRows.length == 0) {
|
||||
return;
|
||||
}
|
||||
bundleStatusModel.remove(selectedRows);
|
||||
|
@ -281,6 +219,7 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
|||
bundlePathTable.setRowSelectionInterval(row, row);
|
||||
}
|
||||
updateButtonsEnabled();
|
||||
fireBundlesChanged();
|
||||
}
|
||||
|
||||
private void add() {
|
||||
|
@ -288,7 +227,7 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
|||
fileChooser = new GhidraFileChooser(panel);
|
||||
fileChooser.setMultiSelectionEnabled(true);
|
||||
fileChooser.setFileSelectionMode(GhidraFileChooserMode.FILES_AND_DIRECTORIES);
|
||||
fileChooser.setTitle(title);
|
||||
fileChooser.setTitle("Select Script Bundle(s)");
|
||||
// fileChooser.setApproveButtonToolTipText(title);
|
||||
if (filter != null) {
|
||||
fileChooser.addFileFilter(new GhidraFileFilter() {
|
||||
|
@ -326,13 +265,10 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
|||
BundlePath p = new BundlePath(element);
|
||||
bundleStatusModel.addPath(p);
|
||||
}
|
||||
fireBundlesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GUI component for the path manager.
|
||||
* @return the GUI component for the path manager
|
||||
*/
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return panel;
|
||||
|
@ -376,12 +312,6 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Temporarily remove the listener to prevent too many
|
||||
* notifications from being sent.
|
||||
*/
|
||||
bundleStatusModel.removeTableModelListener(bundlePathModelListener);
|
||||
|
||||
boolean[] enableArr =
|
||||
ss.getBooleans("BundleManagerPanel_ENABLE", new boolean[pathArr.length]);
|
||||
boolean[] editArr = ss.getBooleans("BundleManagerPanel_EDIT", new boolean[pathArr.length]);
|
||||
|
@ -415,10 +345,6 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reinstall the listener then fire the update.
|
||||
*/
|
||||
bundleStatusModel.addTableModelListener(bundlePathModelListener);
|
||||
fireBundlesChanged();
|
||||
}
|
||||
|
||||
|
@ -434,4 +360,8 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
|||
public void dispose() {
|
||||
bundlePathTable.dispose();
|
||||
}
|
||||
|
||||
void selectRow(int rowIndex) {
|
||||
bundlePathTable.selectRow(rowIndex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,10 +154,10 @@ public class GhidraScriptUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the script directories to the new paths.
|
||||
* @param newPaths the new script directories
|
||||
* Sets the script bundle paths
|
||||
* @param newPaths the new script bundle paths
|
||||
*/
|
||||
public static void setScriptDirectories(List<BundlePath> newPaths) {
|
||||
public static void setScriptBundlePaths(List<BundlePath> newPaths) {
|
||||
scriptBundlePaths = new ArrayList<>(newPaths);
|
||||
}
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ public class GhidraScriptRunner implements GhidraLaunchable {
|
|||
}
|
||||
}
|
||||
}
|
||||
GhidraScriptUtil.setScriptDirectories(paths);
|
||||
GhidraScriptUtil.setScriptBundlePaths(paths);
|
||||
|
||||
StringBuffer buf = new StringBuffer("HEADLESS Script Paths:");
|
||||
for (ResourceFile dir : GhidraScriptUtil.getScriptSourceDirectories()) {
|
||||
|
|
|
@ -676,7 +676,7 @@ public class HeadlessAnalyzer {
|
|||
}
|
||||
}
|
||||
}
|
||||
GhidraScriptUtil.setScriptDirectories(paths);
|
||||
GhidraScriptUtil.setScriptBundlePaths(paths);
|
||||
|
||||
StringBuffer buf = new StringBuffer("HEADLESS Script Paths:");
|
||||
for (ResourceFile dir : GhidraScriptUtil.getScriptSourceDirectories()) {
|
||||
|
|
|
@ -980,7 +980,7 @@ public abstract class AbstractGhidraScriptMgrPluginTest
|
|||
// destroy any NewScriptxxx files...and Temp ones too
|
||||
BundleStatusProvider bundleStatusProvider =
|
||||
(BundleStatusProvider) TestUtils.getInstanceField("bundlePathManager", provider);
|
||||
List<BundlePath> paths = bundleStatusProvider.getPaths();
|
||||
List<BundlePath> paths = bundleStatusProvider.getModel().getPaths();
|
||||
for (BundlePath path : paths) {
|
||||
File file = path.getPath().getFile(false);
|
||||
File[] listFiles = file.listFiles();
|
||||
|
|
|
@ -290,9 +290,9 @@ public class GhidraScriptMgrPlugin3Test extends AbstractGhidraScriptMgrPluginTes
|
|||
dir.mkdirs();
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
List<BundlePath> paths = bundleStatusProvider.getPaths();
|
||||
List<BundlePath> paths = bundleStatusProvider.getModel().getPaths();
|
||||
paths.add(0, new BundlePath(dir));
|
||||
bundleStatusProvider.setPaths(paths);
|
||||
bundleStatusProvider.getModel().setPaths(paths);
|
||||
});
|
||||
waitForSwing();
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ public class GhidraScriptMgrPluginScreenShots extends GhidraScreenShotGenerator
|
|||
paths.add(new BundlePath("/User/defined/invalid/directory"));
|
||||
|
||||
BundleStatusProvider bundleStatusProvider = showProvider(BundleStatusProvider.class);
|
||||
bundleStatusProvider.setPaths(paths);
|
||||
bundleStatusProvider.getModel().setPaths(paths);
|
||||
|
||||
waitForComponentProvider(BundleStatusProvider.class);
|
||||
captureComponent(bundleStatusProvider.getComponent());
|
||||
|
|
Loading…
Reference in a new issue