mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
start connecting OSGi to bundlestatusmanager
- minimize access to BundleHost instance (JavaScriptProvider is still bad) - BundlePath - restrict construction to osgi package - remove "editable" attribute and fix incorrect reference - remove references in GhidraScriptUtil - BundlePath attribute choice came down only to system or user - user filtering on "enabled" were redundant - move compilation from JavaScriptProvider to BundheHost
This commit is contained in:
parent
36f4a219d9
commit
f39d55cca1
14 changed files with 352 additions and 282 deletions
|
@ -39,9 +39,9 @@ import docking.widgets.tree.GTree;
|
||||||
import docking.widgets.tree.GTreeNode;
|
import docking.widgets.tree.GTreeNode;
|
||||||
import docking.widgets.tree.support.BreadthFirstIterator;
|
import docking.widgets.tree.support.BreadthFirstIterator;
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import generic.util.Path;
|
|
||||||
import ghidra.app.plugin.core.script.osgi.*;
|
import ghidra.app.plugin.core.script.osgi.*;
|
||||||
import ghidra.app.script.*;
|
import ghidra.app.script.*;
|
||||||
|
import ghidra.app.script.osgi.BundleHost;
|
||||||
import ghidra.app.services.ConsoleService;
|
import ghidra.app.services.ConsoleService;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||||
|
@ -97,9 +97,10 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
GhidraScriptComponentProvider(GhidraScriptMgrPlugin plugin) {
|
GhidraScriptComponentProvider(GhidraScriptMgrPlugin plugin, BundleHost bundleHost) {
|
||||||
super(plugin.getTool(), "Script Manager", plugin.getName());
|
super(plugin.getTool(), "Script Manager", plugin.getName());
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
this.bundleHost=bundleHost;
|
||||||
|
|
||||||
setHelpLocation(new HelpLocation(plugin.getName(), plugin.getName()));
|
setHelpLocation(new HelpLocation(plugin.getName(), plugin.getName()));
|
||||||
setIcon(ResourceManager.loadImage("images/play.png"));
|
setIcon(ResourceManager.loadImage("images/play.png"));
|
||||||
|
@ -161,8 +162,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
||||||
void renameScript() {
|
void renameScript() {
|
||||||
ResourceFile script = getSelectedScript();
|
ResourceFile script = getSelectedScript();
|
||||||
ResourceFile directory = script.getParentFile();
|
ResourceFile directory = script.getParentFile();
|
||||||
Path path = GhidraScriptUtil.getScriptPath(directory);
|
if (!bundleStatusProvider.getModel().isWriteable(directory)) {
|
||||||
if (path == null || path.isReadOnly()) {
|
|
||||||
Msg.showWarn(getClass(), getComponent(), getName(),
|
Msg.showWarn(getClass(), getComponent(), getName(),
|
||||||
"Unable to rename scripts in '" + directory + "'.");
|
"Unable to rename scripts in '" + directory + "'.");
|
||||||
return;
|
return;
|
||||||
|
@ -297,8 +297,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
ResourceFile directory = script.getParentFile();
|
ResourceFile directory = script.getParentFile();
|
||||||
|
|
||||||
Path path = GhidraScriptUtil.getScriptPath(directory);
|
if (!bundleStatusProvider.getModel().isWriteable(directory)) {
|
||||||
if (path == null || path.isReadOnly()) {
|
|
||||||
Msg.showWarn(getClass(), getComponent(), getName(),
|
Msg.showWarn(getClass(), getComponent(), getName(),
|
||||||
"Unable to delete scripts in '" + directory + "'.");
|
"Unable to delete scripts in '" + directory + "'.");
|
||||||
return;
|
return;
|
||||||
|
@ -339,9 +338,9 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BundlePath> getScriptDirectories() {
|
public List<ResourceFile> getScriptDirectories() {
|
||||||
return bundleStatusProvider.getModel().getPaths().stream().filter(
|
return bundleStatusProvider.getModel().getPaths().stream().filter(
|
||||||
BundlePath::isDirectory).collect(Collectors.toList());
|
ResourceFile::isDirectory).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableScriptDirectory(ResourceFile scriptDir) {
|
public void enableScriptDirectory(ResourceFile scriptDir) {
|
||||||
|
@ -396,9 +395,9 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
void runScript(String scriptName, TaskListener listener) {
|
void runScript(String scriptName, TaskListener listener) {
|
||||||
List<BundlePath> dirPaths = bundleStatusProvider.getModel().getPaths();
|
List<ResourceFile> dirPaths = bundleStatusProvider.getModel().getPaths();
|
||||||
for (Path dir : dirPaths) {
|
for (ResourceFile dir : dirPaths) {
|
||||||
ResourceFile scriptSource = new ResourceFile(dir.getPath(), scriptName);
|
ResourceFile scriptSource = new ResourceFile(dir, scriptName);
|
||||||
if (scriptSource.exists()) {
|
if (scriptSource.exists()) {
|
||||||
runScript(scriptSource, listener);
|
runScript(scriptSource, listener);
|
||||||
return;
|
return;
|
||||||
|
@ -536,11 +535,11 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
||||||
private void updateAvailableScriptFilesForAllPaths() {
|
private void updateAvailableScriptFilesForAllPaths() {
|
||||||
List<ResourceFile> scriptsToRemove = tableModel.getScripts();
|
List<ResourceFile> scriptsToRemove = tableModel.getScripts();
|
||||||
List<ResourceFile> scriptAccumulator = new ArrayList<>();
|
List<ResourceFile> scriptAccumulator = new ArrayList<>();
|
||||||
List<BundlePath> bundlePaths = bundleStatusProvider.getModel().getPaths();
|
List<ResourceFile> bundlePaths = bundleStatusProvider.getModel().getPaths();
|
||||||
for (BundlePath bundlePath : bundlePaths) {
|
for (ResourceFile bundlePath : bundlePaths) {
|
||||||
if (bundlePath.isDirectory()) {
|
if (bundlePath.isDirectory()) {
|
||||||
updateAvailableScriptFilesForDirectory(scriptsToRemove, scriptAccumulator,
|
updateAvailableScriptFilesForDirectory(scriptsToRemove, scriptAccumulator,
|
||||||
bundlePath.getPath());
|
bundlePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,8 +730,33 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void build() {
|
final private BundleHost bundleHost;
|
||||||
|
|
||||||
|
void startActivateDeactiveTask(BundlePath path, boolean activate) {
|
||||||
|
path.setBusy(true);
|
||||||
|
bundleStatusProvider.notifyTableChanged();
|
||||||
|
|
||||||
|
new TaskLauncher(new Task((activate ? "Activating" : "Deactivating ") + " bundle...") {
|
||||||
|
@Override
|
||||||
|
public void run(TaskMonitor monitor) throws CancelledException {
|
||||||
|
try {
|
||||||
|
bundleHost.setActive(path, activate);
|
||||||
|
path.setActive(activate);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Msg.showError(this, GhidraScriptComponentProvider.this.getComponent(),
|
||||||
|
"activation failed", e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
path.setBusy(false);
|
||||||
|
bundleStatusProvider.notifyTableChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, null, 1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void build() {
|
||||||
bundleStatusProvider = new BundleStatusProvider(plugin.getTool(), plugin.getName());
|
bundleStatusProvider = new BundleStatusProvider(plugin.getTool(), plugin.getName());
|
||||||
|
|
||||||
bundleStatusProvider.addListener(new BundlePathManagerListener() {
|
bundleStatusProvider.addListener(new BundlePathManagerListener() {
|
||||||
|
@ -744,8 +768,10 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bundleEnablementChanged(BundlePath path, boolean enabled) {
|
public void bundleEnablementChanged(BundlePath path, boolean enabled) {
|
||||||
System.err.printf("XXXX %s is now %s\n", path.toString(),
|
if (path.isActive()) {
|
||||||
enabled ? "enabled" : "disabled");
|
startActivateDeactiveTask(path, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (path.isDirectory()) {
|
if (path.isDirectory()) {
|
||||||
performRefresh();
|
performRefresh();
|
||||||
}
|
}
|
||||||
|
@ -753,8 +779,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bundleActivationChanged(BundlePath path, boolean newValue) {
|
public void bundleActivationChanged(BundlePath path, boolean newValue) {
|
||||||
System.err.printf("XXXX %s is now %s\n", path.toString(),
|
startActivateDeactiveTask(path, newValue);
|
||||||
newValue ? "active" : "inactive");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1026,7 +1051,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
||||||
bundleStatusProvider.restoreState(saveState);
|
bundleStatusProvider.restoreState(saveState);
|
||||||
|
|
||||||
// pull in the just-loaded paths
|
// pull in the just-loaded paths
|
||||||
List<BundlePath> paths = bundleStatusProvider.getModel().getPaths();
|
List<ResourceFile> paths = bundleStatusProvider.getModel().getPaths();
|
||||||
GhidraScriptUtil.setScriptBundlePaths(paths);
|
GhidraScriptUtil.setScriptBundlePaths(paths);
|
||||||
actionManager.restoreUserDefinedKeybindings(saveState);
|
actionManager.restoreUserDefinedKeybindings(saveState);
|
||||||
actionManager.restoreScriptsThatAreInTool(saveState);
|
actionManager.restoreScriptsThatAreInTool(saveState);
|
||||||
|
@ -1162,4 +1187,10 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ResourceFile> getWritableScriptDirectories() {
|
||||||
|
BundleStatusModel m = bundleStatusProvider.getModel();
|
||||||
|
return m.getPaths().stream().filter(ResourceFile::isDirectory).filter(
|
||||||
|
m::isWriteable).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import ghidra.app.plugin.ProgramPlugin;
|
||||||
import ghidra.app.plugin.core.eclipse.EclipseConnection;
|
import ghidra.app.plugin.core.eclipse.EclipseConnection;
|
||||||
import ghidra.app.plugin.core.eclipse.EclipseIntegrationOptionsPlugin;
|
import ghidra.app.plugin.core.eclipse.EclipseIntegrationOptionsPlugin;
|
||||||
import ghidra.app.script.GhidraState;
|
import ghidra.app.script.GhidraState;
|
||||||
|
import ghidra.app.script.osgi.BundleHost;
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
import ghidra.framework.options.ToolOptions;
|
import ghidra.framework.options.ToolOptions;
|
||||||
|
@ -48,12 +49,15 @@ import ghidra.util.task.TaskListener;
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
public class GhidraScriptMgrPlugin extends ProgramPlugin implements GhidraScriptService {
|
public class GhidraScriptMgrPlugin extends ProgramPlugin implements GhidraScriptService {
|
||||||
|
|
||||||
private GhidraScriptComponentProvider provider;
|
final private GhidraScriptComponentProvider provider;
|
||||||
|
|
||||||
|
final private BundleHost bundleHost;
|
||||||
|
|
||||||
public GhidraScriptMgrPlugin(PluginTool tool) {
|
public GhidraScriptMgrPlugin(PluginTool tool) {
|
||||||
super(tool, true, true, true);
|
super(tool, true, true, true);
|
||||||
|
|
||||||
provider = new GhidraScriptComponentProvider(this);
|
bundleHost = BundleHost.getInstance();
|
||||||
|
provider = new GhidraScriptComponentProvider(this, bundleHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -19,7 +19,8 @@ import java.awt.BorderLayout;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
|
@ -31,7 +32,6 @@ import docking.widgets.MultiLineLabel;
|
||||||
import docking.widgets.label.GLabel;
|
import docking.widgets.label.GLabel;
|
||||||
import docking.widgets.list.ListPanel;
|
import docking.widgets.list.ListPanel;
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import generic.util.Path;
|
|
||||||
import ghidra.app.script.*;
|
import ghidra.app.script.*;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ public class SaveDialog extends DialogComponentProvider implements ListSelection
|
||||||
public SaveDialog(Component parent, String title,
|
public SaveDialog(Component parent, String title,
|
||||||
GhidraScriptComponentProvider componentProvider, ResourceFile scriptFile,
|
GhidraScriptComponentProvider componentProvider, ResourceFile scriptFile,
|
||||||
HelpLocation help) {
|
HelpLocation help) {
|
||||||
this(parent, title, componentProvider, getScriptPaths(), scriptFile, help);
|
this(parent, title, componentProvider, componentProvider.getWritableScriptDirectories(), scriptFile, help);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SaveDialog(Component parent, String title,
|
public SaveDialog(Component parent, String title,
|
||||||
|
@ -85,21 +85,6 @@ public class SaveDialog extends DialogComponentProvider implements ListSelection
|
||||||
DockingWindowManager.showDialog(parent, this);
|
DockingWindowManager.showDialog(parent, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<ResourceFile> getScriptPaths() {
|
|
||||||
List<ResourceFile> newPaths = new ArrayList<>();
|
|
||||||
|
|
||||||
List<ResourceFile> scriptPaths = GhidraScriptUtil.getScriptSourceDirectories();
|
|
||||||
for (ResourceFile directory : scriptPaths) {
|
|
||||||
Path path = GhidraScriptUtil.getScriptPath(directory);
|
|
||||||
if (path != null && !path.isReadOnly()) {
|
|
||||||
newPaths.add(directory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(newPaths);
|
|
||||||
return newPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JPanel buildNamePanel() {
|
private JPanel buildNamePanel() {
|
||||||
nameField = new JTextField(20);
|
nameField = new JTextField(20);
|
||||||
nameField.setText(scriptFile == null ? "" : scriptFile.getName());
|
nameField.setText(scriptFile == null ? "" : scriptFile.getName());
|
||||||
|
|
|
@ -21,7 +21,10 @@ import generic.jar.ResourceFile;
|
||||||
import generic.util.Path;
|
import generic.util.Path;
|
||||||
|
|
||||||
public class BundlePath extends Path {
|
public class BundlePath extends Path {
|
||||||
|
final Type type;
|
||||||
|
|
||||||
boolean active = false;
|
boolean active = false;
|
||||||
|
boolean busy = false;
|
||||||
|
|
||||||
public static enum Type {
|
public static enum Type {
|
||||||
BndScript, Jar, SourceDir, INVALID
|
BndScript, Jar, SourceDir, INVALID
|
||||||
|
@ -55,47 +58,43 @@ public class BundlePath extends Path {
|
||||||
return Type.INVALID;
|
return Type.INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Type type;
|
|
||||||
|
|
||||||
public BundlePath(File path) {
|
|
||||||
super(path);
|
|
||||||
type = getType(getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BundlePath(ResourceFile rf) {
|
BundlePath(String path, boolean enabled, boolean readonly) {
|
||||||
super(rf);
|
super(path, enabled, false /*editable */, readonly);
|
||||||
type = getType(getPath());
|
type = getType(getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BundlePath(String absolutePath) {
|
BundlePath(ResourceFile path, boolean enabled, boolean readonly) {
|
||||||
super(absolutePath);
|
super(path, enabled, false /* editable */, readonly);
|
||||||
type = getType(getPath());
|
type = getType(getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BundlePath(String a, boolean b, boolean c, boolean d) {
|
|
||||||
super(a, b, c, d);
|
|
||||||
type = getType(getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
public BundlePath(ResourceFile a, boolean b, boolean c, boolean d) {
|
|
||||||
super(a, b, c, d);
|
|
||||||
type = getType(getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isActive() {
|
|
||||||
return active;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setActive(Boolean b) {
|
|
||||||
active = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDirectory() {
|
public boolean isDirectory() {
|
||||||
return getPath().isDirectory();
|
return getPath().isDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isActive() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEditable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActive(boolean b) {
|
||||||
|
active = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBusy(boolean b) {
|
||||||
|
busy = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBusy() {
|
||||||
|
return busy;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.script.osgi;
|
package ghidra.app.plugin.core.script.osgi;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import docking.widgets.table.AbstractSortedTableModel;
|
import docking.widgets.table.AbstractSortedTableModel;
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
|
@ -41,20 +41,25 @@ public class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean editable(BundlePath path) {
|
boolean editable(BundlePath path) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object getValue(BundlePath path) {
|
Object getValue(BundlePath path) {
|
||||||
return path;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setValue(BundlePath path, Object aValue) {
|
void setValue(BundlePath path, Object aValue) {
|
||||||
// do nothing
|
throw new RuntimeException(name + " is not editable!");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column enabledColumn = new Column("Enabled", Boolean.class) {
|
Column enabledColumn = new Column("Enabled", Boolean.class) {
|
||||||
|
@Override
|
||||||
|
boolean editable(BundlePath path) {
|
||||||
|
return path.exists();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Object getValue(BundlePath path) {
|
Object getValue(BundlePath path) {
|
||||||
return path.isEnabled();
|
return path.isEnabled();
|
||||||
|
@ -67,6 +72,11 @@ public class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Column activeColumn = new Column("Active", Boolean.class) {
|
Column activeColumn = new Column("Active", Boolean.class) {
|
||||||
|
@Override
|
||||||
|
boolean editable(BundlePath path) {
|
||||||
|
return path.exists(); // XXX maybe only if it's already enabled
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Object getValue(BundlePath path) {
|
Object getValue(BundlePath path) {
|
||||||
return path.isActive();
|
return path.isActive();
|
||||||
|
@ -93,15 +103,12 @@ public class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
||||||
Column pathColumn = new Column("Path", BundlePath.class) {
|
Column pathColumn = new Column("Path", BundlePath.class) {
|
||||||
@Override
|
@Override
|
||||||
boolean editable(BundlePath path) {
|
boolean editable(BundlePath path) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void setValue(BundlePath path, Object aValue) {
|
Object getValue(BundlePath path) {
|
||||||
if (path.isEditable()) {
|
return path;
|
||||||
BundlePath newpath = (BundlePath) aValue;
|
|
||||||
path.setPath(newpath.getPath());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Column badColumn = new Column("INVALID", Object.class);
|
Column badColumn = new Column("INVALID", Object.class);
|
||||||
|
@ -118,26 +125,21 @@ public class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private BundleStatusProvider provider;
|
private BundleStatusProvider provider;
|
||||||
private List<BundlePath> paths = new ArrayList<>();
|
private List<BundlePath> paths;
|
||||||
|
|
||||||
BundleStatusModel(BundleStatusProvider provider) {
|
BundleStatusModel(BundleStatusProvider provider) {
|
||||||
super();
|
super();
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.paths.addAll(dedupPaths(GhidraScriptUtil.getDefaultScriptBundles()));
|
|
||||||
|
// add unmodifiable paths
|
||||||
|
this.paths = GhidraScriptUtil.getSystemScriptPaths().stream().distinct().map(
|
||||||
|
f -> new BundlePath(f, true, true)).collect(Collectors.toList());
|
||||||
|
// add user path
|
||||||
|
this.paths.add(0, new BundlePath(GhidraScriptUtil.getUserScriptDirectory(), true, false));
|
||||||
|
|
||||||
fireTableDataChanged();
|
fireTableDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<BundlePath> dedupPaths(List<BundlePath> newPaths) {
|
|
||||||
List<BundlePath> dedupedPaths = new ArrayList<>();
|
|
||||||
for (BundlePath path : newPaths) {
|
|
||||||
if (!dedupedPaths.contains(path)) {
|
|
||||||
dedupedPaths.add(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dedupedPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
paths.clear();
|
paths.clear();
|
||||||
}
|
}
|
||||||
|
@ -146,21 +148,16 @@ public class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
||||||
return new ArrayList<BundlePath>(paths);
|
return new ArrayList<BundlePath>(paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BundlePath> getPaths() {
|
public List<ResourceFile> getPaths() {
|
||||||
List<BundlePath> list = new ArrayList<>();
|
List<ResourceFile> list = new ArrayList<>();
|
||||||
for (BundlePath path : paths) {
|
for (BundlePath path : paths) {
|
||||||
if (path.isEnabled()) {
|
if (path.isEnabled()) {
|
||||||
list.add(path);
|
list.add(path.getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPaths(List<BundlePath> paths) {
|
|
||||||
this.paths = new ArrayList<>(paths);
|
|
||||||
fireTableDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void addPath(BundlePath path) {
|
void addPath(BundlePath path) {
|
||||||
if (paths.contains(path)) {
|
if (paths.contains(path)) {
|
||||||
return;
|
return;
|
||||||
|
@ -176,7 +173,7 @@ public class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
||||||
list.add(paths.get(selectedRow));
|
list.add(paths.get(selectedRow));
|
||||||
}
|
}
|
||||||
for (BundlePath path : list) {
|
for (BundlePath path : list) {
|
||||||
if (path.isEditable()) {
|
if (!path.isReadOnly()) {
|
||||||
paths.remove(path);
|
paths.remove(path);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -259,11 +256,48 @@ public class BundleStatusModel extends AbstractSortedTableModel<BundlePath> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BundlePath p = new BundlePath(dir);
|
BundlePath p = new BundlePath(dir, true, false);
|
||||||
p.setEnabled(true);
|
|
||||||
addPath(p);
|
addPath(p);
|
||||||
Preferences.setProperty(BundleStatusProvider.preferenceForLastSelectedBundle, dir.getAbsolutePath());
|
Preferences.setProperty(BundleStatusProvider.preferenceForLastSelectedBundle,
|
||||||
|
dir.getAbsolutePath());
|
||||||
provider.fireBundlesChanged();
|
provider.fireBundlesChanged();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the given <code>bundle</code> is managed and not marked readonly
|
||||||
|
* @param bundle the path to test
|
||||||
|
* @return true if the bundle is managed and not marked readonly
|
||||||
|
*/
|
||||||
|
public boolean isWriteable(ResourceFile bundle) {
|
||||||
|
Optional<BundlePath> o = paths.stream().filter(
|
||||||
|
bp -> bp.isDirectory() && bp.getPath().equals(bundle)).findFirst();
|
||||||
|
return o.isPresent() && !o.get().isReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is for testing only!
|
||||||
|
*
|
||||||
|
* each path is marked editable and non-readonly
|
||||||
|
*
|
||||||
|
* @param testingPaths the paths to use
|
||||||
|
*/
|
||||||
|
public void setPathsForTesting(List<String> testingPaths) {
|
||||||
|
this.paths = testingPaths.stream().map(f -> new BundlePath(f, true, false)).collect(
|
||||||
|
Collectors.toList());
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is for testing only!
|
||||||
|
*
|
||||||
|
* insert path, marked editable and non-readonly
|
||||||
|
* @param index index to insert at
|
||||||
|
* @param path the path to insert
|
||||||
|
*/
|
||||||
|
public void insertPathForTesting(int index, String path) {
|
||||||
|
paths.add(0, new BundlePath(path, true, false));
|
||||||
|
fireTableRowsInserted(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,13 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.TableModelEvent;
|
||||||
import javax.swing.table.TableColumn;
|
import javax.swing.table.TableColumn;
|
||||||
|
|
||||||
import docking.widgets.filechooser.GhidraFileChooser;
|
import docking.widgets.filechooser.GhidraFileChooser;
|
||||||
import docking.widgets.filechooser.GhidraFileChooserMode;
|
import docking.widgets.filechooser.GhidraFileChooserMode;
|
||||||
import docking.widgets.table.*;
|
import docking.widgets.table.*;
|
||||||
|
import generic.jar.ResourceFile;
|
||||||
import ghidra.framework.options.SaveState;
|
import ghidra.framework.options.SaveState;
|
||||||
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
import ghidra.framework.plugintool.ComponentProviderAdapter;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
|
@ -51,6 +53,10 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
||||||
private GhidraFileFilter filter;
|
private GhidraFileFilter filter;
|
||||||
private ArrayList<BundlePathManagerListener> listeners = new ArrayList<>();
|
private ArrayList<BundlePathManagerListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
|
public void notifyTableChanged() {
|
||||||
|
bundlePathTable.notifyTableChanged(new TableModelEvent(bundleStatusModel));
|
||||||
|
}
|
||||||
|
|
||||||
void fireBundlesChanged() {
|
void fireBundlesChanged() {
|
||||||
for (BundlePathManagerListener listener : listeners) {
|
for (BundlePathManagerListener listener : listeners) {
|
||||||
listener.bundlesChanged();
|
listener.bundlesChanged();
|
||||||
|
@ -108,7 +114,7 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
||||||
panel = new JPanel(new BorderLayout(5, 5));
|
panel = new JPanel(new BorderLayout(5, 5));
|
||||||
|
|
||||||
selectionColor = new Color(204, 204, 255);
|
selectionColor = new Color(204, 204, 255);
|
||||||
|
|
||||||
addButton = new JButton(ResourceManager.loadImage("images/Plus.png"));
|
addButton = new JButton(ResourceManager.loadImage("images/Plus.png"));
|
||||||
addButton.setName("AddBundle");
|
addButton.setName("AddBundle");
|
||||||
addButton.setToolTipText("Display file chooser to add bundles to list");
|
addButton.setToolTipText("Display file chooser to add bundles to list");
|
||||||
|
@ -138,6 +144,9 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
||||||
bundlePathTable.setSelectionForeground(Color.BLACK);
|
bundlePathTable.setSelectionForeground(Color.BLACK);
|
||||||
bundlePathTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
bundlePathTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||||
|
|
||||||
|
// to allow custom cell renderers
|
||||||
|
bundlePathTable.setAutoCreateColumnsFromModel(false);
|
||||||
|
|
||||||
int skinnyWidth = 50;
|
int skinnyWidth = 50;
|
||||||
|
|
||||||
TableColumn column =
|
TableColumn column =
|
||||||
|
@ -152,6 +161,27 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
||||||
column.setMinWidth(skinnyWidth);
|
column.setMinWidth(skinnyWidth);
|
||||||
column.setMaxWidth(skinnyWidth);
|
column.setMaxWidth(skinnyWidth);
|
||||||
column.setWidth(skinnyWidth);
|
column.setWidth(skinnyWidth);
|
||||||
|
column.setCellRenderer(new GBooleanCellRenderer() {
|
||||||
|
@Override
|
||||||
|
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
|
||||||
|
BundlePath path = (BundlePath) data.getRowObject();
|
||||||
|
Component x = super.getTableCellRendererComponent(data);
|
||||||
|
if (path.getBusy()) {
|
||||||
|
cb.setVisible(false);
|
||||||
|
cb.setEnabled(false);
|
||||||
|
setHorizontalAlignment(SwingConstants.CENTER);
|
||||||
|
setText("...");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cb.setVisible(true);
|
||||||
|
cb.setEnabled(true);
|
||||||
|
setText("");
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
column = bundlePathTable.getColumnModel().getColumn(bundleStatusModel.typeColumn.index);
|
column = bundlePathTable.getColumnModel().getColumn(bundleStatusModel.typeColumn.index);
|
||||||
|
|
||||||
|
@ -163,13 +193,13 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
||||||
column.setCellRenderer(new GTableCellRenderer() {
|
column.setCellRenderer(new GTableCellRenderer() {
|
||||||
@Override
|
@Override
|
||||||
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
|
public Component getTableCellRendererComponent(GTableCellRenderingData data) {
|
||||||
JLabel renderer = (JLabel) super.getTableCellRendererComponent(data);
|
JLabel c = (JLabel) super.getTableCellRendererComponent(data);
|
||||||
|
|
||||||
BundlePath path = (BundlePath) data.getValue();
|
BundlePath path = (BundlePath) data.getValue();
|
||||||
if (!path.exists()) {
|
if (!path.exists()) {
|
||||||
renderer.setForeground(Color.RED);
|
c.setForeground(Color.RED);
|
||||||
}
|
}
|
||||||
return renderer;
|
return c;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -262,7 +292,7 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
||||||
Preferences.setProperty(preferenceForLastSelectedBundle,
|
Preferences.setProperty(preferenceForLastSelectedBundle,
|
||||||
files.get(0).getAbsolutePath());
|
files.get(0).getAbsolutePath());
|
||||||
for (File element : files) {
|
for (File element : files) {
|
||||||
BundlePath p = new BundlePath(element);
|
BundlePath p = new BundlePath(new ResourceFile(element), true, false);
|
||||||
bundleStatusModel.addPath(p);
|
bundleStatusModel.addPath(p);
|
||||||
}
|
}
|
||||||
fireBundlesChanged();
|
fireBundlesChanged();
|
||||||
|
@ -283,22 +313,19 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
||||||
|
|
||||||
String[] pathArr = new String[paths.size()];
|
String[] pathArr = new String[paths.size()];
|
||||||
boolean[] enableArr = new boolean[paths.size()];
|
boolean[] enableArr = new boolean[paths.size()];
|
||||||
boolean[] editArr = new boolean[paths.size()];
|
|
||||||
boolean[] readArr = new boolean[paths.size()];
|
boolean[] readArr = new boolean[paths.size()];
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (BundlePath path : paths) {
|
for (BundlePath path : paths) {
|
||||||
pathArr[index] = path.getPathAsString();
|
pathArr[index] = path.getPathAsString();
|
||||||
enableArr[index] = path.isEnabled();
|
enableArr[index] = path.isEnabled();
|
||||||
editArr[index] = path.isEditable();
|
|
||||||
readArr[index] = path.isReadOnly();
|
readArr[index] = path.isReadOnly();
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
||||||
ss.putStrings("BundleManagerPanel_PATH", pathArr);
|
ss.putStrings("BundleStatus_PATH", pathArr);
|
||||||
ss.putBooleans("BundleManagerPanel_ENABLE", enableArr);
|
ss.putBooleans("BundleStatus_ENABLE", enableArr);
|
||||||
ss.putBooleans("BundleManagerPanel_EDIT", editArr);
|
ss.putBooleans("BundleStatus_READ", readArr);
|
||||||
ss.putBooleans("BundleManagerPanel_READ", readArr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -306,22 +333,21 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
||||||
* @param ss the SaveState object
|
* @param ss the SaveState object
|
||||||
*/
|
*/
|
||||||
public void restoreState(SaveState ss) {
|
public void restoreState(SaveState ss) {
|
||||||
String[] pathArr = ss.getStrings("BundleManagerPanel_PATH", new String[0]);
|
String[] pathArr = ss.getStrings("BundleStatus_PATH", new String[0]);
|
||||||
|
|
||||||
if (pathArr.length == 0) {
|
if (pathArr.length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean[] enableArr =
|
boolean[] enableArr =
|
||||||
ss.getBooleans("BundleManagerPanel_ENABLE", new boolean[pathArr.length]);
|
ss.getBooleans("BundleStatus_ENABLE", new boolean[pathArr.length]);
|
||||||
boolean[] editArr = ss.getBooleans("BundleManagerPanel_EDIT", new boolean[pathArr.length]);
|
boolean[] readArr = ss.getBooleans("BundleStatus_READ", new boolean[pathArr.length]);
|
||||||
boolean[] readArr = ss.getBooleans("BundleManagerPanel_READ", new boolean[pathArr.length]);
|
|
||||||
|
|
||||||
List<BundlePath> oldPaths = bundleStatusModel.getAllPaths();
|
List<BundlePath> oldPaths = bundleStatusModel.getAllPaths();
|
||||||
bundleStatusModel.clear();
|
bundleStatusModel.clear();
|
||||||
|
|
||||||
for (int i = 0; i < pathArr.length; i++) {
|
for (int i = 0; i < pathArr.length; i++) {
|
||||||
BundlePath path = new BundlePath(pathArr[i], enableArr[i], editArr[i], readArr[i]);
|
BundlePath path = new BundlePath(pathArr[i], enableArr[i], readArr[i]);
|
||||||
BundlePath oldPath = getPath(path.getPathAsString(), oldPaths);
|
BundlePath oldPath = getPath(path.getPathAsString(), oldPaths);
|
||||||
if (oldPath != null) {
|
if (oldPath != null) {
|
||||||
if (!oldPath.isEditable()) {
|
if (!oldPath.isEditable()) {
|
||||||
|
@ -361,7 +387,4 @@ public class BundleStatusProvider extends ComponentProviderAdapter {
|
||||||
bundlePathTable.dispose();
|
bundlePathTable.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void selectRow(int rowIndex) {
|
|
||||||
bundlePathTable.selectRow(rowIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import java.util.stream.Collectors;
|
||||||
import org.apache.commons.collections4.map.LazyMap;
|
import org.apache.commons.collections4.map.LazyMap;
|
||||||
|
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import ghidra.app.plugin.core.script.osgi.BundlePath;
|
|
||||||
import ghidra.framework.Application;
|
import ghidra.framework.Application;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
@ -48,7 +47,7 @@ public class GhidraScriptUtil {
|
||||||
*/
|
*/
|
||||||
public static String USER_SCRIPTS_DIR = buildUserScriptsDirectory();
|
public static String USER_SCRIPTS_DIR = buildUserScriptsDirectory();
|
||||||
|
|
||||||
private static List<BundlePath> scriptBundlePaths = new ArrayList<>();
|
private static List<ResourceFile> scriptBundlePaths = new ArrayList<>();
|
||||||
|
|
||||||
private static Map<ResourceFile, ScriptInfo> scriptFileToInfoMap = new HashMap<>();
|
private static Map<ResourceFile, ScriptInfo> scriptFileToInfoMap = new HashMap<>();
|
||||||
|
|
||||||
|
@ -56,7 +55,8 @@ public class GhidraScriptUtil {
|
||||||
LazyMap.lazyMap(new HashMap<String, List<ResourceFile>>(), () -> new ArrayList<>());
|
LazyMap.lazyMap(new HashMap<String, List<ResourceFile>>(), () -> new ArrayList<>());
|
||||||
|
|
||||||
static {
|
static {
|
||||||
scriptBundlePaths = getDefaultScriptBundles();
|
scriptBundlePaths = getSystemScriptPaths();
|
||||||
|
scriptBundlePaths.add(0, getUserScriptDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,25 +81,22 @@ public class GhidraScriptUtil {
|
||||||
* Returns a list of the default script directories.
|
* Returns a list of the default script directories.
|
||||||
* @return a list of the default script directories
|
* @return a list of the default script directories
|
||||||
*/
|
*/
|
||||||
public static List<BundlePath> getDefaultScriptBundles() {
|
public static List<ResourceFile> getSystemScriptPaths() {
|
||||||
|
List<ResourceFile> pathsList = new ArrayList<>();
|
||||||
List<BundlePath> pathsList = new ArrayList<>();
|
|
||||||
|
|
||||||
addScriptPaths(pathsList, SCRIPTS_SUBDIR_NAME);
|
addScriptPaths(pathsList, SCRIPTS_SUBDIR_NAME);
|
||||||
addScriptPaths(pathsList, DEV_SCRIPTS_SUBDIR_NAME);
|
addScriptPaths(pathsList, DEV_SCRIPTS_SUBDIR_NAME);
|
||||||
|
|
||||||
Collections.sort(pathsList);
|
Collections.sort(pathsList);
|
||||||
|
|
||||||
// this one should always be first
|
|
||||||
pathsList.add(0, new BundlePath(new ResourceFile(USER_SCRIPTS_DIR), true, false, false));
|
|
||||||
return pathsList;
|
return pathsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addScriptPaths(List<BundlePath> pathsList, String directoryName) {
|
public static ResourceFile getUserScriptDirectory() {
|
||||||
Iterable<ResourceFile> files = Application.findModuleSubDirectories(directoryName);
|
return new ResourceFile(USER_SCRIPTS_DIR);
|
||||||
for (ResourceFile file : files) {
|
}
|
||||||
pathsList.add(new BundlePath(file, true, false, true));
|
|
||||||
}
|
private static void addScriptPaths(List<ResourceFile> pathsList, String directoryName) {
|
||||||
|
pathsList.addAll(Application.findModuleSubDirectories(directoryName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,39 +141,18 @@ public class GhidraScriptUtil {
|
||||||
* @return a list of the current script directories
|
* @return a list of the current script directories
|
||||||
*/
|
*/
|
||||||
public static List<ResourceFile> getScriptSourceDirectories() {
|
public static List<ResourceFile> getScriptSourceDirectories() {
|
||||||
ArrayList<ResourceFile> dirs = new ArrayList<>();
|
return scriptBundlePaths.stream().filter(ResourceFile::isDirectory).collect(
|
||||||
for (BundlePath path : scriptBundlePaths) {
|
Collectors.toList());
|
||||||
if (path.isDirectory()) {
|
|
||||||
dirs.add(path.getPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dirs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the script bundle paths
|
* Sets the script bundle paths
|
||||||
* @param newPaths the new script bundle paths
|
* @param newPaths the new script bundle paths
|
||||||
*/
|
*/
|
||||||
public static void setScriptBundlePaths(List<BundlePath> newPaths) {
|
public static void setScriptBundlePaths(List<ResourceFile> newPaths) {
|
||||||
scriptBundlePaths = new ArrayList<>(newPaths);
|
scriptBundlePaths = new ArrayList<>(newPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the PATH for the specified directory.
|
|
||||||
* @param directory the directory
|
|
||||||
* @return the path for the specified directory
|
|
||||||
*/
|
|
||||||
public static BundlePath getScriptPath(ResourceFile directory) {
|
|
||||||
if (directory.isDirectory()) {
|
|
||||||
for (BundlePath path : scriptBundlePaths) {
|
|
||||||
if (path.getPath().equals(directory)) {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Path getOsgiDir() {
|
public static Path getOsgiDir() {
|
||||||
Path usersettings = Application.getUserSettingsDirectory().toPath();
|
Path usersettings = Application.getUserSettingsDirectory().toPath();
|
||||||
return usersettings.resolve("osgi");
|
return usersettings.resolve("osgi");
|
||||||
|
@ -218,7 +194,7 @@ public class GhidraScriptUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<ResourceFile> dirs = new HashSet<>();
|
Set<ResourceFile> dirs = new HashSet<>();
|
||||||
for (BundlePath path : scriptBundlePaths) {
|
for (ResourceFile scriptDir : scriptBundlePaths) {
|
||||||
//
|
//
|
||||||
// Assumed structure of script dir path:
|
// Assumed structure of script dir path:
|
||||||
// /some/path/Ghidra/Features/Module/ghidra_scripts
|
// /some/path/Ghidra/Features/Module/ghidra_scripts
|
||||||
|
@ -226,7 +202,6 @@ public class GhidraScriptUtil {
|
||||||
// Desired path:
|
// Desired path:
|
||||||
// /some/path/Ghidra/Features/Module/bin/scripts
|
// /some/path/Ghidra/Features/Module/bin/scripts
|
||||||
|
|
||||||
ResourceFile scriptDir = path.getPath();
|
|
||||||
ResourceFile moduleDir = scriptDir.getParentFile();
|
ResourceFile moduleDir = scriptDir.getParentFile();
|
||||||
dirs.add(new ResourceFile(moduleDir, BIN_DIR_NAME + File.separator + "scripts"));
|
dirs.add(new ResourceFile(moduleDir, BIN_DIR_NAME + File.separator + "scripts"));
|
||||||
}
|
}
|
||||||
|
@ -381,14 +356,14 @@ public class GhidraScriptUtil {
|
||||||
* @throws IOException if an i/o error occurs
|
* @throws IOException if an i/o error occurs
|
||||||
*/
|
*/
|
||||||
public static ResourceFile createNewScript(GhidraScriptProvider provider,
|
public static ResourceFile createNewScript(GhidraScriptProvider provider,
|
||||||
ResourceFile parentDirectory, List<BundlePath> scriptDirectories) throws IOException {
|
ResourceFile parentDirectory, List<ResourceFile> scriptDirectories) throws IOException {
|
||||||
String baseName = GhidraScriptConstants.DEFAULT_SCRIPT_NAME;
|
String baseName = GhidraScriptConstants.DEFAULT_SCRIPT_NAME;
|
||||||
String extension = provider.getExtension();
|
String extension = provider.getExtension();
|
||||||
return createNewScript(baseName, extension, parentDirectory, scriptDirectories);
|
return createNewScript(baseName, extension, parentDirectory, scriptDirectories);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ResourceFile createNewScript(String scriptName, String extension,
|
private static ResourceFile createNewScript(String scriptName, String extension,
|
||||||
ResourceFile parentDirctory, List<BundlePath> scriptDirectories) throws IOException {
|
ResourceFile parentDirctory, List<ResourceFile> scriptDirectories) throws IOException {
|
||||||
String baseName = scriptName;
|
String baseName = scriptName;
|
||||||
String className = baseName + extension;
|
String className = baseName + extension;
|
||||||
|
|
||||||
|
@ -409,13 +384,12 @@ public class GhidraScriptUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if the given filename exists in any of the given directories */
|
/** Returns true if the given filename exists in any of the given directories */
|
||||||
private static ResourceFile findScriptFileInPaths(List<BundlePath> scriptDirectories,
|
private static ResourceFile findScriptFileInPaths(List<ResourceFile> scriptDirectories,
|
||||||
String filename) {
|
String filename) {
|
||||||
|
|
||||||
String validatedName = fixupName(filename);
|
String validatedName = fixupName(filename);
|
||||||
|
|
||||||
for (BundlePath path : scriptDirectories) {
|
for (ResourceFile resourceFile : scriptDirectories) {
|
||||||
ResourceFile resourceFile = path.getPath();
|
|
||||||
if (resourceFile.isDirectory()) {
|
if (resourceFile.isDirectory()) {
|
||||||
ResourceFile file = new ResourceFile(resourceFile, validatedName);
|
ResourceFile file = new ResourceFile(resourceFile, validatedName);
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
|
@ -477,8 +451,8 @@ public class GhidraScriptUtil {
|
||||||
|
|
||||||
public static List<ResourceFile> getAllScripts() {
|
public static List<ResourceFile> getAllScripts() {
|
||||||
List<ResourceFile> scriptList = new ArrayList<>();
|
List<ResourceFile> scriptList = new ArrayList<>();
|
||||||
for (BundlePath dirPath : scriptBundlePaths) {
|
for (ResourceFile dirPath : scriptBundlePaths) {
|
||||||
updateAvailableScriptFilesForDirectory(scriptList, dirPath.getPath());
|
updateAvailableScriptFilesForDirectory(scriptList, dirPath);
|
||||||
}
|
}
|
||||||
return scriptList;
|
return scriptList;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import ghidra.app.script.osgi.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
public class JavaScriptProvider extends GhidraScriptProvider {
|
public class JavaScriptProvider extends GhidraScriptProvider {
|
||||||
public SourceBundleInfo getBundleInfoForSource(ResourceFile sourceFile) {
|
static public SourceBundleInfo getBundleInfoForSource(ResourceFile sourceFile) {
|
||||||
ResourceFile sourceDir = getSourceDirectoryContaining(sourceFile);
|
ResourceFile sourceDir = getSourceDirectoryContaining(sourceFile);
|
||||||
if (sourceDir == null) {
|
if (sourceDir == null) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -87,7 +87,7 @@ public class JavaScriptProvider extends GhidraScriptProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> loadClass(ResourceFile sourceFile, PrintWriter writer)
|
static public Class<?> loadClass(ResourceFile sourceFile, PrintWriter writer)
|
||||||
throws IOException, OSGiException, ClassNotFoundException, InterruptedException {
|
throws IOException, OSGiException, ClassNotFoundException, InterruptedException {
|
||||||
|
|
||||||
if (writer == null) {
|
if (writer == null) {
|
||||||
|
@ -95,72 +95,7 @@ public class JavaScriptProvider extends GhidraScriptProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceBundleInfo bi = getBundleInfoForSource(sourceFile);
|
SourceBundleInfo bi = getBundleInfoForSource(sourceFile);
|
||||||
|
Bundle b = BundleHost.getInstance().activate(bi, writer);
|
||||||
bi.updateFromFilesystem(writer);
|
|
||||||
|
|
||||||
// needsCompile => needsBundleActivate
|
|
||||||
boolean needsCompile = false;
|
|
||||||
boolean needsBundleActivate = false;
|
|
||||||
|
|
||||||
int failing = bi.getFailingSourcesCount();
|
|
||||||
int newSourcecount = bi.getNewSourcesCount();
|
|
||||||
|
|
||||||
long lastBundleActivation = 0; // XXX record last bundle activation in pathmanager
|
|
||||||
if (failing > 0 && (lastBundleActivation > bi.getLastCompileAttempt())) {
|
|
||||||
needsCompile = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newSourcecount == 0) {
|
|
||||||
if (failing > 0) {
|
|
||||||
writer.printf("%s hasn't changed, with %d file%s failing in previous build(s):\n",
|
|
||||||
bi.getSourceDir().toString(), failing, failing > 1 ? "s" : "");
|
|
||||||
writer.printf("%s\n", bi.getPreviousBuildErrors());
|
|
||||||
}
|
|
||||||
if (bi.newManifestFile()) {
|
|
||||||
needsCompile = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
needsCompile = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
needsBundleActivate |= needsCompile;
|
|
||||||
|
|
||||||
BundleHost bundle_host = BundleHost.getInstance();
|
|
||||||
if (needsBundleActivate) {
|
|
||||||
writer.printf("%s has %d new/updated %d failed in previous build(s)%s\n",
|
|
||||||
bi.getSourceDir().toString(), newSourcecount, failing,
|
|
||||||
bi.newManifestFile() ? " and the manifest is new" : "");
|
|
||||||
|
|
||||||
// if there a bundle is currently active, uninstall it
|
|
||||||
Bundle b = bi.getBundle();
|
|
||||||
if (b != null) {
|
|
||||||
bundle_host.synchronousUninstall(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
// once we've committed to recompile and regenerate generated classes, delete the old stuff
|
|
||||||
if (needsCompile) {
|
|
||||||
bi.deleteOldBinaries();
|
|
||||||
|
|
||||||
BundleCompiler bc = new BundleCompiler(bundle_host);
|
|
||||||
|
|
||||||
long startTime = System.nanoTime();
|
|
||||||
bc.compileToExplodedBundle(bi, writer);
|
|
||||||
long endTime = System.nanoTime();
|
|
||||||
writer.printf("%3.2f seconds compile time.\n", (endTime - startTime) / 1e9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// as much source as possible built, install bundle and start it if necessary
|
|
||||||
Bundle b = bi.getBundle();
|
|
||||||
if (b == null) {
|
|
||||||
b = bi.install();
|
|
||||||
needsBundleActivate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsBundleActivate) {
|
|
||||||
bundle_host.synchronousStart(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
String classname = bi.classNameForScript(sourceFile);
|
String classname = bi.classNameForScript(sourceFile);
|
||||||
Class<?> clazz = b.loadClass(classname); // throws ClassNotFoundException
|
Class<?> clazz = b.loadClass(classname); // throws ClassNotFoundException
|
||||||
return clazz;
|
return clazz;
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.osgi.framework.wiring.*;
|
||||||
import org.osgi.service.log.*;
|
import org.osgi.service.log.*;
|
||||||
|
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
|
import ghidra.app.plugin.core.script.osgi.BundlePath;
|
||||||
import ghidra.app.script.GhidraScriptUtil;
|
import ghidra.app.script.GhidraScriptUtil;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.*;
|
import ghidra.util.task.*;
|
||||||
|
@ -532,4 +533,101 @@ public class BundleHost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the status of the bundle referenced by <code>path</code>
|
||||||
|
*
|
||||||
|
* @param path the bundle path to activate/deactivate
|
||||||
|
* @param value the new activation value
|
||||||
|
* @throws InterruptedException
|
||||||
|
*/
|
||||||
|
public void setActive(BundlePath path, boolean value) throws InterruptedException {
|
||||||
|
if (path.isDirectory()) {
|
||||||
|
SourceBundleInfo sbi = getSourceBundleInfo(path.getPath());
|
||||||
|
}
|
||||||
|
Thread.sleep(3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* synchronously perform steps necessary to activate bundle:
|
||||||
|
* <ol>
|
||||||
|
* <li>if source bundle, checkCompile</li>
|
||||||
|
* <li>b</li>
|
||||||
|
*
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* @param bi the bundle info
|
||||||
|
* @param writer where to write issues
|
||||||
|
* @throws OSGiException if bundle operations fail
|
||||||
|
* @throws IOException if there are issues with the contents of the bundle
|
||||||
|
* @return the activated bundle
|
||||||
|
* @throws InterruptedException if interrupted while waiting for bundle state change
|
||||||
|
*/
|
||||||
|
public Bundle activate(SourceBundleInfo bi, PrintWriter writer)
|
||||||
|
throws OSGiException, IOException, InterruptedException {
|
||||||
|
bi.updateFromFilesystem(writer);
|
||||||
|
|
||||||
|
// needsCompile => needsBundleActivate
|
||||||
|
boolean needsCompile = false;
|
||||||
|
boolean needsBundleActivate = false;
|
||||||
|
|
||||||
|
int failing = bi.getFailingSourcesCount();
|
||||||
|
int newSourcecount = bi.getNewSourcesCount();
|
||||||
|
|
||||||
|
long lastBundleActivation = 0; // XXX record last bundle activation in bundlestatusmodel
|
||||||
|
if (failing > 0 && (lastBundleActivation > bi.getLastCompileAttempt())) {
|
||||||
|
needsCompile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newSourcecount == 0) {
|
||||||
|
if (failing > 0) {
|
||||||
|
writer.printf("%s hasn't changed, with %d file%s failing in previous build(s):\n",
|
||||||
|
bi.getSourceDir().toString(), failing, failing > 1 ? "s" : "");
|
||||||
|
writer.printf("%s\n", bi.getPreviousBuildErrors());
|
||||||
|
}
|
||||||
|
if (bi.newManifestFile()) {
|
||||||
|
needsCompile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
needsCompile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
needsBundleActivate |= needsCompile;
|
||||||
|
|
||||||
|
if (needsBundleActivate) {
|
||||||
|
writer.printf("%s has %d new/updated %d failed in previous build(s)%s\n",
|
||||||
|
bi.getSourceDir().toString(), newSourcecount, failing,
|
||||||
|
bi.newManifestFile() ? " and the manifest is new" : "");
|
||||||
|
|
||||||
|
// if there a bundle is currently active, uninstall it
|
||||||
|
Bundle b = bi.getBundle();
|
||||||
|
if (b != null) {
|
||||||
|
synchronousUninstall(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// once we've committed to recompile and regenerate generated classes, delete the old stuff
|
||||||
|
if (needsCompile) {
|
||||||
|
bi.deleteOldBinaries();
|
||||||
|
|
||||||
|
BundleCompiler bc = new BundleCompiler(this);
|
||||||
|
|
||||||
|
long startTime = System.nanoTime();
|
||||||
|
bc.compileToExplodedBundle(bi, writer);
|
||||||
|
long endTime = System.nanoTime();
|
||||||
|
writer.printf("%3.2f seconds compile time.\n", (endTime - startTime) / 1e9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// as much source as possible built, install bundle and start it if necessary
|
||||||
|
Bundle b = bi.getBundle();
|
||||||
|
if (b == null) {
|
||||||
|
b = bi.install();
|
||||||
|
needsBundleActivate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsBundleActivate) {
|
||||||
|
synchronousStart(b);
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import java.util.List;
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import ghidra.GhidraApplicationLayout;
|
import ghidra.GhidraApplicationLayout;
|
||||||
import ghidra.GhidraLaunchable;
|
import ghidra.GhidraLaunchable;
|
||||||
import ghidra.app.plugin.core.script.osgi.BundlePath;
|
|
||||||
import ghidra.app.script.*;
|
import ghidra.app.script.*;
|
||||||
import ghidra.framework.Application;
|
import ghidra.framework.Application;
|
||||||
import ghidra.framework.HeadlessGhidraApplicationConfiguration;
|
import ghidra.framework.HeadlessGhidraApplicationConfiguration;
|
||||||
|
@ -31,7 +30,7 @@ import ghidra.program.database.ProgramDB;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.SystemUtilities;
|
||||||
import ghidra.util.task.TaskMonitorAdapter;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import utility.application.ApplicationLayout;
|
import utility.application.ApplicationLayout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,7 +75,7 @@ public class GhidraScriptRunner implements GhidraLaunchable {
|
||||||
try {
|
try {
|
||||||
PrintWriter writer = new PrintWriter(System.out);
|
PrintWriter writer = new PrintWriter(System.out);
|
||||||
Msg.info(this, "SCRIPT: " + scriptName);
|
Msg.info(this, "SCRIPT: " + scriptName);
|
||||||
script.execute(scriptState, TaskMonitorAdapter.DUMMY_MONITOR, writer);
|
script.execute(scriptState, TaskMonitor.DUMMY, writer);
|
||||||
writer.flush();
|
writer.flush();
|
||||||
}
|
}
|
||||||
catch (Exception exc) {
|
catch (Exception exc) {
|
||||||
|
@ -100,8 +99,8 @@ public class GhidraScriptRunner implements GhidraLaunchable {
|
||||||
GhidraScriptProvider provider = GhidraScriptUtil.getProvider(scriptSourceFile);
|
GhidraScriptProvider provider = GhidraScriptUtil.getProvider(scriptSourceFile);
|
||||||
|
|
||||||
if (provider == null) {
|
if (provider == null) {
|
||||||
throw new IOException("Missing plugin needed to run scripts of this type. Please "
|
throw new IOException("Missing plugin needed to run scripts of this type. Please " +
|
||||||
+ "ensure you have installed the necessary plugin.");
|
"ensure you have installed the necessary plugin.");
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintWriter writer = new PrintWriter(System.out);
|
PrintWriter writer = new PrintWriter(System.out);
|
||||||
|
@ -192,20 +191,18 @@ public class GhidraScriptRunner implements GhidraLaunchable {
|
||||||
* Gather paths where scripts may be found.
|
* Gather paths where scripts may be found.
|
||||||
*/
|
*/
|
||||||
private void initializeScriptPaths() {
|
private void initializeScriptPaths() {
|
||||||
List<BundlePath> paths;
|
List<ResourceFile> paths;
|
||||||
if (scriptPaths == null || scriptPaths.isEmpty()) {
|
if (scriptPaths == null || scriptPaths.isEmpty()) {
|
||||||
paths = GhidraScriptUtil.getDefaultScriptBundles();
|
paths = GhidraScriptUtil.getSystemScriptPaths();
|
||||||
|
paths.add(0, GhidraScriptUtil.getUserScriptDirectory());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
paths = new ArrayList<>();
|
paths = new ArrayList<>();
|
||||||
for (String path : scriptPaths) {
|
for (String path : scriptPaths) {
|
||||||
paths.add(new BundlePath(path, true, false, true));
|
paths.add(new ResourceFile(path));
|
||||||
}
|
|
||||||
for (BundlePath path : GhidraScriptUtil.getDefaultScriptBundles()) {
|
|
||||||
if (path.isEnabled() && !paths.contains(path)) {
|
|
||||||
paths.add(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
paths.addAll(GhidraScriptUtil.getSystemScriptPaths());
|
||||||
|
paths.add(0, GhidraScriptUtil.getUserScriptDirectory());
|
||||||
}
|
}
|
||||||
GhidraScriptUtil.setScriptBundlePaths(paths);
|
GhidraScriptUtil.setScriptBundlePaths(paths);
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ import generic.util.Path;
|
||||||
import ghidra.GhidraApplicationLayout;
|
import ghidra.GhidraApplicationLayout;
|
||||||
import ghidra.GhidraJarApplicationLayout;
|
import ghidra.GhidraJarApplicationLayout;
|
||||||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||||
import ghidra.app.plugin.core.script.osgi.BundlePath;
|
|
||||||
import ghidra.app.script.*;
|
import ghidra.app.script.*;
|
||||||
import ghidra.app.util.headless.HeadlessScript.HeadlessContinuationOption;
|
import ghidra.app.util.headless.HeadlessScript.HeadlessContinuationOption;
|
||||||
import ghidra.app.util.importer.AutoImporter;
|
import ghidra.app.util.importer.AutoImporter;
|
||||||
|
@ -661,20 +660,18 @@ public class HeadlessAnalyzer {
|
||||||
*/
|
*/
|
||||||
private void initializeScriptPaths() {
|
private void initializeScriptPaths() {
|
||||||
|
|
||||||
List<BundlePath> paths;
|
List<ResourceFile> paths;
|
||||||
if (options.scriptPaths == null || options.scriptPaths.isEmpty()) {
|
if (options.scriptPaths == null || options.scriptPaths.isEmpty()) {
|
||||||
paths = GhidraScriptUtil.getDefaultScriptBundles();
|
paths = GhidraScriptUtil.getSystemScriptPaths();
|
||||||
|
paths.add(0, GhidraScriptUtil.getUserScriptDirectory());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
paths = new ArrayList<>();
|
paths = new ArrayList<>();
|
||||||
for (String path : options.scriptPaths) {
|
for (String path : options.scriptPaths) {
|
||||||
paths.add(new BundlePath(path, true, false, true));
|
paths.add(new ResourceFile(path));
|
||||||
}
|
|
||||||
for (BundlePath path : GhidraScriptUtil.getDefaultScriptBundles()) {
|
|
||||||
if (path.isEnabled() && !paths.contains(path)) {
|
|
||||||
paths.add(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
paths.addAll(GhidraScriptUtil.getSystemScriptPaths());
|
||||||
|
paths.add(0, GhidraScriptUtil.getUserScriptDirectory());
|
||||||
}
|
}
|
||||||
GhidraScriptUtil.setScriptBundlePaths(paths);
|
GhidraScriptUtil.setScriptBundlePaths(paths);
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,6 @@ import generic.jar.ResourceFile;
|
||||||
import generic.test.TestUtils;
|
import generic.test.TestUtils;
|
||||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||||
import ghidra.app.plugin.core.console.ConsoleComponentProvider;
|
import ghidra.app.plugin.core.console.ConsoleComponentProvider;
|
||||||
import ghidra.app.plugin.core.script.osgi.BundlePath;
|
|
||||||
import ghidra.app.plugin.core.script.osgi.BundleStatusProvider;
|
import ghidra.app.plugin.core.script.osgi.BundleStatusProvider;
|
||||||
import ghidra.app.script.*;
|
import ghidra.app.script.*;
|
||||||
import ghidra.app.services.ConsoleService;
|
import ghidra.app.services.ConsoleService;
|
||||||
|
@ -979,10 +978,10 @@ public abstract class AbstractGhidraScriptMgrPluginTest
|
||||||
|
|
||||||
// destroy any NewScriptxxx files...and Temp ones too
|
// destroy any NewScriptxxx files...and Temp ones too
|
||||||
BundleStatusProvider bundleStatusProvider =
|
BundleStatusProvider bundleStatusProvider =
|
||||||
(BundleStatusProvider) TestUtils.getInstanceField("bundlePathManager", provider);
|
(BundleStatusProvider) TestUtils.getInstanceField("bundleStatusProvider", provider);
|
||||||
List<BundlePath> paths = bundleStatusProvider.getModel().getPaths();
|
List<ResourceFile> paths = bundleStatusProvider.getModel().getPaths();
|
||||||
for (BundlePath path : paths) {
|
for (ResourceFile path : paths) {
|
||||||
File file = path.getPath().getFile(false);
|
File file = path.getFile(false);
|
||||||
File[] listFiles = file.listFiles();
|
File[] listFiles = file.listFiles();
|
||||||
if (listFiles == null) {
|
if (listFiles == null) {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -19,9 +19,7 @@ import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.awt.event.InputEvent;
|
import java.awt.event.InputEvent;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
|
@ -32,7 +30,6 @@ import docking.action.DockingActionIf;
|
||||||
import docking.widgets.filter.FilterTextField;
|
import docking.widgets.filter.FilterTextField;
|
||||||
import docking.widgets.list.ListPanel;
|
import docking.widgets.list.ListPanel;
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import ghidra.app.plugin.core.script.osgi.BundlePath;
|
|
||||||
import ghidra.app.plugin.core.script.osgi.BundleStatusProvider;
|
import ghidra.app.plugin.core.script.osgi.BundleStatusProvider;
|
||||||
import ghidra.app.script.GhidraScriptUtil;
|
import ghidra.app.script.GhidraScriptUtil;
|
||||||
import ghidra.app.script.JavaScriptProvider;
|
import ghidra.app.script.JavaScriptProvider;
|
||||||
|
@ -286,13 +283,11 @@ public class GhidraScriptMgrPlugin3Test extends AbstractGhidraScriptMgrPluginTes
|
||||||
|
|
||||||
final BundleStatusProvider bundleStatusProvider = waitForComponentProvider(BundleStatusProvider.class);
|
final BundleStatusProvider bundleStatusProvider = waitForComponentProvider(BundleStatusProvider.class);
|
||||||
|
|
||||||
final File dir = new File(getTestDirectoryPath() + "/test_scripts");
|
final ResourceFile dir = new ResourceFile(getTestDirectoryPath() + "/test_scripts");
|
||||||
dir.mkdirs();
|
dir.getFile(false).mkdirs();
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
List<BundlePath> paths = bundleStatusProvider.getModel().getPaths();
|
bundleStatusProvider.getModel().insertPathForTesting(0, dir.getAbsolutePath());
|
||||||
paths.add(0, new BundlePath(dir));
|
|
||||||
bundleStatusProvider.getModel().setPaths(paths);
|
|
||||||
});
|
});
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
|
@ -333,7 +328,7 @@ public class GhidraScriptMgrPlugin3Test extends AbstractGhidraScriptMgrPluginTes
|
||||||
assertTrue(newScript.exists());
|
assertTrue(newScript.exists());
|
||||||
|
|
||||||
assertNotNull(newScript);
|
assertNotNull(newScript);
|
||||||
assertEquals(dir, newScript.getParentFile().getFile(false));
|
assertEquals(dir.getAbsolutePath(), newScript.getParentFile().getFile(false).getAbsolutePath());
|
||||||
|
|
||||||
newScript.delete();
|
newScript.delete();
|
||||||
dir.delete();
|
dir.delete();
|
||||||
|
|
|
@ -28,7 +28,6 @@ import docking.widgets.tree.GTreeNode;
|
||||||
import generic.jar.ResourceFile;
|
import generic.jar.ResourceFile;
|
||||||
import ghidra.app.plugin.core.console.ConsoleComponentProvider;
|
import ghidra.app.plugin.core.console.ConsoleComponentProvider;
|
||||||
import ghidra.app.plugin.core.script.*;
|
import ghidra.app.plugin.core.script.*;
|
||||||
import ghidra.app.plugin.core.script.osgi.BundlePath;
|
|
||||||
import ghidra.app.plugin.core.script.osgi.BundleStatusProvider;
|
import ghidra.app.plugin.core.script.osgi.BundleStatusProvider;
|
||||||
import ghidra.app.script.GhidraScriptUtil;
|
import ghidra.app.script.GhidraScriptUtil;
|
||||||
import ghidra.app.services.ConsoleService;
|
import ghidra.app.services.ConsoleService;
|
||||||
|
@ -50,10 +49,10 @@ public class GhidraScriptMgrPluginScreenShots extends GhidraScreenShotGenerator
|
||||||
|
|
||||||
performAction("New", "GhidraScriptMgrPlugin", false);
|
performAction("New", "GhidraScriptMgrPlugin", false);
|
||||||
|
|
||||||
JDialog d = waitForJDialog(null, "New Script: Type", 5000);
|
JDialog d = waitForJDialog("New Script: Type");
|
||||||
pressButtonByText(d, "OK");
|
pressButtonByText(d, "OK");
|
||||||
|
|
||||||
d = waitForJDialog(null, "New Script", 5000);
|
d = waitForJDialog("New Script");
|
||||||
pressButtonByText(d, "OK");
|
pressButtonByText(d, "OK");
|
||||||
|
|
||||||
captureIsolatedProvider(GhidraScriptEditorComponentProvider.class, 597, 600);
|
captureIsolatedProvider(GhidraScriptEditorComponentProvider.class, 597, 600);
|
||||||
|
@ -111,13 +110,13 @@ public class GhidraScriptMgrPluginScreenShots extends GhidraScreenShotGenerator
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testScript_Dirs() throws Exception {
|
public void testScript_Dirs() throws Exception {
|
||||||
List<BundlePath> paths = new ArrayList<>();
|
List<String> paths = new ArrayList<>();
|
||||||
paths.add(new BundlePath("$USER_HOME/ghidra_scripts"));
|
paths.add("$USER_HOME/ghidra_scripts");
|
||||||
paths.add(new BundlePath("$GHIDRA_HOME/Features/Base/ghidra_scripts"));
|
paths.add("$GHIDRA_HOME/Features/Base/ghidra_scripts");
|
||||||
paths.add(new BundlePath("/User/defined/invalid/directory"));
|
paths.add("/User/defined/invalid/directory");
|
||||||
|
|
||||||
BundleStatusProvider bundleStatusProvider = showProvider(BundleStatusProvider.class);
|
BundleStatusProvider bundleStatusProvider = showProvider(BundleStatusProvider.class);
|
||||||
bundleStatusProvider.getModel().setPaths(paths);
|
bundleStatusProvider.getModel().setPathsForTesting(paths);
|
||||||
|
|
||||||
waitForComponentProvider(BundleStatusProvider.class);
|
waitForComponentProvider(BundleStatusProvider.class);
|
||||||
captureComponent(bundleStatusProvider.getComponent());
|
captureComponent(bundleStatusProvider.getComponent());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue