mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-16 15:40:14 +00:00
Merge remote-tracking branch 'origin/GP-4659_ryanmkurtz_jython'
This commit is contained in:
commit
907a834fdc
@ -21,7 +21,7 @@ apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/javadoc.gradle"
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
eclipse.project.name = 'Features Python'
|
||||
eclipse.project.name = 'Features Jython'
|
||||
|
||||
|
||||
def JYTHON = "org.python:jython-standalone:2.7.3"
|
||||
@ -51,15 +51,15 @@ task jythonUnpack(type: Copy) {
|
||||
destinationDir file("build/data/${JYTHON_DIR}")
|
||||
}
|
||||
|
||||
task pythonSrcCopy(type: Copy) {
|
||||
description "Copy python-src directory (for Feature Python)"
|
||||
task jythonSrcCopy(type: Copy) {
|
||||
description "Copy jython-src directory (for Feature Jython)"
|
||||
|
||||
from(file("python-src"))
|
||||
from(file("jython-src"))
|
||||
|
||||
destinationDir file("build/data/python-src")
|
||||
destinationDir file("build/data/jython-src")
|
||||
}
|
||||
|
||||
// Ensure that Jython is usable in development xx
|
||||
rootProject.prepDev.dependsOn jythonUnpack
|
||||
jar.dependsOn jythonUnpack
|
||||
jar.dependsOn pythonSrcCopy
|
||||
jar.dependsOn jythonSrcCopy
|
@ -2,7 +2,7 @@
|
||||
##MODULE IP: Jython License
|
||||
##MODULE IP: LGPL 2.1
|
||||
Module.manifest||GHIDRA||||END|
|
||||
data/python.theme.properties||GHIDRA||||END|
|
||||
data/jython.theme.properties||GHIDRA||||END|
|
||||
src/main/help/help/TOC_Source.xml||GHIDRA||||END|
|
||||
src/main/help/help/topics/Python/interpreter.html||GHIDRA||||END|
|
||||
src/main/help/help/topics/Jython/interpreter.html||GHIDRA||||END|
|
||||
src/main/resources/images/python.png||GHIDRA||||END|
|
21
Ghidra/Features/Jython/data/jython.theme.properties
Normal file
21
Ghidra/Features/Jython/data/jython.theme.properties
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
[Defaults]
|
||||
|
||||
color.fg.plugin.jython.syntax.class = color.palette.blue
|
||||
color.fg.plugin.jython.syntax.code = color.palette.darkgreen
|
||||
color.fg.plugin.jython.syntax.function = color.palette.green
|
||||
color.fg.plugin.jython.syntax.instance = color.palette.purple
|
||||
color.fg.plugin.jython.syntax.map = color.palette.steelblue
|
||||
color.fg.plugin.jython.syntax.method = color.palette.teal
|
||||
color.fg.plugin.jython.syntax.null = color.palette.red
|
||||
color.fg.plugin.jython.syntax.number = color.palette.darkgray
|
||||
color.fg.plugin.jython.syntax.package = color.palette.darkred
|
||||
color.fg.plugin.jython.syntax.sequence = color.palette.saddlebrown
|
||||
color.fg.plugin.jython.syntax.special = color.palette.darkgreen
|
||||
|
||||
icon.plugin.jython = python.png
|
||||
|
||||
|
||||
|
||||
[Dark Defaults]
|
||||
|
@ -16,7 +16,7 @@ import sys
|
||||
import tokenize
|
||||
import types
|
||||
import __main__
|
||||
from ghidra.python import PythonCodeCompletionFactory
|
||||
from ghidra.jython import JythonCodeCompletionFactory
|
||||
import java # needed for java.lang.Class
|
||||
|
||||
try:
|
||||
@ -72,7 +72,7 @@ def getAutoCompleteList(command='', locals=None, includeMagic=1,
|
||||
pyObj = getattr(object, attribute)
|
||||
else:
|
||||
pyObj = locals[attribute]
|
||||
completion_list.append(PythonCodeCompletionFactory.
|
||||
completion_list.append(JythonCodeCompletionFactory.
|
||||
newCodeCompletion(attribute,
|
||||
attribute,
|
||||
pyObj,
|
@ -8,7 +8,7 @@ import string
|
||||
import __builtin__
|
||||
import java # needed for java.lang.Class
|
||||
import org # for org.python.core
|
||||
import ghidra # for PythonCodeCompletionFactory
|
||||
import ghidra # for JythonCodeCompletionFactory
|
||||
|
||||
__author__ = "Don Coleman <dcoleman@chariotsolutions.com>"
|
||||
|
@ -3,7 +3,7 @@
|
||||
<tocroot>
|
||||
<tocref id="Ghidra Functionality">
|
||||
<tocref id="Scripting">
|
||||
<tocdef id="Python Interpreter" sortgroup="z" text="Python Interpreter" target="help/topics/Python/interpreter.html" />
|
||||
<tocdef id="Jython Interpreter" sortgroup="z" text="Jython Interpreter" target="help/topics/Jython/interpreter.html" />
|
||||
</tocref>
|
||||
</tocref>
|
||||
</tocroot>
|
@ -2,15 +2,15 @@
|
||||
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Python Interpreter</TITLE>
|
||||
<TITLE>Jython Interpreter</TITLE>
|
||||
<LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
|
||||
</HEAD>
|
||||
|
||||
<BODY lang="EN-US">
|
||||
<H1><A name="Python"></A>Python Interpreter</H1>
|
||||
<H1><A name="Jython"></A>Jython Interpreter</H1>
|
||||
|
||||
<P>
|
||||
The Ghidra <I>Python Interpreter</I> provides a full general-purpose Python interactive shell
|
||||
The Ghidra <I>Jython Interpreter</I> provides a full general-purpose Jython interactive shell
|
||||
and allows you to interact with your current Ghidra session by exposing Ghidra's powerful Java
|
||||
API through the magic of Jython.
|
||||
</P>
|
||||
@ -18,7 +18,7 @@
|
||||
<H2>Environment</H2>
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
The Ghidra <I>Python Interpreter</I> is configured to run in a similar context as a Ghidra
|
||||
The Ghidra <I>Jython Interpreter</I> is configured to run in a similar context as a Ghidra
|
||||
script. Therefore, you immediately have access to variables such as <TT>currentProgram</TT>,
|
||||
<TT>currentSelection</TT>, <TT>currentAddress</TT>, etc without needing to import them.
|
||||
These variables exist as Java objects behind the scenes, but Jython allows you to interact with
|
||||
@ -48,7 +48,7 @@
|
||||
hierarchy, so nothing has to be explicitly imported before they can be used. However, because
|
||||
the <TT>DataTypeSelectionDialog</TT> class and <TT>AllowedDataType</TT> enum reside in
|
||||
different packages, they must be explicitly imported. Failure to do so will result in a
|
||||
Python <TT><FONT COLOR="RED">NameError</FONT></TT>.
|
||||
Jython <TT><FONT COLOR="RED">NameError</FONT></TT>.
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
@ -78,7 +78,7 @@
|
||||
<H2>Keybindings</H2>
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
The Ghidra <I>Python Interpreter</I> supports the following hard-coded keybindings:
|
||||
The Ghidra <I>Jython Interpreter</I> supports the following hard-coded keybindings:
|
||||
<UL>
|
||||
<LI><B>(up):</B> Move backward in command stack</LI>
|
||||
<LI><B>(down):</B> Move forward in command stack</LI>
|
||||
@ -100,7 +100,7 @@
|
||||
<H2>Copy/Paste</H2>
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
Copy and paste from within the Ghidra <I>Python Interpreter</I> should work as expected for
|
||||
Copy and paste from within the Ghidra <I>Jython Interpreter</I> should work as expected for
|
||||
your given environment:
|
||||
<UL>
|
||||
<LI><B>Windows:</B> CTRL+C / CTRL+V</LI>
|
||||
@ -113,7 +113,7 @@
|
||||
<H2>API Documentation</H2>
|
||||
<BLOCKQUOTE>
|
||||
<P>
|
||||
The built-in <TT>help()</TT> Python function has been altered by the Ghidra <I>Python Interpreter</I>
|
||||
The built-in <TT>help()</TT> Jython function has been altered by the Ghidra <I>Jython Interpreter</I>
|
||||
to add support for displaying Ghidra's Javadoc (where available) for a given Ghidra class, method,
|
||||
or variable. For example, to see Ghidra's Javadoc on the <TT>state</TT> variable, simply do:
|
||||
<PRE>
|
||||
@ -147,7 +147,7 @@
|
||||
</P>
|
||||
<P>
|
||||
<B>Note:</B> It may be necessary to import a Ghidra class before calling the built-in <TT>help()</TT>
|
||||
Python function on it. Failure to do so will result in a Python <TT><FONT COLOR="RED">NameError</FONT></TT>.
|
||||
Jython function on it. Failure to do so will result in a Jython <TT><FONT COLOR="RED">NameError</FONT></TT>.
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
@ -160,7 +160,7 @@
|
||||
</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P align="left" class="providedbyplugin">Provided by: <I>PythonPlugin</I></P>
|
||||
<P align="left" class="providedbyplugin">Provided by: <I>JythonPlugin</I></P>
|
||||
|
||||
<P> </P>
|
||||
<BR>
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -41,7 +41,7 @@ import util.CollectionUtils;
|
||||
* There is no longer a way to reset an interpreter...it was too complicated to get right.
|
||||
* Instead, you should {@link #cleanup()} your old interpreter and make a new one.
|
||||
*/
|
||||
public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||
public class GhidraJythonInterpreter extends InteractiveInterpreter {
|
||||
|
||||
private static boolean pythonInitialized;
|
||||
private static List<PyString> defaultPythonPath;
|
||||
@ -58,23 +58,23 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||
*
|
||||
* @return A new GhidraPythonInterpreter. Could be null if it failed to be created.
|
||||
*/
|
||||
public static GhidraPythonInterpreter get() {
|
||||
public static GhidraJythonInterpreter get() {
|
||||
|
||||
// Initialize the python environment if necessary. Only needs to happen once.
|
||||
if (!pythonInitialized) {
|
||||
try {
|
||||
// Setup python home directory
|
||||
PythonUtils.setupPythonHomeDir();
|
||||
JythonUtils.setupJythonHomeDir();
|
||||
|
||||
// Setup python cache directory
|
||||
PythonUtils.setupPythonCacheDir(TaskMonitor.DUMMY);
|
||||
JythonUtils.setupJythonCacheDir(TaskMonitor.DUMMY);
|
||||
|
||||
// Indicate that we've initialized the python environment, which should
|
||||
// only happen once.
|
||||
pythonInitialized = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.showError(GhidraPythonInterpreter.class, null, "Python error",
|
||||
Msg.showError(GhidraJythonInterpreter.class, null, "Python error",
|
||||
"Problem getting Ghirda Python interpreter", e);
|
||||
return null;
|
||||
}
|
||||
@ -86,7 +86,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||
state.ps2 = new PyString("... ");
|
||||
|
||||
// Return a new instance of our interpreter
|
||||
return new GhidraPythonInterpreter(state);
|
||||
return new GhidraJythonInterpreter(state);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,7 +94,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||
*
|
||||
* @param state The initial system state of the interpreter.
|
||||
*/
|
||||
private GhidraPythonInterpreter(PySystemState state) {
|
||||
private GhidraJythonInterpreter(PySystemState state) {
|
||||
super(null, state);
|
||||
|
||||
// Store the default python path in case we need to reset it later.
|
||||
@ -158,7 +158,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||
* @throws PyException if an unhandled exception occurred while executing the line of python
|
||||
* @throws IllegalStateException if this interpreter has been cleaned up.
|
||||
*/
|
||||
public synchronized boolean push(String line, PythonScript script)
|
||||
public synchronized boolean push(String line, JythonScript script)
|
||||
throws PyException, IllegalStateException {
|
||||
|
||||
if (cleanedUp) {
|
||||
@ -198,7 +198,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||
* @param script A PythonScript from which we load state (or null).
|
||||
* @throws IllegalStateException if this interpreter has been cleaned up.
|
||||
*/
|
||||
public synchronized void execFile(ResourceFile file, PythonScript script)
|
||||
public synchronized void execFile(ResourceFile file, JythonScript script)
|
||||
throws IllegalStateException {
|
||||
|
||||
if (cleanedUp) {
|
||||
@ -332,7 +332,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||
*
|
||||
* @param script The script whose class hierarchy is to be used for injection.
|
||||
*/
|
||||
void injectScriptHierarchy(PythonScript script) {
|
||||
void injectScriptHierarchy(JythonScript script) {
|
||||
|
||||
if (script == null) {
|
||||
return;
|
||||
@ -447,7 +447,7 @@ public class GhidraPythonInterpreter extends InteractiveInterpreter {
|
||||
* @param includeBuiltins True if we should include python built-ins; otherwise, false.
|
||||
* @param caretPos The position of the caret in the input string 'cmd'
|
||||
* @return A list of possible command completions. Could be empty if there aren't any.
|
||||
* @see PythonPlugin#getCompletions
|
||||
* @see JythonPlugin#getCompletions
|
||||
*/
|
||||
List<CodeCompletion> getCommandCompletions(String cmd, boolean includeBuiltins, int caretPos) {
|
||||
// At this point the caret is assumed to be positioned right after the value we need to
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.lang.reflect.Method;
|
||||
@ -31,12 +31,12 @@ import ghidra.framework.options.Options;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* Generates CodeCompletions from Python objects.
|
||||
* Generates CodeCompletions from Jython objects.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class PythonCodeCompletionFactory {
|
||||
public class JythonCodeCompletionFactory {
|
||||
private static List<Class<?>> classes = new ArrayList<>();
|
||||
private static Map<Class<?>, Color> classToColorMap = new HashMap<>();
|
||||
/* necessary because we only want to show the user the simple class name
|
||||
@ -47,7 +47,7 @@ public class PythonCodeCompletionFactory {
|
||||
private static Map<Class<?>, String> classDescription = new HashMap<>();
|
||||
public static final String COMPLETION_LABEL = "Code Completion Colors";
|
||||
|
||||
/* package-level accessibility so that PythonPlugin can tell this is
|
||||
/* package-level accessibility so that JythonPlugin can tell this is
|
||||
* our option
|
||||
*/
|
||||
final static String INCLUDE_TYPES_LABEL = "Include type names in code completion popup?";
|
||||
@ -59,19 +59,19 @@ public class PythonCodeCompletionFactory {
|
||||
private static boolean includeTypes = INCLUDE_TYPES_DEFAULT;
|
||||
|
||||
//@formatter:off
|
||||
public static final Color NULL_COLOR = new GColor("color.fg.plugin.python.syntax.null");
|
||||
public static final Color FUNCTION_COLOR = new GColor("color.fg.plugin.python.syntax.function");
|
||||
public static final Color PACKAGE_COLOR = new GColor("color.fg.plugin.python.syntax.package");
|
||||
public static final Color CLASS_COLOR = new GColor("color.fg.plugin.python.syntax.class");
|
||||
public static final Color METHOD_COLOR = new GColor("color.fg.plugin.python.syntax.method");
|
||||
public static final Color NULL_COLOR = new GColor("color.fg.plugin.jython.syntax.null");
|
||||
public static final Color FUNCTION_COLOR = new GColor("color.fg.plugin.jython.syntax.function");
|
||||
public static final Color PACKAGE_COLOR = new GColor("color.fg.plugin.jython.syntax.package");
|
||||
public static final Color CLASS_COLOR = new GColor("color.fg.plugin.jython.syntax.class");
|
||||
public static final Color METHOD_COLOR = new GColor("color.fg.plugin.jython.syntax.method");
|
||||
/* anonymous code chunks */
|
||||
public static final Color CODE_COLOR = new GColor("color.fg.plugin.python.syntax.code");
|
||||
public static final Color INSTANCE_COLOR = new GColor("color.fg.plugin.python.syntax.instance");
|
||||
public static final Color SEQUENCE_COLOR = new GColor("color.fg.plugin.python.syntax.sequence");
|
||||
public static final Color MAP_COLOR = new GColor("color.fg.plugin.python.syntax.map");
|
||||
public static final Color NUMBER_COLOR = new GColor("color.fg.plugin.python.syntax.number");
|
||||
public static final Color CODE_COLOR = new GColor("color.fg.plugin.jython.syntax.code");
|
||||
public static final Color INSTANCE_COLOR = new GColor("color.fg.plugin.jython.syntax.instance");
|
||||
public static final Color SEQUENCE_COLOR = new GColor("color.fg.plugin.jython.syntax.sequence");
|
||||
public static final Color MAP_COLOR = new GColor("color.fg.plugin.jython.syntax.map");
|
||||
public static final Color NUMBER_COLOR = new GColor("color.fg.plugin.jython.syntax.number");
|
||||
/* for weird Jython-specific stuff */
|
||||
public static final Color SPECIAL_COLOR = new GColor("color.fg.plugin.python.syntax.special");
|
||||
public static final Color SPECIAL_COLOR = new GColor("color.fg.plugin.jython.syntax.special");
|
||||
//@formatter:on
|
||||
|
||||
static {
|
||||
@ -174,18 +174,18 @@ public class PythonCodeCompletionFactory {
|
||||
classDescription.put(klass, description);
|
||||
}
|
||||
catch (ClassNotFoundException cnfe) {
|
||||
Msg.debug(PythonCodeCompletionFactory.class, "Unable to find class: " + className,
|
||||
Msg.debug(JythonCodeCompletionFactory.class, "Unable to find class: " + className,
|
||||
cnfe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CodeCompletion from the given Python objects.
|
||||
* Creates a new CodeCompletion from the given Jython objects.
|
||||
*
|
||||
* @param description description of the new CodeCompletion
|
||||
* @param insertion what will be inserted to make the code complete
|
||||
* @param pyObj a Python Object
|
||||
* @return A new CodeCompletion from the given Python objects.
|
||||
* @param pyObj a Jython Object
|
||||
* @return A new CodeCompletion from the given Jython objects.
|
||||
* @deprecated use {@link #newCodeCompletion(String, String, PyObject, String)} instead,
|
||||
* it allows creation of substituting code completions
|
||||
*/
|
||||
@ -196,15 +196,15 @@ public class PythonCodeCompletionFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CodeCompletion from the given Python objects.
|
||||
* Creates a new CodeCompletion from the given Jython objects.
|
||||
*
|
||||
* @param description description of the new CodeCompletion
|
||||
* @param insertion what will be inserted to make the code complete
|
||||
* @param pyObj a Python Object
|
||||
* @param pyObj a Jython Object
|
||||
* @param userInput a word we want to complete, can be an empty string.
|
||||
* It's used to determine which part (if any) of the input should be
|
||||
* removed before the insertion of the completion
|
||||
* @return A new CodeCompletion from the given Python objects.
|
||||
* @return A new CodeCompletion from the given Jython objects.
|
||||
*/
|
||||
public static CodeCompletion newCodeCompletion(String description, String insertion,
|
||||
PyObject pyObj, String userInput) {
|
||||
@ -241,11 +241,11 @@ public class PythonCodeCompletionFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up Python code completion Options.
|
||||
* @param plugin python plugin as options owner
|
||||
* Sets up Jython code completion Options.
|
||||
* @param plugin jython plugin as options owner
|
||||
* @param options an Options handle
|
||||
*/
|
||||
public static void setupOptions(PythonPlugin plugin, Options options) {
|
||||
public static void setupOptions(JythonPlugin plugin, Options options) {
|
||||
includeTypes = options.getBoolean(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT);
|
||||
options.registerOption(INCLUDE_TYPES_LABEL, INCLUDE_TYPES_DEFAULT, null,
|
||||
INCLUDE_TYPES_DESCRIPTION);
|
||||
@ -271,20 +271,20 @@ public class PythonCodeCompletionFactory {
|
||||
includeTypes = ((Boolean) newValue).booleanValue();
|
||||
}
|
||||
else {
|
||||
Msg.error(PythonCodeCompletionFactory.class, "unknown option '" + name + "'");
|
||||
Msg.error(JythonCodeCompletionFactory.class, "unknown option '" + name + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Java __call__ methods declared for a Python object.
|
||||
* Returns the Java __call__ methods declared for a Jython object.
|
||||
*
|
||||
* Some Python "methods" in the new-style Python objects are actually
|
||||
* Some Jython "methods" in the new-style Jython objects are actually
|
||||
* classes in and of themselves, re-implementing __call__ methods to
|
||||
* tell us how to call them. This returns an array of those Methods
|
||||
* (for code completion help).
|
||||
*
|
||||
* @param obj a PyObject
|
||||
* @return the Java __call__ methods declared for the Python object
|
||||
* @return the Java __call__ methods declared for the Jython object
|
||||
*/
|
||||
public static Object[] getCallMethods(PyObject obj) {
|
||||
List<Method> callMethodList = new ArrayList<>();
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.*;
|
||||
@ -44,44 +44,44 @@ import ghidra.util.task.*;
|
||||
import resources.Icons;
|
||||
|
||||
/**
|
||||
* This plugin provides the interactive Python interpreter.
|
||||
* This plugin provides the interactive Jython interpreter.
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(
|
||||
status = PluginStatus.RELEASED,
|
||||
packageName = CorePluginPackage.NAME,
|
||||
category = PluginCategoryNames.COMMON,
|
||||
shortDescription = "Python Interpreter",
|
||||
description = "Provides an interactive Python Interpreter that is tightly integrated with a loaded Ghidra program.",
|
||||
shortDescription = "Jython Interpreter",
|
||||
description = "Provides an interactive Jython Interpreter that is tightly integrated with a loaded Ghidra program.",
|
||||
servicesRequired = { InterpreterPanelService.class },
|
||||
isSlowInstallation = true
|
||||
)
|
||||
//@formatter:on
|
||||
public class PythonPlugin extends ProgramPlugin
|
||||
public class JythonPlugin extends ProgramPlugin
|
||||
implements InterpreterConnection, OptionsChangeListener {
|
||||
|
||||
private InterpreterConsole console;
|
||||
private GhidraPythonInterpreter interpreter;
|
||||
private PythonScript interactiveScript;
|
||||
private GhidraJythonInterpreter interpreter;
|
||||
private JythonScript interactiveScript;
|
||||
private TaskMonitor interactiveTaskMonitor;
|
||||
private PythonPluginInputThread inputThread;
|
||||
private JythonPluginInputThread inputThread;
|
||||
|
||||
// Plugin options
|
||||
private final static String INCLUDE_BUILTINS_LABEL = "Include \"builtins\" in code completion?";
|
||||
private final static String INCLUDE_BUILTINS_DESCRIPTION =
|
||||
"Whether or not to include Python's built-in functions and properties in the pop-up code completion window.";
|
||||
"Whether or not to include Jython's built-in functions and properties in the pop-up code completion window.";
|
||||
private final static boolean INCLUDE_BUILTINS_DEFAULT = true;
|
||||
|
||||
private static final Icon ICON = new GIcon("icon.plugin.python");
|
||||
private static final Icon ICON = new GIcon("icon.plugin.jython");
|
||||
|
||||
private boolean includeBuiltins = INCLUDE_BUILTINS_DEFAULT;
|
||||
|
||||
/**
|
||||
* Creates a new PythonPlugin object.
|
||||
* Creates a new {@link JythonPlugin} object.
|
||||
*
|
||||
* @param tool The tool associated with this plugin.
|
||||
*/
|
||||
public PythonPlugin(PluginTool tool) {
|
||||
public JythonPlugin(PluginTool tool) {
|
||||
super(tool);
|
||||
}
|
||||
|
||||
@ -95,11 +95,11 @@ public class PythonPlugin extends ProgramPlugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the plugin's Python interpreter.
|
||||
* Gets the plugin's Jython interpreter.
|
||||
*
|
||||
* @return The plugin's Python interpreter. May be null.
|
||||
* @return The plugin's Jython interpreter. May be null.
|
||||
*/
|
||||
GhidraPythonInterpreter getInterpreter() {
|
||||
GhidraJythonInterpreter getInterpreter() {
|
||||
return interpreter;
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||
*
|
||||
* @return The plugin's interactive script.
|
||||
*/
|
||||
PythonScript getInteractiveScript() {
|
||||
JythonScript getInteractiveScript() {
|
||||
return interactiveScript;
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||
|
||||
/**
|
||||
* Resets the interpreter to a new starting state. This is used when the plugin is first
|
||||
* initialized, as well as when an existing interpreter receives a Python exit command.
|
||||
* initialized, as well as when an existing interpreter receives a Jython exit command.
|
||||
* We used to try to reset the same interpreter, but it was really hard to do that correctly
|
||||
* so we now just create a brand new one.
|
||||
* <p>
|
||||
@ -181,7 +181,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||
*/
|
||||
private void resetInterpreter() {
|
||||
|
||||
TaskLauncher.launchModal("Resetting Python...", () -> {
|
||||
TaskLauncher.launchModal("Resetting Jython...", () -> {
|
||||
resetInterpreterInBackground();
|
||||
});
|
||||
}
|
||||
@ -193,23 +193,23 @@ public class PythonPlugin extends ProgramPlugin
|
||||
if (interpreter == null) {
|
||||
|
||||
// Setup options
|
||||
ToolOptions options = tool.getOptions("Python");
|
||||
ToolOptions options = tool.getOptions("Jython");
|
||||
includeBuiltins = options.getBoolean(INCLUDE_BUILTINS_LABEL, INCLUDE_BUILTINS_DEFAULT);
|
||||
options.registerOption(INCLUDE_BUILTINS_LABEL, INCLUDE_BUILTINS_DEFAULT, null,
|
||||
INCLUDE_BUILTINS_DESCRIPTION);
|
||||
options.addOptionsChangeListener(this);
|
||||
|
||||
interpreter = GhidraPythonInterpreter.get();
|
||||
interpreter = GhidraJythonInterpreter.get();
|
||||
|
||||
// Setup code completion. This currently has to be done after the interpreter
|
||||
// is created. Otherwise an exception will occur.
|
||||
PythonCodeCompletionFactory.setupOptions(this, options);
|
||||
JythonCodeCompletionFactory.setupOptions(this, options);
|
||||
}
|
||||
else {
|
||||
inputThread.shutdown();
|
||||
inputThread = null;
|
||||
interpreter.cleanup();
|
||||
interpreter = GhidraPythonInterpreter.get();
|
||||
interpreter = GhidraJythonInterpreter.get();
|
||||
}
|
||||
|
||||
// Reset the console.
|
||||
@ -224,20 +224,20 @@ public class PythonPlugin extends ProgramPlugin
|
||||
// Print a welcome message.
|
||||
welcome();
|
||||
|
||||
// Setup the PythonScript describing the state of the interactive prompt.
|
||||
// Setup the JythonScript describing the state of the interactive prompt.
|
||||
// This allows things like currentProgram and currentAddress to dynamically reflect
|
||||
// what's happening in the listing. Injecting the script hierarchy early here allows
|
||||
// code completion to work before commands are entered.
|
||||
interactiveScript = new PythonScript();
|
||||
interactiveScript = new JythonScript();
|
||||
interactiveScript.set(
|
||||
new GhidraState(tool, tool.getProject(), getCurrentProgram(), getProgramLocation(),
|
||||
getProgramSelection(), getProgramHighlight()),
|
||||
interactiveTaskMonitor, new PrintWriter(getConsole().getStdOut()));
|
||||
interpreter.injectScriptHierarchy(interactiveScript);
|
||||
interactiveTaskMonitor = new PythonInteractiveTaskMonitor(console.getStdOut());
|
||||
interactiveTaskMonitor = new JythonInteractiveTaskMonitor(console.getStdOut());
|
||||
|
||||
// Start the input thread that receives python commands to execute.
|
||||
inputThread = new PythonPluginInputThread(this);
|
||||
// Start the input thread that receives jython commands to execute.
|
||||
inputThread = new JythonPluginInputThread(this);
|
||||
inputThread.start();
|
||||
}
|
||||
|
||||
@ -252,11 +252,11 @@ public class PythonPlugin extends ProgramPlugin
|
||||
@Override
|
||||
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
|
||||
Object newValue) {
|
||||
if (optionName.startsWith(PythonCodeCompletionFactory.COMPLETION_LABEL)) {
|
||||
PythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue);
|
||||
if (optionName.startsWith(JythonCodeCompletionFactory.COMPLETION_LABEL)) {
|
||||
JythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue);
|
||||
}
|
||||
else if (optionName.equals(PythonCodeCompletionFactory.INCLUDE_TYPES_LABEL)) {
|
||||
PythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue);
|
||||
else if (optionName.equals(JythonCodeCompletionFactory.INCLUDE_TYPES_LABEL)) {
|
||||
JythonCodeCompletionFactory.changeOptions(options, optionName, oldValue, newValue);
|
||||
}
|
||||
else if (optionName.equals(INCLUDE_BUILTINS_LABEL)) {
|
||||
includeBuiltins = ((Boolean) newValue).booleanValue();
|
||||
@ -284,7 +284,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||
@Override
|
||||
public List<CodeCompletion> getCompletions(String cmd, int caretPos) {
|
||||
// Refresh the environment
|
||||
interactiveScript.setSourceFile(new ResourceFile(new File("python")));
|
||||
interactiveScript.setSourceFile(new ResourceFile(new File("jython")));
|
||||
interactiveScript.set(
|
||||
new GhidraState(tool, tool.getProject(), currentProgram, currentLocation,
|
||||
currentSelection, currentHighlight),
|
||||
@ -327,7 +327,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||
if (interpreter == null) {
|
||||
return;
|
||||
}
|
||||
interpreter.interrupt(inputThread.getPythonPluginExecutionThread());
|
||||
interpreter.interrupt(inputThread.getJythonPluginExecutionThread());
|
||||
console.setPrompt(interpreter.getPrimaryPrompt());
|
||||
}
|
||||
|
||||
@ -344,7 +344,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Python";
|
||||
return "Jython";
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -361,7 +361,7 @@ public class PythonPlugin extends ProgramPlugin
|
||||
* Prints a welcome message to the console.
|
||||
*/
|
||||
private void welcome() {
|
||||
console.getOutWriter().println("Python Interpreter for Ghidra");
|
||||
console.getOutWriter().println("Jython Interpreter for Ghidra");
|
||||
console.getOutWriter().println("Based on Jython version " + PySystemState.version);
|
||||
console.getOutWriter().println("Press 'F1' for usage instructions");
|
||||
}
|
||||
@ -369,20 +369,20 @@ public class PythonPlugin extends ProgramPlugin
|
||||
/**
|
||||
* Support for cancelling execution using a TaskMonitor.
|
||||
*/
|
||||
class PythonInteractiveTaskMonitor extends TaskMonitorAdapter {
|
||||
class JythonInteractiveTaskMonitor extends TaskMonitorAdapter {
|
||||
private PrintWriter output = null;
|
||||
|
||||
public PythonInteractiveTaskMonitor(PrintWriter stdOut) {
|
||||
public JythonInteractiveTaskMonitor(PrintWriter stdOut) {
|
||||
output = stdOut;
|
||||
}
|
||||
|
||||
public PythonInteractiveTaskMonitor(OutputStream stdout) {
|
||||
public JythonInteractiveTaskMonitor(OutputStream stdout) {
|
||||
this(new PrintWriter(stdout));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessage(String message) {
|
||||
output.println("<python-interactive>: " + message);
|
||||
output.println("<jython-interactive>: " + message);
|
||||
}
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
@ -29,23 +29,24 @@ import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* Thread responsible for executing a python command for the plugin.
|
||||
* Thread responsible for executing a jython command for the plugin.
|
||||
*/
|
||||
class PythonPluginExecutionThread extends Thread {
|
||||
class JythonPluginExecutionThread extends Thread {
|
||||
|
||||
private PythonPlugin plugin;
|
||||
private JythonPlugin plugin;
|
||||
private String cmd;
|
||||
private AtomicBoolean moreInputWanted;
|
||||
|
||||
/**
|
||||
* Creates a new python plugin execution thread that executes the given command for the given plugin.
|
||||
* Creates a new jython plugin execution thread that executes the given command for the given
|
||||
* plugin.
|
||||
*
|
||||
* @param plugin The python plugin to execute the command for.
|
||||
* @param cmd The python command to execute.
|
||||
* @param plugin The jython plugin to execute the command for.
|
||||
* @param cmd The jython command to execute.
|
||||
* @param moreInputWanted Gets set to indicate that the executed command expects more input.
|
||||
*/
|
||||
PythonPluginExecutionThread(PythonPlugin plugin, String cmd, AtomicBoolean moreInputWanted) {
|
||||
super("Python plugin execution thread");
|
||||
JythonPluginExecutionThread(JythonPlugin plugin, String cmd, AtomicBoolean moreInputWanted) {
|
||||
super("Jython plugin execution thread");
|
||||
|
||||
this.plugin = plugin;
|
||||
this.cmd = cmd;
|
||||
@ -56,14 +57,14 @@ class PythonPluginExecutionThread extends Thread {
|
||||
public void run() {
|
||||
|
||||
TaskMonitor interactiveTaskMonitor = plugin.getInteractiveTaskMonitor();
|
||||
PythonScript interactiveScript = plugin.getInteractiveScript();
|
||||
JythonScript interactiveScript = plugin.getInteractiveScript();
|
||||
Program program = plugin.getCurrentProgram();
|
||||
|
||||
// Setup transaction for the execution.
|
||||
try (Transaction tx = program != null ? program.openTransaction("Python command") : null) {
|
||||
try (Transaction tx = program != null ? program.openTransaction("Jython command") : null) {
|
||||
// Setup Ghidra state to be passed into interpreter
|
||||
interactiveTaskMonitor.clearCancelled();
|
||||
interactiveScript.setSourceFile(new ResourceFile(new File("python")));
|
||||
interactiveScript.setSourceFile(new ResourceFile(new File("jython")));
|
||||
PluginTool tool = plugin.getTool();
|
||||
interactiveScript.set(
|
||||
new GhidraState(tool, tool.getProject(), program, plugin.getProgramLocation(),
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@ -21,37 +21,37 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* Thread responsible for getting interactive lines of python from the plugin.
|
||||
* This class also kicks off the execution of that line in a new {@link PythonPluginExecutionThread}.
|
||||
* Thread responsible for getting interactive lines of jython from the plugin.
|
||||
* This class also kicks off the execution of that line in a new {@link JythonPluginExecutionThread}.
|
||||
*/
|
||||
class PythonPluginInputThread extends Thread {
|
||||
class JythonPluginInputThread extends Thread {
|
||||
|
||||
private static int generationCount = 0;
|
||||
|
||||
private final PythonPlugin plugin;
|
||||
private final JythonPlugin plugin;
|
||||
private final AtomicBoolean moreInputWanted = new AtomicBoolean(false);
|
||||
private final AtomicBoolean shutdownRequested = new AtomicBoolean(false);
|
||||
private final InputStream consoleStdin;
|
||||
private PythonPluginExecutionThread pythonExecutionThread;
|
||||
private JythonPluginExecutionThread jythonExecutionThread;
|
||||
|
||||
/**
|
||||
* Creates a new python input thread that gets a line of python input from the given plugin.
|
||||
* Creates a new jython input thread that gets a line of jython input from the given plugin.
|
||||
*
|
||||
* @param plugin The python plugin to get input from.
|
||||
* @param plugin The jython plugin to get input from.
|
||||
*/
|
||||
PythonPluginInputThread(PythonPlugin plugin) {
|
||||
super("Python plugin input thread (generation " + ++generationCount + ")");
|
||||
JythonPluginInputThread(JythonPlugin plugin) {
|
||||
super("Jython plugin input thread (generation " + ++generationCount + ")");
|
||||
this.plugin = plugin;
|
||||
this.consoleStdin = plugin.getConsole().getStdin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last python plugin execution thread that ran.
|
||||
* Gets the last jython plugin execution thread that ran.
|
||||
*
|
||||
* @return The last python plugin execution thread that ran. Could be null if one never ran.
|
||||
* @return The last jython plugin execution thread that ran. Could be null if one never ran.
|
||||
*/
|
||||
PythonPluginExecutionThread getPythonPluginExecutionThread() {
|
||||
return pythonExecutionThread;
|
||||
JythonPluginExecutionThread getJythonPluginExecutionThread() {
|
||||
return jythonExecutionThread;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -61,13 +61,13 @@ class PythonPluginInputThread extends Thread {
|
||||
while (!shutdownRequested.get() && (line = reader.readLine()) != null) {
|
||||
|
||||
// Execute the line in a new thread
|
||||
pythonExecutionThread =
|
||||
new PythonPluginExecutionThread(plugin, line, moreInputWanted);
|
||||
pythonExecutionThread.start();
|
||||
jythonExecutionThread =
|
||||
new JythonPluginExecutionThread(plugin, line, moreInputWanted);
|
||||
jythonExecutionThread.start();
|
||||
|
||||
try {
|
||||
// Wait for the execution to finish
|
||||
pythonExecutionThread.join();
|
||||
jythonExecutionThread.join();
|
||||
}
|
||||
catch (InterruptedException ie) {
|
||||
// Hey we're back... a little earlier than expected, but there must be a reason.
|
||||
@ -82,7 +82,7 @@ class PythonPluginInputThread extends Thread {
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.error(PythonPluginInputThread.class,
|
||||
Msg.error(JythonPluginInputThread.class,
|
||||
"Internal error reading commands from interpreter console. Please reset the interpreter.",
|
||||
e);
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -28,7 +28,7 @@ import ghidra.util.exception.CancelledException;
|
||||
/**
|
||||
* Launcher entry point for running Ghidra from within Jython.
|
||||
*/
|
||||
public class PythonRun implements GhidraLaunchable {
|
||||
public class JythonRun implements GhidraLaunchable {
|
||||
|
||||
@Override
|
||||
public void launch(GhidraApplicationLayout layout, String[] args) {
|
||||
@ -37,25 +37,25 @@ public class PythonRun implements GhidraLaunchable {
|
||||
ApplicationConfiguration configuration = new HeadlessGhidraApplicationConfiguration();
|
||||
Application.initializeApplication(layout, configuration);
|
||||
|
||||
// Setup python home directory
|
||||
// Setup jython home directory
|
||||
try {
|
||||
PythonUtils.setupPythonHomeDir();
|
||||
JythonUtils.setupJythonHomeDir();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.showError(PythonRun.class, null, "Python home directory", e.getMessage());
|
||||
Msg.showError(JythonRun.class, null, "Jython home directory", e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Setup python cache directory
|
||||
// Setup jython cache directory
|
||||
try {
|
||||
PythonUtils.setupPythonCacheDir(configuration.getTaskMonitor());
|
||||
JythonUtils.setupJythonCacheDir(configuration.getTaskMonitor());
|
||||
}
|
||||
catch (IOException e) {
|
||||
Msg.showError(PythonRun.class, null, "Python cache directory", e.getMessage());
|
||||
Msg.showError(JythonRun.class, null, "Jython cache directory", e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
Msg.showError(PythonRun.class, null, "Operation cancelled", e.getMessage());
|
||||
Msg.showError(JythonRun.class, null, "Operation cancelled", e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@ -25,11 +25,11 @@ import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.util.exception.AssertException;
|
||||
|
||||
/**
|
||||
* A Python version of a {@link GhidraScript}.
|
||||
* A Jython version of a {@link GhidraScript}.
|
||||
*/
|
||||
public class PythonScript extends GhidraScript {
|
||||
public class JythonScript extends GhidraScript {
|
||||
|
||||
static final String PYTHON_INTERPRETER = "ghidra.python.interpreter";
|
||||
static final String JYTHON_INTERPRETER = "ghidra.jython.interpreter";
|
||||
|
||||
private AtomicBoolean interpreterRunning = new AtomicBoolean();
|
||||
|
||||
@ -37,10 +37,10 @@ public class PythonScript extends GhidraScript {
|
||||
public void run() {
|
||||
|
||||
// Try to get the interpreter from an existing script state.
|
||||
GhidraPythonInterpreter interpreter =
|
||||
(GhidraPythonInterpreter) state.getEnvironmentVar(PYTHON_INTERPRETER);
|
||||
GhidraJythonInterpreter interpreter =
|
||||
(GhidraJythonInterpreter) state.getEnvironmentVar(JYTHON_INTERPRETER);
|
||||
|
||||
// Are we being called from an already running PythonScript with existing state?
|
||||
// Are we being called from an already running JythonScript with existing state?
|
||||
if (interpreter != null) {
|
||||
runInExistingEnvironment(interpreter);
|
||||
}
|
||||
@ -51,12 +51,12 @@ public class PythonScript extends GhidraScript {
|
||||
|
||||
@Override
|
||||
public void runScript(String scriptName, GhidraState scriptState) throws Exception {
|
||||
GhidraPythonInterpreter interpreter =
|
||||
(GhidraPythonInterpreter) state.getEnvironmentVar(PYTHON_INTERPRETER);
|
||||
GhidraJythonInterpreter interpreter =
|
||||
(GhidraJythonInterpreter) state.getEnvironmentVar(JYTHON_INTERPRETER);
|
||||
if (interpreter == null) {
|
||||
interpreter = GhidraPythonInterpreter.get();
|
||||
interpreter = GhidraJythonInterpreter.get();
|
||||
if (interpreter == null) {
|
||||
throw new AssertException("Could not get Ghidra Python interpreter!");
|
||||
throw new AssertException("Could not get Ghidra Jython interpreter!");
|
||||
}
|
||||
}
|
||||
ResourceFile scriptSource = GhidraScriptUtil.findScriptByName(scriptName);
|
||||
@ -71,10 +71,10 @@ public class PythonScript extends GhidraScript {
|
||||
updateStateFromVariables();
|
||||
}
|
||||
|
||||
if (ghidraScript instanceof PythonScript) {
|
||||
if (ghidraScript instanceof JythonScript) {
|
||||
ghidraScript.set(scriptState, monitor, writer);
|
||||
PythonScript pythonScript = (PythonScript) ghidraScript;
|
||||
interpreter.execFile(pythonScript.getSourceFile(), pythonScript);
|
||||
JythonScript jythonScript = (JythonScript) ghidraScript;
|
||||
interpreter.execFile(jythonScript.getSourceFile(), jythonScript);
|
||||
}
|
||||
else {
|
||||
ghidraScript.execute(scriptState, monitor, writer);
|
||||
@ -93,7 +93,7 @@ public class PythonScript extends GhidraScript {
|
||||
*
|
||||
* @param interpreter The existing interpreter to execute from.
|
||||
*/
|
||||
private void runInExistingEnvironment(GhidraPythonInterpreter interpreter) {
|
||||
private void runInExistingEnvironment(GhidraJythonInterpreter interpreter) {
|
||||
interpreter.execFile(sourceFile, this);
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ public class PythonScript extends GhidraScript {
|
||||
private void runInNewEnvironment() {
|
||||
|
||||
// Create new interpreter and stick it in the script's state.
|
||||
final GhidraPythonInterpreter interpreter = GhidraPythonInterpreter.get();
|
||||
final GhidraJythonInterpreter interpreter = GhidraJythonInterpreter.get();
|
||||
final PrintWriter stdout = getStdOut();
|
||||
final PrintWriter stderr = getStdErr();
|
||||
interpreter.setOut(stdout);
|
||||
@ -114,11 +114,11 @@ public class PythonScript extends GhidraScript {
|
||||
// script will use the same interpreter. It is questionable whether or not we should do
|
||||
// this (the new script will get all of the old script's variables), but changing it now
|
||||
// could break people's scripts if they expect this behavior.
|
||||
state.addEnvironmentVar(PYTHON_INTERPRETER, interpreter);
|
||||
state.addEnvironmentVar(JYTHON_INTERPRETER, interpreter);
|
||||
|
||||
// Execute the script in a new thread.
|
||||
PythonScriptExecutionThread executionThread =
|
||||
new PythonScriptExecutionThread(this, interpreter, interpreterRunning);
|
||||
JythonScriptExecutionThread executionThread =
|
||||
new JythonScriptExecutionThread(this, interpreter, interpreterRunning);
|
||||
interpreterRunning.set(true);
|
||||
executionThread.start();
|
||||
|
||||
@ -139,7 +139,7 @@ public class PythonScript extends GhidraScript {
|
||||
// Cleanup the interpreter, and remove it from the state (once it's cleaned it cannot be
|
||||
// reused)
|
||||
interpreter.cleanup();
|
||||
state.removeEnvironmentVar(PYTHON_INTERPRETER);
|
||||
state.removeEnvironmentVar(JYTHON_INTERPRETER);
|
||||
}
|
||||
|
||||
private PrintWriter getStdOut() {
|
||||
@ -175,6 +175,6 @@ public class PythonScript extends GhidraScript {
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return "Python";
|
||||
return "Jython";
|
||||
}
|
||||
}
|
@ -13,31 +13,31 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.python.core.PyException;
|
||||
|
||||
/**
|
||||
* Thread responsible for executing a python script from a file.
|
||||
* Thread responsible for executing a jython script from a file.
|
||||
*/
|
||||
class PythonScriptExecutionThread extends Thread {
|
||||
class JythonScriptExecutionThread extends Thread {
|
||||
|
||||
private PythonScript script;
|
||||
private GhidraPythonInterpreter interpreter;
|
||||
private JythonScript script;
|
||||
private GhidraJythonInterpreter interpreter;
|
||||
private AtomicBoolean interpreterRunning;
|
||||
|
||||
/**
|
||||
* Creates a new python script execution thread that executes the given python script.
|
||||
* Creates a new jython script execution thread that executes the given jython script.
|
||||
*
|
||||
* @param script The python script to execute.
|
||||
* @param interpreter The python interpreter to use for execution.
|
||||
* @param script The jython script to execute.
|
||||
* @param interpreter The jython interpreter to use for execution.
|
||||
* @param interpreterRunning Gets set to indicate whether or not the interpreter is still running the script.
|
||||
*/
|
||||
PythonScriptExecutionThread(PythonScript script, GhidraPythonInterpreter interpreter,
|
||||
JythonScriptExecutionThread(JythonScript script, GhidraJythonInterpreter interpreter,
|
||||
AtomicBoolean interpreterRunning) {
|
||||
super("Python script execution thread");
|
||||
super("Jython script execution thread");
|
||||
|
||||
this.script = script;
|
||||
this.interpreter = interpreter;
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.regex.Pattern;
|
||||
@ -21,7 +21,7 @@ import java.util.regex.Pattern;
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.app.script.*;
|
||||
|
||||
public class PythonScriptProvider extends GhidraScriptProvider {
|
||||
public class JythonScriptProvider extends GhidraScriptProvider {
|
||||
|
||||
private static final Pattern BLOCK_COMMENT = Pattern.compile("'''");
|
||||
|
||||
@ -39,9 +39,9 @@ public class PythonScriptProvider extends GhidraScriptProvider {
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>
|
||||
* In Python this is a triple single quote sequence, "'''".
|
||||
* In Jython this is a triple single quote sequence, "'''".
|
||||
*
|
||||
* @return the Pattern for Python block comment openings
|
||||
* @return the Pattern for Jython block comment openings
|
||||
*/
|
||||
@Override
|
||||
public Pattern getBlockCommentStart() {
|
||||
@ -52,9 +52,9 @@ public class PythonScriptProvider extends GhidraScriptProvider {
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>
|
||||
* In Python this is a triple single quote sequence, "'''".
|
||||
* In Jython this is a triple single quote sequence, "'''".
|
||||
*
|
||||
* @return the Pattern for Python block comment openings
|
||||
* @return the Pattern for Jython block comment openings
|
||||
*/
|
||||
@Override
|
||||
public Pattern getBlockCommentEnd() {
|
||||
@ -83,7 +83,7 @@ public class PythonScriptProvider extends GhidraScriptProvider {
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Python";
|
||||
return "Jython";
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -96,7 +96,7 @@ public class PythonScriptProvider extends GhidraScriptProvider {
|
||||
throws GhidraScriptLoadException {
|
||||
|
||||
try {
|
||||
Class<?> clazz = Class.forName(PythonScript.class.getName());
|
||||
Class<?> clazz = Class.forName(JythonScript.class.getName());
|
||||
GhidraScript script = (GhidraScript) clazz.getConstructor().newInstance();
|
||||
script.setSourceFile(sourceFile);
|
||||
return script;
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
@ -25,83 +25,83 @@ import utilities.util.FileUtilities;
|
||||
/**
|
||||
* Python utility method class.
|
||||
*/
|
||||
public class PythonUtils {
|
||||
public class JythonUtils {
|
||||
|
||||
public static final String PYTHON_NAME = "jython-2.7.3";
|
||||
public static final String PYTHON_CACHEDIR = "jython_cachedir";
|
||||
public static final String PYTHON_SRC = "python-src";
|
||||
public static final String JYTHON_NAME = "jython-2.7.3";
|
||||
public static final String JYTHON_CACHEDIR = "jython_cachedir";
|
||||
public static final String JYTHON_SRC = "jython-src";
|
||||
|
||||
/**
|
||||
* Sets up the python home directory. This is the directory that has the "Lib" directory in it.
|
||||
* Sets up the jython home directory. This is the directory that has the "Lib" directory in it.
|
||||
*
|
||||
* @return The python home directory.
|
||||
* @return The jython home directory.
|
||||
* @throws IOException If there was a disk-related problem setting up the home directory.
|
||||
*/
|
||||
public static File setupPythonHomeDir() throws IOException {
|
||||
public static File setupJythonHomeDir() throws IOException {
|
||||
|
||||
File pythonModuleDir = Application.getMyModuleRootDirectory().getFile(false);
|
||||
File pythonHomeDir =
|
||||
Application.getModuleDataSubDirectory(pythonModuleDir.getName(), PYTHON_NAME).getFile(
|
||||
false);
|
||||
File jythonModuleDir = Application.getMyModuleRootDirectory().getFile(false);
|
||||
File jythonHomeDir =
|
||||
Application.getModuleDataSubDirectory(jythonModuleDir.getName(), JYTHON_NAME)
|
||||
.getFile(false);
|
||||
|
||||
if (!pythonHomeDir.exists()) {
|
||||
throw new IOException("Failed to find the python home directory at: " + pythonHomeDir);
|
||||
if (!jythonHomeDir.exists()) {
|
||||
throw new IOException("Failed to find the jython home directory at: " + jythonHomeDir);
|
||||
}
|
||||
|
||||
System.setProperty("python.home", pythonHomeDir.getAbsolutePath());
|
||||
System.setProperty("jython.home", jythonHomeDir.getAbsolutePath());
|
||||
|
||||
return pythonHomeDir;
|
||||
return jythonHomeDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the python cache directory. This is a temporary space that python source files
|
||||
* Sets up the jython cache directory. This is a temporary space that jython source files
|
||||
* get compiled to and cached. It should NOT be in the Ghidra installation directory, because
|
||||
* some installations will not have the appropriate directory permissions to create new files in.
|
||||
*
|
||||
* @param monitor A monitor to use during the cache directory setup.
|
||||
* @return The python cache directory.
|
||||
* @return The jython cache directory.
|
||||
* @throws IOException If there was a disk-related problem setting up the cache directory.
|
||||
* @throws CancelledException If the user cancelled the setup.
|
||||
*/
|
||||
public static File setupPythonCacheDir(TaskMonitor monitor)
|
||||
public static File setupJythonCacheDir(TaskMonitor monitor)
|
||||
throws CancelledException, IOException {
|
||||
|
||||
File devDir = new File(Application.getUserSettingsDirectory(), "dev");
|
||||
File cacheDir = new File(devDir, PYTHON_CACHEDIR);
|
||||
File cacheDir = new File(devDir, JYTHON_CACHEDIR);
|
||||
if (!FileUtilities.mkdirs(cacheDir)) {
|
||||
throw new IOException("Failed to create the python cache directory at: " + cacheDir);
|
||||
throw new IOException("Failed to create the jython cache directory at: " + cacheDir);
|
||||
}
|
||||
|
||||
File pythonSrcDestDir = new File(cacheDir, PYTHON_SRC);
|
||||
if (!FileUtilities.createDir(pythonSrcDestDir)) {
|
||||
File jythonSrcDestDir = new File(cacheDir, JYTHON_SRC);
|
||||
if (!FileUtilities.createDir(jythonSrcDestDir)) {
|
||||
throw new IOException(
|
||||
"Failed to create the " + PYTHON_SRC + " directory at: " + pythonSrcDestDir);
|
||||
"Failed to create the " + JYTHON_SRC + " directory at: " + jythonSrcDestDir);
|
||||
}
|
||||
|
||||
File pythonModuleDir = Application.getMyModuleRootDirectory().getFile(false);
|
||||
File pythonSrcDir = new File(pythonModuleDir, PYTHON_SRC);
|
||||
if (!pythonSrcDir.exists()) {
|
||||
File jythonModuleDir = Application.getMyModuleRootDirectory().getFile(false);
|
||||
File jythonSrcDir = new File(jythonModuleDir, JYTHON_SRC);
|
||||
if (!jythonSrcDir.exists()) {
|
||||
try {
|
||||
pythonSrcDir = Application.getModuleDataSubDirectory(pythonModuleDir.getName(),
|
||||
PYTHON_SRC).getFile(false);
|
||||
jythonSrcDir = Application.getModuleDataSubDirectory(jythonModuleDir.getName(),
|
||||
JYTHON_SRC).getFile(false);
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
throw new IOException("Failed to find the module's " + PYTHON_SRC + " directory");
|
||||
throw new IOException("Failed to find the module's " + JYTHON_SRC + " directory");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtilities.copyDir(pythonSrcDir, pythonSrcDestDir, f -> f.getName().endsWith(".py"),
|
||||
FileUtilities.copyDir(jythonSrcDir, jythonSrcDestDir, f -> f.getName().endsWith(".py"),
|
||||
monitor);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IOException(
|
||||
"Failed to copy " + PYTHON_SRC + " files to: " + pythonSrcDestDir);
|
||||
"Failed to copy " + JYTHON_SRC + " files to: " + jythonSrcDestDir);
|
||||
}
|
||||
|
||||
System.setProperty("python.cachedir.skip", "false");
|
||||
System.setProperty("python.cachedir", cacheDir.getAbsolutePath());
|
||||
System.setProperty("python.path", pythonSrcDestDir.getAbsolutePath());
|
||||
System.setProperty("python.path", jythonSrcDestDir.getAbsolutePath());
|
||||
|
||||
return cacheDir;
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import java.io.File;
|
||||
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@ -36,7 +36,7 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
/**
|
||||
* Tests for the Ghidra Python Interpreter's code completion functionality.
|
||||
*/
|
||||
public class PythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
public class JythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private String simpleTestProgram = """
|
||||
my_int = 32
|
||||
@ -68,13 +68,13 @@ public class PythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTes
|
||||
@Rule
|
||||
public TemporaryFolder tempScriptFolder = new TemporaryFolder();
|
||||
|
||||
private GhidraPythonInterpreter interpreter;
|
||||
private GhidraJythonInterpreter interpreter;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
GhidraScriptUtil.initialize(new BundleHost(), null);
|
||||
interpreter = GhidraPythonInterpreter.get();
|
||||
executePythonProgram(simpleTestProgram);
|
||||
interpreter = GhidraJythonInterpreter.get();
|
||||
executeJythonProgram(simpleTestProgram);
|
||||
}
|
||||
|
||||
@After
|
||||
@ -160,7 +160,7 @@ public class PythonCodeCompletionTest extends AbstractGhidraHeadedIntegrationTes
|
||||
return interpreter.getCommandCompletions(command, false, caretPos);
|
||||
}
|
||||
|
||||
private void executePythonProgram(String code) {
|
||||
private void executeJythonProgram(String code) {
|
||||
try {
|
||||
File tempFile = tempScriptFolder.newFile();
|
||||
FileUtils.writeStringToFile(tempFile, code, Charset.defaultCharset());
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@ -29,16 +29,16 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
/**
|
||||
* Tests the Ghidra python interpreter's functionality.
|
||||
*/
|
||||
public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
public class JythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private ByteArrayOutputStream out;
|
||||
private GhidraPythonInterpreter interpreter;
|
||||
private GhidraJythonInterpreter interpreter;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
out = new ByteArrayOutputStream();
|
||||
GhidraScriptUtil.initialize(new BundleHost(), null);
|
||||
interpreter = GhidraPythonInterpreter.get();
|
||||
interpreter = GhidraJythonInterpreter.get();
|
||||
interpreter.setOut(out);
|
||||
interpreter.setErr(out);
|
||||
}
|
||||
@ -54,7 +54,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
* Tests that the interpreter's "push" method is working by executing a simple line of python.
|
||||
*/
|
||||
@Test
|
||||
public void testPythonPush() {
|
||||
public void testJythonPush() {
|
||||
final String str = "hi";
|
||||
interpreter.push("print \"" + str + "\"", null);
|
||||
assertEquals(out.toString().trim(), str);
|
||||
@ -64,7 +64,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
* Tests that the interpreter's "execFile" method is working by executing a simple file of python.
|
||||
*/
|
||||
@Test
|
||||
public void testPythonExecFile() {
|
||||
public void testJythonExecFile() {
|
||||
interpreter.execFile(new ResourceFile("ghidra_scripts/python_basics.py"), null);
|
||||
assertTrue(out.toString().contains("Snoopy"));
|
||||
}
|
||||
@ -74,7 +74,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
* that we install from there.
|
||||
*/
|
||||
@Test
|
||||
public void testPythonSiteCustomize() {
|
||||
public void testJythonSiteCustomize() {
|
||||
interpreter.push("help", null);
|
||||
assertTrue(out.toString().contains("Press 'F1'"));
|
||||
}
|
||||
@ -83,7 +83,7 @@ public class PythonInterpreterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
* Tests that cleaning the interpreter invalidates it.
|
||||
*/
|
||||
@Test
|
||||
public void testPythonCleanupInvalidation() {
|
||||
public void testJythonCleanupInvalidation() {
|
||||
interpreter.cleanup();
|
||||
|
||||
try {
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@ -28,19 +28,19 @@ import ghidra.test.TestEnv;
|
||||
/**
|
||||
* Tests the Python Plugin functionality.
|
||||
*/
|
||||
public class PythonPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
public class JythonPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private TestEnv env;
|
||||
private PluginTool tool;
|
||||
private PythonPlugin plugin;
|
||||
private JythonPlugin plugin;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
env = new TestEnv();
|
||||
tool = env.getTool();
|
||||
GhidraScriptUtil.initialize(new BundleHost(), null);
|
||||
tool.addPlugin(PythonPlugin.class.getName());
|
||||
plugin = env.getPlugin(PythonPlugin.class);
|
||||
tool.addPlugin(JythonPlugin.class.getName());
|
||||
plugin = env.getPlugin(JythonPlugin.class);
|
||||
}
|
||||
|
||||
@After
|
||||
@ -53,10 +53,10 @@ public class PythonPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
* Tests that issuing a reset from the plugin resets the interpreter.
|
||||
*/
|
||||
@Test
|
||||
public void testPythonPluginReset() {
|
||||
GhidraPythonInterpreter origInterpreter = plugin.getInterpreter();
|
||||
public void testJythonPluginReset() {
|
||||
GhidraJythonInterpreter origInterpreter = plugin.getInterpreter();
|
||||
plugin.reset();
|
||||
GhidraPythonInterpreter newInterpreter = plugin.getInterpreter();
|
||||
GhidraJythonInterpreter newInterpreter = plugin.getInterpreter();
|
||||
assertNotSame(origInterpreter, newInterpreter);
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@ -31,7 +31,7 @@ import ghidra.app.script.GhidraScriptUtil;
|
||||
import ghidra.app.script.ScriptInfo;
|
||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
|
||||
public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
public class JythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@ -48,7 +48,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetailedPythonScript() {
|
||||
public void testDetailedJythonScript() {
|
||||
String descLine1 = "This script exists to check that the info on";
|
||||
String descLine2 = "a script that has extensive documentation is";
|
||||
String descLine3 = "properly parsed and represented.";
|
||||
@ -99,7 +99,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPythonScriptWithBlockComment() {
|
||||
public void testJythonScriptWithBlockComment() {
|
||||
String description = "Script with a block comment at the top.";
|
||||
String category = "Test";
|
||||
ResourceFile scriptFile = null;
|
||||
@ -129,7 +129,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPythonScriptWithBlockCommentAndCertifyHeader() {
|
||||
public void testJythonScriptWithBlockCommentAndCertifyHeader() {
|
||||
String description = "Script with a block comment at the top.";
|
||||
String category = "Test";
|
||||
ResourceFile scriptFile = null;
|
||||
@ -168,7 +168,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPythonScriptWithoutBlockComment() {
|
||||
public void testJythonScriptWithoutBlockComment() {
|
||||
String description = "Script without a block comment at the top.";
|
||||
String category = "Test";
|
||||
ResourceFile scriptFile = null;
|
||||
@ -194,7 +194,7 @@ public class PythonScriptInfoTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPythonScriptWithSingleLineBlockComment() {
|
||||
public void testJythonScriptWithSingleLineBlockComment() {
|
||||
String description = "Script with a block comment at the top.";
|
||||
String category = "Test";
|
||||
ResourceFile scriptFile = null;
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.python;
|
||||
package ghidra.jython;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@ -37,7 +37,7 @@ import ghidra.util.task.TaskMonitor;
|
||||
/**
|
||||
* Tests the Python script functionality.
|
||||
*/
|
||||
public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
public class JythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private TestEnv env;
|
||||
private PluginTool tool;
|
||||
@ -59,19 +59,19 @@ public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that Python scripts are running correctly.
|
||||
* Tests that Jython scripts are running correctly.
|
||||
*
|
||||
* @throws Exception If an exception occurred while trying to run the script.
|
||||
*/
|
||||
@Test
|
||||
public void testPythonScript() throws Exception {
|
||||
public void testJythonScript() throws Exception {
|
||||
String script = "ghidra_scripts/python_basics.py";
|
||||
try {
|
||||
String output = runPythonScript(Application.getModuleFile("Python", script));
|
||||
String output = runPythonScript(Application.getModuleFile("Jython", script));
|
||||
assertTrue(output.contains("Snoopy"));
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
fail("Could not find python script: " + script);
|
||||
fail("Could not find jython script: " + script);
|
||||
}
|
||||
catch (Exception e) {
|
||||
fail("Exception occurred trying to run script: " + e.getMessage());
|
||||
@ -79,18 +79,18 @@ public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that Python scripts are running correctly.
|
||||
* Tests that Jython scripts are running correctly.
|
||||
*
|
||||
* @throws Exception If an exception occurred while trying to run the script.
|
||||
*/
|
||||
@Test
|
||||
public void testPythonInterpreterGoneFromState() throws Exception {
|
||||
public void testJythonInterpreterGoneFromState() throws Exception {
|
||||
String script = "ghidra_scripts/python_basics.py";
|
||||
try {
|
||||
GhidraState state =
|
||||
new GhidraState(env.getTool(), env.getProject(), null, null, null, null);
|
||||
runPythonScript(Application.getModuleFile("Python", script), state);
|
||||
assertTrue(state.getEnvironmentVar(PythonScript.PYTHON_INTERPRETER) == null);
|
||||
runPythonScript(Application.getModuleFile("Jython", script), state);
|
||||
assertTrue(state.getEnvironmentVar(JythonScript.JYTHON_INTERPRETER) == null);
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
fail("Could not find python script: " + script);
|
||||
@ -125,9 +125,9 @@ public class PythonScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
runSwing(() -> console.clearMessages());
|
||||
|
||||
PythonScriptProvider scriptProvider = new PythonScriptProvider();
|
||||
JythonScriptProvider scriptProvider = new JythonScriptProvider();
|
||||
PrintWriter writer = new PrintWriter(new ByteArrayOutputStream());
|
||||
PythonScript script = (PythonScript) scriptProvider.getScriptInstance(scriptFile, writer);
|
||||
JythonScript script = (JythonScript) scriptProvider.getScriptInstance(scriptFile, writer);
|
||||
script.set(state, TaskMonitor.DUMMY, writer);
|
||||
script.run();
|
||||
|
@ -1,21 +0,0 @@
|
||||
|
||||
[Defaults]
|
||||
|
||||
color.fg.plugin.python.syntax.class = color.palette.blue
|
||||
color.fg.plugin.python.syntax.code = color.palette.darkgreen
|
||||
color.fg.plugin.python.syntax.function = color.palette.green
|
||||
color.fg.plugin.python.syntax.instance = color.palette.purple
|
||||
color.fg.plugin.python.syntax.map = color.palette.steelblue
|
||||
color.fg.plugin.python.syntax.method = color.palette.teal
|
||||
color.fg.plugin.python.syntax.null = color.palette.red
|
||||
color.fg.plugin.python.syntax.number = color.palette.darkgray
|
||||
color.fg.plugin.python.syntax.package = color.palette.darkred
|
||||
color.fg.plugin.python.syntax.sequence = color.palette.saddlebrown
|
||||
color.fg.plugin.python.syntax.special = color.palette.darkgreen
|
||||
|
||||
icon.plugin.python = python.png
|
||||
|
||||
|
||||
|
||||
[Dark Defaults]
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#----------------------------------------
|
||||
# Ghidra Python launch
|
||||
# Ghidra Jython launch
|
||||
#----------------------------------------
|
||||
|
||||
# Maximum heap memory may be changed if default is inadequate. This will generally be up to 1/4 of
|
||||
@ -31,6 +31,6 @@ VMARG_LIST+="-Djava.awt.headless=true "
|
||||
SCRIPT_FILE="$(readlink -f "$0" 2>/dev/null || readlink "$0" 2>/dev/null || echo "$0")"
|
||||
SCRIPT_DIR="${SCRIPT_FILE%/*}"
|
||||
|
||||
# Launch Ghidra Python
|
||||
# Launch Ghidra Jython
|
||||
# DEBUG_ADDRESS set via environment for launch.sh
|
||||
DEBUG_ADDRESS=${DEBUG_ADDRESS} "${SCRIPT_DIR}"/launch.sh "${LAUNCH_MODE}" jdk "Ghidra-Python" "${MAXMEM}" "${VMARG_LIST}" ghidra.python.PythonRun "$@"
|
||||
DEBUG_ADDRESS=${DEBUG_ADDRESS} "${SCRIPT_DIR}"/launch.sh "${LAUNCH_MODE}" jdk "Ghidra-Jython" "${MAXMEM}" "${VMARG_LIST}" ghidra.jython.JythonRun "$@"
|
||||
|
@ -1,4 +1,4 @@
|
||||
:: Ghidra python launch
|
||||
:: Ghidra jython launch
|
||||
|
||||
@echo off
|
||||
setlocal
|
||||
@ -24,4 +24,4 @@ set DEBUG_ADDRESS=127.0.0.1:13002
|
||||
set VMARG_LIST=-XX:ParallelGCThreads=2
|
||||
set VMARG_LIST=%VMARG_LIST% -XX:CICompilerCount=2
|
||||
|
||||
call "%~dp0launch.bat" %LAUNCH_MODE% jdk Ghidra-Python "%MAXMEM%" "%VMARG_LIST%" ghidra.python.PythonRun %*
|
||||
call "%~dp0launch.bat" %LAUNCH_MODE% jdk Ghidra-Jython "%MAXMEM%" "%VMARG_LIST%" ghidra.jython.JythonRun %*
|
||||
|
@ -36,7 +36,7 @@ import ghidra.app.plugin.core.osgi.BundleStatusComponentProvider;
|
||||
import ghidra.app.plugin.core.script.*;
|
||||
import ghidra.app.script.*;
|
||||
import ghidra.app.services.ConsoleService;
|
||||
import ghidra.python.PythonScriptProvider;
|
||||
import ghidra.jython.JythonScriptProvider;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
public class GhidraScriptMgrPluginScreenShots extends GhidraScreenShotGenerator {
|
||||
@ -223,7 +223,7 @@ public class GhidraScriptMgrPluginScreenShots extends GhidraScreenShotGenerator
|
||||
List<GhidraScriptProvider> items = new ArrayList<>();
|
||||
JavaScriptProvider javaScriptProvider = new JavaScriptProvider();
|
||||
items.add(javaScriptProvider);
|
||||
items.add(new PythonScriptProvider());
|
||||
items.add(new JythonScriptProvider());
|
||||
final PickProviderDialog pickDialog = new PickProviderDialog(items, javaScriptProvider);
|
||||
runSwing(() -> tool.showDialog(pickDialog), false);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user