diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptProvider.java index a9f18480ab..d94e14cab1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptProvider.java @@ -133,4 +133,19 @@ public abstract class GhidraScriptProvider protected void writeBody(PrintWriter writer) { writer.println(getCommentCharacter() + "TODO Add User Code Here"); } + + /** + * Fixup a script name for searching in script directories. + * + *
This method is part of a poorly specified behavior that is due for future amendment, + * see {@link GhidraScriptUtil#fixupName(String)}. + * + * @param scriptName the name of the script, must end with this provider's extension + * @return a (relative) file path to the corresponding script + */ + @Deprecated + protected String fixupName(String scriptName) { + return scriptName; + } + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptUtil.java b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptUtil.java index 5f2ac752b6..e386c800d9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptUtil.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScriptUtil.java @@ -28,6 +28,7 @@ import generic.jar.ResourceFile; import ghidra.app.plugin.core.osgi.BundleHost; import ghidra.app.plugin.core.osgi.OSGiException; import ghidra.app.plugin.core.script.GhidraScriptMgrPlugin; +import ghidra.app.util.headless.HeadlessAnalyzer; import ghidra.framework.Application; import ghidra.util.Msg; import ghidra.util.classfinder.ClassSearcher; @@ -139,8 +140,7 @@ public class GhidraScriptUtil { } catch (IOException e) { Msg.error(GhidraScriptUtil.class, - "Failed to find script in any script directory: " + sourceFile.toString(), - e); + "Failed to find script in any script directory: " + sourceFile.toString(), e); } return null; } @@ -293,14 +293,7 @@ public class GhidraScriptUtil { * @return the Ghidra script provider */ public static GhidraScriptProvider getProvider(ResourceFile scriptFile) { - String scriptFileName = scriptFile.getName().toLowerCase(); - - for (GhidraScriptProvider provider : getProviders()) { - if (scriptFileName.endsWith(provider.getExtension().toLowerCase())) { - return provider; - } - } - return null; + return findProvider(scriptFile.getName()); } /** @@ -310,13 +303,23 @@ public class GhidraScriptUtil { * @return true if a provider exists that can process the specified file */ public static boolean hasScriptProvider(ResourceFile scriptFile) { - String scriptFileName = scriptFile.getName().toLowerCase(); + return findProvider(scriptFile.getName()) != null; + } + + /** + * Find the provider whose extension matches the given filename extension. + * + * @param fileName name of script file + * @return the first matching provider or null if no provider matches + */ + private static GhidraScriptProvider findProvider(String fileName) { + fileName = fileName.toLowerCase(); for (GhidraScriptProvider provider : getProviders()) { - if (scriptFileName.endsWith(provider.getExtension().toLowerCase())) { - return true; + if (fileName.endsWith(provider.getExtension().toLowerCase())) { + return provider; } } - return false; + return null; } /** @@ -362,31 +365,35 @@ public class GhidraScriptUtil { } /** - * Fixup name issues, such as package parts in the name and inner class names. + * Fix script name issues for searching in script directories. + * If no provider can be identified, Java is assumed. * - *
This method can handle names with or without '.java' at the end; names with - * '$' (inner classes) and names with '.' characters for package separators + *
This method is part of a poorly specified behavior that is due for future amendment. * + *
It is used by {@link GhidraScript#runScript(String)} methods,
+ * {@link #createNewScript(String, String, ResourceFile, List)}, and by {@link HeadlessAnalyzer} for
+ * {@code preScript} and {@code postScript}. The intent was to allow some freedom in how a user specifies
+ * a script in two ways: 1) if the extension is omitted ".java" is assumed and 2) if a Java class name is
+ * given it's converted to a relative path.
+ *
* @param name the name of the script
- * @return the name as a '.java' file path (with '/'s and not '.'s)
+ * @return the name as a file path
*/
+ @Deprecated
static String fixupName(String name) {
- if (name.endsWith(".java")) {
- name = name.substring(0, name.length() - 5);
+ GhidraScriptProvider provider = findProvider(name);
+ // assume Java if no provider matched
+ if (provider == null) {
+ name = name + ".java";
+ provider = findProvider(".java");
}
-
- String path = name.replace('.', '/');
- int innerClassIndex = path.indexOf('$');
- if (innerClassIndex != -1) {
- path = path.substring(0, innerClassIndex);
- }
- return path + ".java";
+ return provider.fixupName(name);
}
static ResourceFile findScriptFileInPaths(Collection This method can handle names with '$' (inner classes) and names with '.'
+ * characters for package separators
+ *
+ * It is part of a poorly specified behavior that is due for future amendment,
+ * see {@link GhidraScriptUtil#fixupName(String)}.
+ *
+ * @param scriptName the name of the script
+ * @return the name as a '.java' file path (with '/'s and not '.'s)
+ */
+ @Override
+ protected String fixupName(String scriptName) {
+ scriptName = scriptName.substring(0, scriptName.length() - 5);
+
+ String path = scriptName.replace('.', '/');
+ int innerClassIndex = path.indexOf('$');
+ if (innerClassIndex != -1) {
+ path = path.substring(0, innerClassIndex);
+ }
+ return path + ".java";
+ }
+
}
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/script/GhidraScriptUtilTest.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/script/GhidraScriptUtilTest.java
similarity index 78%
rename from Ghidra/Features/Base/src/test.slow/java/ghidra/app/script/GhidraScriptUtilTest.java
rename to Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/script/GhidraScriptUtilTest.java
index b56bba04a0..c05490e0c3 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/script/GhidraScriptUtilTest.java
+++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/script/GhidraScriptUtilTest.java
@@ -15,14 +15,23 @@
*/
package ghidra.app.script;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
+import org.junit.Before;
import org.junit.Test;
import generic.test.AbstractGenericTest;
+import ghidra.util.classfinder.ClassSearcher;
+import ghidra.util.exception.CancelledException;
+import ghidra.util.task.ConsoleTaskMonitor;
public class GhidraScriptUtilTest extends AbstractGenericTest {
+ @Before
+ public void setup() throws CancelledException {
+ ClassSearcher.search(false, new ConsoleTaskMonitor());
+ }
+
@Test
public void fixupName_WithExtension() {
String input = "Bob.java";
@@ -58,4 +67,11 @@ public class GhidraScriptUtilTest extends AbstractGenericTest {
String input = "a.b.c.Bob$InnerClass";
assertEquals(GhidraScriptUtil.fixupName(input), "a/b/c/Bob.java");
}
+
+ @Test
+ public void fixupName_Python() {
+ String input = "Bob.py";
+ assertEquals(GhidraScriptUtil.fixupName(input), "Bob.py");
+ }
+
}