mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 13:44:50 +08:00
Merge remote-tracking branch 'origin/GT-2949-dragonmacher-deprecated-script-methods'
This commit is contained in:
@@ -220,9 +220,9 @@ public class BuildResultState extends GhidraScript {
|
||||
// }
|
||||
//
|
||||
Register[] regs = currentProgram.getLanguage().getRegisters();
|
||||
List<Register> registers = Arrays.asList(regs);
|
||||
try {
|
||||
Register reg =
|
||||
askChoice("Results Query", "Select Register:", Arrays.asList(regs), null);
|
||||
Register reg = askChoice("Results Query", "Select Register:", registers, null);
|
||||
while (reg != null) {
|
||||
boolean first = true;
|
||||
boolean preserved = true;
|
||||
@@ -242,7 +242,7 @@ public class BuildResultState extends GhidraScript {
|
||||
System.out.println(reg.getName() + " value is preserved.");
|
||||
}
|
||||
|
||||
reg = askChoice("Results Query", "Select Register:", regs, null);
|
||||
reg = askChoice("Results Query", "Select Register:", registers, null);
|
||||
}
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
|
||||
@@ -13,11 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
@@ -83,8 +82,8 @@ public class FixLangId extends GhidraScript {
|
||||
dbh.close();
|
||||
}
|
||||
|
||||
private boolean modifyLanguage(DomainFile df, DBHandle dbh) throws IOException,
|
||||
ImproperUseException {
|
||||
private boolean modifyLanguage(DomainFile df, DBHandle dbh)
|
||||
throws IOException, ImproperUseException {
|
||||
|
||||
// TODO: Check for address map and overlay entries which could break from
|
||||
// changing the memory model !!
|
||||
@@ -104,9 +103,9 @@ public class FixLangId extends GhidraScript {
|
||||
LanguageDescription desc = null;
|
||||
List<LanguageDescription> descriptions =
|
||||
DefaultLanguageService.getLanguageService().getLanguageDescriptions(true);
|
||||
String[] choices = new String[descriptions.size()];
|
||||
for (int i = 0; i < choices.length; i++) {
|
||||
choices[i] = descriptions.get(i).getLanguageID().getIdAsString();
|
||||
List<String> choices = new ArrayList<>(descriptions.size());
|
||||
for (int i = 0; i < choices.size(); i++) {
|
||||
choices.add(descriptions.get(i).getLanguageID().getIdAsString());
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -114,9 +113,8 @@ public class FixLangId extends GhidraScript {
|
||||
if (langId != null) {
|
||||
Msg.warn(this, "Changing language ID from '" + record.getString(0) + "' to '" +
|
||||
langId + "' for program: " + df.getName());
|
||||
desc =
|
||||
DefaultLanguageService.getLanguageService().getLanguageDescription(
|
||||
new LanguageID(langId));
|
||||
desc = DefaultLanguageService.getLanguageService().getLanguageDescription(
|
||||
new LanguageID(langId));
|
||||
long txId = dbh.startTransaction();
|
||||
try {
|
||||
record.setString(0, langId);
|
||||
@@ -140,20 +138,12 @@ public class FixLangId extends GhidraScript {
|
||||
public DomainFile askProgramFile(String title) {
|
||||
final DomainFile[] domainFile = new DomainFile[] { null };
|
||||
final DataTreeDialog dtd = new DataTreeDialog(null, title, DataTreeDialog.OPEN);
|
||||
dtd.addOkActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
dtd.close();
|
||||
domainFile[0] = dtd.getDomainFile();
|
||||
}
|
||||
dtd.addOkActionListener(e -> {
|
||||
dtd.close();
|
||||
domainFile[0] = dtd.getDomainFile();
|
||||
});
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dtd.showComponent();
|
||||
}
|
||||
});
|
||||
SwingUtilities.invokeAndWait(() -> dtd.showComponent());
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
|
||||
@@ -89,7 +89,8 @@ public class AskScript extends GhidraScript {
|
||||
println("You typed: " + myStr + " and " + myOtherStr);
|
||||
|
||||
String choice = askChoice("Choice", "Please choose one",
|
||||
new String[] { "grumpy", "dopey", "sleepy", "doc", "bashful" }, "bashful");
|
||||
Arrays.asList(new String[] { "grumpy", "dopey", "sleepy", "doc", "bashful" }),
|
||||
"bashful");
|
||||
println("Choice? " + choice);
|
||||
|
||||
List<Integer> choices1 = askChoices("Choices 1", "Please choose one or more numbers.",
|
||||
|
||||
@@ -13,13 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.framework.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Asks user for a single .pdb file or a directory that contains .pdb files (search for
|
||||
@@ -46,10 +45,10 @@ public class CreatePdbXmlFilesScript extends GhidraScript {
|
||||
// Get appropriate pdb.exe file
|
||||
String pdbExeLocation = Application.getOSFile("pdb.exe").getAbsolutePath();
|
||||
|
||||
String[] choices = new String[] { "single file", "directory of files" };
|
||||
String fileOrDir =
|
||||
askChoice("PDB file or directory", "Would you like to operate on a single "
|
||||
+ ".pdb file or a directory of .pdb files?", choices, choices[1]);
|
||||
List<String> choices = Arrays.asList("single file", "directory of files");
|
||||
String fileOrDir = askChoice("PDB file or directory",
|
||||
"Would you like to operate on a single " + ".pdb file or a directory of .pdb files?",
|
||||
choices, choices.get(1));
|
||||
|
||||
File pdbParentDir;
|
||||
String pdbName;
|
||||
@@ -57,7 +56,7 @@ public class CreatePdbXmlFilesScript extends GhidraScript {
|
||||
int filesCreated = 0;
|
||||
|
||||
try {
|
||||
if (fileOrDir.equals(choices[0])) {
|
||||
if (fileOrDir.equals(choices.get(0))) {
|
||||
File pdbFile = askFile("Choose a PDB file", "OK");
|
||||
|
||||
if (!pdbFile.exists()) {
|
||||
@@ -82,12 +81,11 @@ public class CreatePdbXmlFilesScript extends GhidraScript {
|
||||
}
|
||||
else {
|
||||
// Do recursive processing
|
||||
File pdbDir =
|
||||
askDirectory(
|
||||
"Choose PDB root folder (performs recursive search for .pdb files)", "OK");
|
||||
File pdbDir = askDirectory(
|
||||
"Choose PDB root folder (performs recursive search for .pdb files)", "OK");
|
||||
|
||||
// Get list of files to process
|
||||
List<File> pdbFiles = new ArrayList<File>();
|
||||
List<File> pdbFiles = new ArrayList<>();
|
||||
getPDBFiles(pdbDir, pdbFiles);
|
||||
|
||||
int createdFilesCounter = 0;
|
||||
@@ -157,8 +155,8 @@ public class CreatePdbXmlFilesScript extends GhidraScript {
|
||||
createdFile.delete();
|
||||
}
|
||||
|
||||
throw new IOException("At file '" + pdbName +
|
||||
"':\nAbnormal termination of 'pdb.exe' process.");
|
||||
throw new IOException(
|
||||
"At file '" + pdbName + "':\nAbnormal termination of 'pdb.exe' process.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,9 @@ package ghidra.app.script;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.rmi.ConnectException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
@@ -262,15 +260,12 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
}
|
||||
|
||||
private void doCleanup(boolean success) {
|
||||
|
||||
// TODO transient cleanup
|
||||
|
||||
cleanup(success);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will ye, nill ye?
|
||||
* @param success
|
||||
* A callback for scripts to perform any needed cleanup after the script is finished
|
||||
* @param success true if the script was successful
|
||||
*/
|
||||
public void cleanup(boolean success) {
|
||||
// for users to override
|
||||
@@ -296,7 +291,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
*
|
||||
* @param dirLocation String representation of the path to the .properties file
|
||||
* @param basename base name of the file
|
||||
* @throws IOException
|
||||
* @throws IOException if there is an exception loading the new properties file
|
||||
*/
|
||||
public void setPropertiesFileLocation(String dirLocation, String basename) throws IOException {
|
||||
File testIfDir = new File(dirLocation);
|
||||
@@ -407,23 +402,6 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts auto-analysis on the specified program and performs complete analysis
|
||||
* of the entire program. This is usually only necessary if full analysis was never
|
||||
* performed. This method blocks until analysis completes.
|
||||
*
|
||||
* @param program the program to analyze
|
||||
* @deprecated the method {@link #analyzeAll} or {@link #analyzeChanges} should be invoked.
|
||||
* These separate methods were created to clarify their true behavior since many times it is
|
||||
* only necessary to analyze changes and not the entire program which can take much
|
||||
* longer and affect more of the program than is necessary.
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void analyze(Program program) {
|
||||
analyzeAll(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyzeAll(Program program) {
|
||||
if (program == null) {
|
||||
@@ -508,7 +486,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
|
||||
/**
|
||||
* Set associated source file
|
||||
* @param sourceFile
|
||||
* @param sourceFile the source file
|
||||
*/
|
||||
public final void setSourceFile(ResourceFile sourceFile) {
|
||||
this.sourceFile = sourceFile;
|
||||
@@ -617,19 +595,6 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is no longer supported.
|
||||
* Calling it will result in an UnsupportedOperationException being thrown.
|
||||
* @param name the name of the script
|
||||
*
|
||||
* @deprecated you can no longer change a script's name
|
||||
* @throws UnsupportedOperationException
|
||||
*/
|
||||
@Deprecated
|
||||
public void setName(String name) {
|
||||
throw new UnsupportedOperationException("You cannot change a script's name.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the username of the user running the script.
|
||||
* @return the username of the user running the script
|
||||
@@ -1099,22 +1064,6 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of valid choices, given an analysis option name (if they exist for this
|
||||
* option). If the analysis option is unconstrained (does not have to be one of a list
|
||||
* of specific options), returns an empty array.
|
||||
*
|
||||
* @param program the program to get analysis option choices from
|
||||
* @param analysisOption the analysis option to get choices for
|
||||
* @return an String array of the only valid choices for this analysis option (array is empty if
|
||||
* choices are unconstrained)
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public String[] getAnalysisOptionChoices(Program program, String analysisOption) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description of an analysis option name, as provided by the analyzer. This
|
||||
* method returns an empty string if no description is available.
|
||||
@@ -2086,7 +2035,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
chooser.setFileSelectionMode(GhidraFileChooserMode.FILES_ONLY);
|
||||
ref.set(chooser.getSelectedFile());
|
||||
};
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
|
||||
if (chooser.wasCancelled()) {
|
||||
throw new CancelledException();
|
||||
@@ -2169,7 +2118,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
chooser.setFileSelectionMode(GhidraFileChooserMode.DIRECTORIES_ONLY);
|
||||
ref.set(chooser.getSelectedFile());
|
||||
};
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
|
||||
if (chooser.wasCancelled()) {
|
||||
throw new CancelledException();
|
||||
@@ -2276,7 +2225,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
dialog.setSelectedLanguage(lastValue);
|
||||
ref.set(dialog.getSelectedLanguage());
|
||||
};
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
|
||||
if (dialog.wasCancelled()) {
|
||||
throw new CancelledException();
|
||||
@@ -2358,7 +2307,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
});
|
||||
|
||||
Runnable r = () -> dtd.showComponent();
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
|
||||
if (dtd.wasCancelled()) {
|
||||
throw new CancelledException();
|
||||
@@ -2726,7 +2675,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
});
|
||||
|
||||
Runnable r = () -> dtd.showComponent();
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
|
||||
if (dtd.wasCancelled()) {
|
||||
throw new CancelledException();
|
||||
@@ -2818,7 +2767,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
});
|
||||
|
||||
Runnable r = () -> dtd.showComponent();
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
|
||||
if (dtd.wasCancelled()) {
|
||||
throw new CancelledException();
|
||||
@@ -3218,7 +3167,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
new MultipleOptionsDialog<>(title, message, choices, true);
|
||||
|
||||
Runnable r = () -> reference.set(dialog.getUserChoices());
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
|
||||
if (dialog.isCanceled()) {
|
||||
throw new CancelledException();
|
||||
@@ -3295,7 +3244,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
new MultipleOptionsDialog<>(title, message, choices, choiceLabels, true);
|
||||
|
||||
Runnable r = () -> reference.set(dialog.getUserChoices());
|
||||
SystemUtilities.runSwingNow(r);
|
||||
Swing.runNow(r);
|
||||
|
||||
if (dialog.isCanceled()) {
|
||||
throw new CancelledException();
|
||||
@@ -3366,16 +3315,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
return existingValue;
|
||||
}
|
||||
|
||||
AtomicBoolean yesno = new AtomicBoolean();
|
||||
|
||||
Runnable r = () -> {
|
||||
int choice = OptionDialog.showYesNoDialog(null, title, question);
|
||||
yesno.set(choice == OptionDialog.OPTION_ONE);
|
||||
};
|
||||
|
||||
SystemUtilities.runSwingNow(r);
|
||||
|
||||
return yesno.get();
|
||||
return OptionDialog.showYesNoDialog(null, title, question) == OptionDialog.OPTION_ONE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3772,7 +3712,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
Color.GREEN, null, "Script Results", null);
|
||||
tableProvider.installRemoveItemsAction();
|
||||
};
|
||||
SystemUtilities.runSwingLater(runnable);
|
||||
Swing.runLater(runnable);
|
||||
}
|
||||
|
||||
private void show(final String title, final TableService table,
|
||||
@@ -3790,7 +3730,7 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
"GhidraScript", model, Color.GREEN, null, "Script Results", null);
|
||||
tableProvider.installRemoveItemsAction();
|
||||
};
|
||||
SystemUtilities.runSwingLater(runnable);
|
||||
Swing.runLater(runnable);
|
||||
}
|
||||
|
||||
private Map<Class<?>, Object> getScriptMap(String title, String message) {
|
||||
@@ -3813,217 +3753,4 @@ public abstract class GhidraScript extends FlatProgramAPI {
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Deprecated Methods - version 2 - Feb 2017
|
||||
//==================================================================================================
|
||||
|
||||
/**
|
||||
* Fetches the text contained within the given portion of the console.
|
||||
*
|
||||
* @param offset the offset into the console representing the desired start of the text >= 0
|
||||
* @param length the length of the desired string >= 0
|
||||
* @return the text, in a String of length >= 0
|
||||
* @deprecated deemed not worth supporting due to lack of value
|
||||
*/
|
||||
@Deprecated
|
||||
public String getConsoleText(int offset, int length) {
|
||||
|
||||
PluginTool tool = state.getTool();
|
||||
if (tool == null) {
|
||||
throw new ImproperUseException(
|
||||
"The getConsoleText() method can only be run within a headed Ghidra.");
|
||||
}
|
||||
|
||||
ConsoleService console = tool.getService(ConsoleService.class);
|
||||
if (console == null) {
|
||||
// the console service is not a dependency
|
||||
return "";
|
||||
}
|
||||
|
||||
return console.getText(offset, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns number of characters of currently in the console.
|
||||
* <p>
|
||||
* If the console is cleared, this number is reset.
|
||||
*
|
||||
* @return the text in the console, in a String of length >= 0
|
||||
* @deprecated deemed not worth supporting due to lack of value
|
||||
*/
|
||||
@Deprecated
|
||||
public int getConsoleTextLength() {
|
||||
PluginTool tool = state.getTool();
|
||||
if (tool == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ConsoleService console = tool.getService(ConsoleService.class);
|
||||
if (console == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return console.getTextLength();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Deprecated Methods - version 3 - Nov 30 - Ghidra 7.5
|
||||
//==================================================================================================
|
||||
|
||||
/**
|
||||
* Returns an array of Objects representing one or more choices from the given list. The actual
|
||||
* behavior of the method depends on your environment, which can be GUI or headless.
|
||||
* <p>
|
||||
* Regardless of environment -- if script arguments have been set, this method will use the
|
||||
* next argument in the array and advance the array index so the next call to an ask method
|
||||
* will get the next argument. If there are no script arguments and a .properties file
|
||||
* sharing the same base name as the Ghidra Script exists (i.e., Script1.properties for
|
||||
* Script1.java), then this method will then look there for the String value to return.
|
||||
* The method will look in the .properties file by searching for a property name that is a
|
||||
* space-separated concatenation of the input String parameters (title + " " + message).
|
||||
* If that property name exists and its value represents valid choices, then the
|
||||
* .properties value will be used in the following way:
|
||||
* <ol>
|
||||
* <li>In the GUI environment, this method displays a pop-up dialog that presents the user
|
||||
* with checkbox choices (to allow a more flexible option where the user can pick
|
||||
* some, all, or none).</li>
|
||||
* <li>In the headless environment, if a .properties file sharing the same base name as the
|
||||
* Ghidra Script exists (i.e., Script1.properties for Script1.java), then this method
|
||||
* looks there for the choices to return. The method will look in the .properties file
|
||||
* by searching for a property name equal to a space-separated concatenation of the
|
||||
* String parameters (title + " " + message). If that property name exists and
|
||||
* represents a list (one or more) of valid choice(s) in the form
|
||||
* "choice1;choice2;choice3;..." (<-- note the quotes surrounding the choices), then
|
||||
* an Object array of those choices is returned. Otherwise, an Exception is thrown if
|
||||
* there is an invalid or missing .properties value.</li>
|
||||
*</ol>
|
||||
*
|
||||
* @param title the title of the dialog (in GUI mode) or the first part of the variable name
|
||||
* (in headless mode or when using .properties file)
|
||||
* @param message the message to display with the choices (in GUI mode) or the second
|
||||
* part of the variable name (in headless mode or when using .properties file)
|
||||
* @param choices set of choices (toString() value of each object will be displayed in the dialog)
|
||||
* @return the user-selected value(s); null if no selection was made
|
||||
*
|
||||
* @throws CancelledException if the user hits the 'cancel' button
|
||||
* @throws IllegalArgumentException if in headless mode, there was a missing or invalid set of
|
||||
* choices specified in the .properties file
|
||||
* @deprecated use {@link #askChoices(String, String, List)} instead.
|
||||
* Deprecated in 7.5
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T[] askChoices(String title, String message, T[] choices) throws CancelledException {
|
||||
|
||||
List<T> choicesList = Arrays.asList(choices);
|
||||
|
||||
List<T> results = askChoices(title, message, choicesList);
|
||||
T[] array = (T[]) Array.newInstance(choices.getClass().getComponentType(), results.size());
|
||||
return results.toArray(array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object that represents one of the choices in the given list. The actual behavior
|
||||
* of the method depends on your environment, which can be GUI or headless.
|
||||
* <p>
|
||||
* Regardless of environment -- if script arguments have been set, this method will use the
|
||||
* next argument in the array and advance the array index so the next call to an ask method
|
||||
* will get the next argument. If there are no script arguments and a .properties file
|
||||
* sharing the same base name as the Ghidra Script exists (i.e., Script1.properties for
|
||||
* Script1.java), then this method will then look there for the String value to return.
|
||||
* The method will look in the .properties file by searching for a property name that is a
|
||||
* space-separated concatenation of the input String parameters (title + " " + message).
|
||||
* If that property name exists and its value represents a valid choice, then the
|
||||
* .properties value will be used in the following way:
|
||||
* <ol>
|
||||
* <li>In the GUI environment, this method displays a popup dialog that prompts the user
|
||||
* to choose from the given list of objects. The pre-chosen choice will be the last
|
||||
* user-chosen value (if the dialog has been run before). If that does not exist, the
|
||||
* pre-chosen value is the .properties value. If that does not exist or is invalid,
|
||||
* then the 'defaultValue' parameter is used (as long as it is not null).</li>
|
||||
* <li>In the headless environment, this method returns an object representing the
|
||||
* .properties value (if it exists and is a valid choice), or throws an Exception if
|
||||
* there is an invalid or missing .properties value.</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
* @param title the title of the dialog (in GUI mode) or the first part of the variable name
|
||||
* (in headless mode or when using .properties file)
|
||||
* @param message the message to display next to the input field (in GUI mode) or the second
|
||||
* part of the variable name (in headless mode or when using .properties file)
|
||||
* @param choices set of choices (toString() value of each object will be displayed in the dialog)
|
||||
* @param defaultValue the default value to display in the input field; may be
|
||||
* null, but must be a valid choice if non-null.
|
||||
* @return the user-selected value
|
||||
* @throws CancelledException if the user hit the 'cancel' button
|
||||
* @throws IllegalArgumentException if in headless mode, there was a missing or invalid choice
|
||||
* specified in the .properties file
|
||||
* @deprecated use {@link #askChoice(String, String, List, Object)} instead.
|
||||
* Deprecated in 7.5
|
||||
*/
|
||||
@Deprecated
|
||||
public <T> T askChoice(String title, String message, T[] choices, T defaultValue)
|
||||
throws CancelledException {
|
||||
|
||||
List<T> choicesList = Arrays.asList(choices);
|
||||
return askChoice(title, message, choicesList, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of Objects representing one or more choices from the given list. The user
|
||||
* specifies the choices as Objects, also passing along a corresponding array of String
|
||||
* representations for each choice (used as the checkbox label). The actual behavior of the
|
||||
* method depends on your environment, which can be GUI or headless.
|
||||
* <p>
|
||||
* Regardless of environment -- if script arguments have been set, this method will use the
|
||||
* next argument in the array and advance the array index so the next call to an ask method
|
||||
* will get the next argument. If there are no script arguments and a .properties file
|
||||
* sharing the same base name as the Ghidra Script exists (i.e., Script1.properties for
|
||||
* Script1.java), then this method will then look there for the String value to return.
|
||||
* The method will look in the .properties file by searching for a property name that is a
|
||||
* space-separated concatenation of the input String parameters (title + " " + message).
|
||||
* If that property name exists and its value represents valid choices, then the
|
||||
* .properties value will be used in the following way:
|
||||
* <ol>
|
||||
* <li>In the GUI environment, this method displays a pop-up dialog that presents the user
|
||||
* with checkbox choices (to allow a more flexible option where the user can pick
|
||||
* some, all, or none).</li>
|
||||
* <li>In the headless environment, if a .properties file sharing the same base name as the
|
||||
* Ghidra Script exists (i.e., Script1.properties for Script1.java), then this method
|
||||
* looks there for the choices to return. The method will look in the .properties file
|
||||
* by searching for a property name equal to a space-separated concatenation of the
|
||||
* String parameters (title + " " + message). If that property name exists and
|
||||
* represents a list (one or more) of valid choice(s) in the form
|
||||
* "choice1;choice2;choice3;..." (<-- note the quotes surrounding the choices), then
|
||||
* an Object array of those choices is returned. Otherwise, an Exception is thrown if
|
||||
* there is an invalid or missing .properties value. NOTE: the choice names for
|
||||
* this method must match those in the stringRepresentationOfChoices array.</li>
|
||||
*</ol>
|
||||
*
|
||||
* @param title the title of the dialog (in GUI mode) or the first part of the variable name
|
||||
* (in headless mode or when using .properties file)
|
||||
* @param message the message to display with the choices (in GUI mode) or the second
|
||||
* part of the variable name (in headless mode or when using .properties file)
|
||||
* @param choices set of choices
|
||||
* @param choiceLabels the String representation for each choice, used for
|
||||
* checkbox labels
|
||||
* @return the user-selected value(s); an empty list if no selection was made
|
||||
*
|
||||
* @throws CancelledException if the user hits the 'cancel' button
|
||||
* @throws IllegalArgumentException if in headless mode, there was a missing or invalid set of
|
||||
* choices specified in the .properties file
|
||||
* @deprecated use {@link #askChoices(String, String, List, List)} instead.
|
||||
* Deprecated in 7.5
|
||||
*/
|
||||
@Deprecated
|
||||
public <T> Object[] askChoices(String title, String message, T[] choices, String[] choiceLabels)
|
||||
throws CancelledException {
|
||||
|
||||
List<T> choicesList = Arrays.asList(choices);
|
||||
List<String> labelsList = Arrays.asList(choiceLabels);
|
||||
|
||||
List<T> results = askChoices(title, message, choicesList, labelsList);
|
||||
return results.toArray(new Object[results.size()]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import generic.jar.ResourceFile;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* Handles processing for a .properties files associated with a GhidraScript (.properties file and
|
||||
* Handles processing for .properties files associated with a GhidraScript (.properties file and
|
||||
* script should share the same basename).
|
||||
*
|
||||
* This should only be called/used by the GhidraScript class.
|
||||
@@ -43,6 +43,7 @@ public class GhidraScriptProperties {
|
||||
*
|
||||
* @param scriptLocation location of the GhidraScript
|
||||
* @param newBaseName name of the GhidraScript (without the extension)
|
||||
* @throws IOException if there is an exception loading the properties file
|
||||
*/
|
||||
protected void loadGhidraScriptProperties(ResourceFile scriptLocation, String newBaseName)
|
||||
throws IOException {
|
||||
@@ -79,8 +80,9 @@ public class GhidraScriptProperties {
|
||||
/**
|
||||
* Look for a .properties file corresponding to the basename in the given locations.
|
||||
*
|
||||
* @param possibleLocations possible locations where the .properties file can be found
|
||||
* @param basename name of the GhidraScript (without the extension)
|
||||
* @param possibleLocations possible locations where the .properties file can be found
|
||||
* @param newBaseName name of the GhidraScript (without the extension)
|
||||
* @throws IOException if there is an exception loading the properties file
|
||||
*/
|
||||
protected void loadGhidraScriptProperties(List<ResourceFile> possibleLocations,
|
||||
String newBaseName) throws IOException {
|
||||
@@ -98,6 +100,7 @@ public class GhidraScriptProperties {
|
||||
* Load a .properties file.
|
||||
*
|
||||
* @param file the .properties file
|
||||
* @throws IOException if there is an exception loading the properties file
|
||||
*/
|
||||
protected void loadGhidraScriptProperties(ResourceFile file) throws IOException {
|
||||
|
||||
|
||||
+31
-45
@@ -19,8 +19,7 @@ import static org.junit.Assert.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -30,7 +29,7 @@ import org.junit.*;
|
||||
|
||||
import docking.DialogComponentProvider;
|
||||
import docking.widgets.filechooser.GhidraFileChooser;
|
||||
import generic.test.AbstractGenericTest;
|
||||
import generic.test.AbstractGTest;
|
||||
import generic.test.TestUtils;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||
import ghidra.app.plugin.core.script.GhidraScriptMgrPlugin;
|
||||
@@ -43,7 +42,7 @@ import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
import ghidra.test.TestEnv;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import utilities.util.FileUtilities;
|
||||
|
||||
public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
@@ -123,7 +122,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
assertByteArrayEquals(expectedBytes, myBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Calling askProgram() would stacktrace if the user 1) didn't select a program in the
|
||||
* tree and then 2) pressed the OK button.
|
||||
*/
|
||||
@@ -141,7 +140,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
}, false);
|
||||
|
||||
DataTreeDialog dtd = waitForDialogComponent(null, DataTreeDialog.class, 2000);
|
||||
DataTreeDialog dtd = waitForDialogComponent(DataTreeDialog.class);
|
||||
JButton okButton = (JButton) getInstanceField("okButton", dtd);
|
||||
|
||||
runSwing(() -> okButton.doClick());
|
||||
@@ -152,7 +151,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
runSwing(() -> dtd.close());
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* For scripts with properties files in a different location (could be the case with subscripts),
|
||||
* tests that the .properties file is found in the default location and that the default value
|
||||
* for the input field is provided by the .properties file in the alternate location.
|
||||
@@ -164,7 +163,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
|
||||
// Create a temporary .properties file and set the potentialPropertiesFileLocs to look
|
||||
// in that location
|
||||
String tempDirPath = AbstractGenericTest.getTestDirectoryPath();
|
||||
String tempDirPath = AbstractGTest.getTestDirectoryPath();
|
||||
File tempDir = new File(tempDirPath);
|
||||
File tempPropertiesFile = new File(tempDir, "GhidraScriptTest.properties");
|
||||
tempPropertiesFile.delete();
|
||||
@@ -200,8 +199,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
});
|
||||
|
||||
AskDialog askDialog =
|
||||
waitForDialogComponent(env.getTool().getToolFrame(), AskDialog.class, TIMEOUT_MILLIS);
|
||||
AskDialog<?> askDialog = waitForDialogComponent(AskDialog.class);
|
||||
assertNotNull(askDialog);
|
||||
pressButtonByText(askDialog, "OK");
|
||||
waitForSwing();
|
||||
@@ -216,7 +214,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
|
||||
// Create a temporary files, then create a temporary .properties file that contains
|
||||
// the path to one of the temporary file.
|
||||
String tempDirPath = AbstractGenericTest.getTestDirectoryPath();
|
||||
String tempDirPath = AbstractGTest.getTestDirectoryPath();
|
||||
File tempDir = new File(tempDirPath);
|
||||
File tempFile = new File(tempDir, "tempFile.exe");
|
||||
File anotherTempFile = new File(tempDir, "MyTempFile.txt");
|
||||
@@ -258,8 +256,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
});
|
||||
|
||||
GhidraFileChooser fileChooser = waitForDialogComponent(env.getTool().getToolFrame(),
|
||||
GhidraFileChooser.class, TIMEOUT_MILLIS * 2);
|
||||
GhidraFileChooser fileChooser = waitForDialogComponent(GhidraFileChooser.class);
|
||||
|
||||
waitForUpdateOnDirectory(fileChooser);
|
||||
|
||||
@@ -281,8 +278,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
});
|
||||
|
||||
fileChooser = waitForDialogComponent(env.getTool().getToolFrame(), GhidraFileChooser.class,
|
||||
TIMEOUT_MILLIS * 2);
|
||||
fileChooser = waitForDialogComponent(GhidraFileChooser.class);
|
||||
|
||||
fileChooser.setSelectedFile(anotherTempFile);
|
||||
waitForUpdateOnDirectory(fileChooser);
|
||||
@@ -300,8 +296,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
});
|
||||
|
||||
fileChooser = waitForDialogComponent(env.getTool().getToolFrame(), GhidraFileChooser.class,
|
||||
TIMEOUT_MILLIS * 2);
|
||||
fileChooser = waitForDialogComponent(GhidraFileChooser.class);
|
||||
|
||||
fileChooser.setSelectedFile(anotherTempFile);
|
||||
waitForUpdateOnDirectory(fileChooser);
|
||||
@@ -324,7 +319,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
|
||||
// Create temporary directories, then create a temporary .properties file that contains
|
||||
// the path to one of the temporary directory.
|
||||
String tempDirPath = AbstractGenericTest.getTestDirectoryPath();
|
||||
String tempDirPath = AbstractGTest.getTestDirectoryPath();
|
||||
File tempDir = new File(tempDirPath);
|
||||
File tempSubDir = new File(tempDir, TEMP_SUB_DIR);
|
||||
File anotherTempSubDir = new File(tempDir, "anotherTempDir");
|
||||
@@ -368,8 +363,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
});
|
||||
|
||||
GhidraFileChooser fileChooser = waitForDialogComponent(env.getTool().getToolFrame(),
|
||||
GhidraFileChooser.class, TIMEOUT_MILLIS * 2);
|
||||
GhidraFileChooser fileChooser = waitForDialogComponent(GhidraFileChooser.class);
|
||||
waitForUpdateOnDirectory(fileChooser);
|
||||
|
||||
assertNotNull(fileChooser);
|
||||
@@ -390,8 +384,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
});
|
||||
|
||||
fileChooser = waitForDialogComponent(env.getTool().getToolFrame(), GhidraFileChooser.class,
|
||||
TIMEOUT_MILLIS * 2);
|
||||
fileChooser = waitForDialogComponent(GhidraFileChooser.class);
|
||||
|
||||
fileChooser.setSelectedFile(anotherTempSubDir);
|
||||
waitForUpdateOnDirectory(fileChooser);
|
||||
@@ -409,8 +402,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
});
|
||||
|
||||
fileChooser = waitForDialogComponent(env.getTool().getToolFrame(), GhidraFileChooser.class,
|
||||
TIMEOUT_MILLIS * 2);
|
||||
fileChooser = waitForDialogComponent(GhidraFileChooser.class);
|
||||
waitForUpdateOnDirectory(fileChooser);
|
||||
|
||||
pressButtonByText(fileChooser, "Choose!");
|
||||
@@ -444,8 +436,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
}, false);
|
||||
|
||||
SelectLanguageDialog langDialog = waitForDialogComponent(env.getTool().getToolFrame(),
|
||||
SelectLanguageDialog.class, TIMEOUT_MILLIS);
|
||||
SelectLanguageDialog langDialog = waitForDialogComponent(SelectLanguageDialog.class);
|
||||
assertNotNull(langDialog);
|
||||
pressButtonByText(langDialog, "Give me a language:");
|
||||
waitForSwing();
|
||||
@@ -463,8 +454,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
}, false);
|
||||
|
||||
langDialog = waitForDialogComponent(env.getTool().getToolFrame(),
|
||||
SelectLanguageDialog.class, TIMEOUT_MILLIS);
|
||||
langDialog = waitForDialogComponent(SelectLanguageDialog.class);
|
||||
|
||||
LanguageCompilerSpecPair chosenLang =
|
||||
new LanguageCompilerSpecPair("68000:BE:32:Coldfire", "default");
|
||||
@@ -484,8 +474,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
}, false);
|
||||
|
||||
langDialog = waitForDialogComponent(env.getTool().getToolFrame(),
|
||||
SelectLanguageDialog.class, TIMEOUT_MILLIS);
|
||||
langDialog = waitForDialogComponent(SelectLanguageDialog.class);
|
||||
|
||||
pressButtonByText(langDialog, "Give me a language:");
|
||||
waitForSwing();
|
||||
@@ -510,7 +499,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
assertEquals(10101, chosenInt);
|
||||
|
||||
// Now set int to some other value
|
||||
Integer newInt = new Integer(123456);
|
||||
Integer newInt = 123456;
|
||||
chosenInt = ask_TextInput(Integer.toString(newInt), () -> {
|
||||
return script.askInt("Ask Test", "Enter an integer:");
|
||||
});
|
||||
@@ -539,7 +528,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
assertEquals((long) Math.pow(2, 18), chosenLong);
|
||||
|
||||
// Now set the long value to a different value
|
||||
Long newLong = new Long((long) Math.pow(4, 28));
|
||||
Long newLong = (long) Math.pow(4, 28);
|
||||
chosenLong = ask_TextInput(Long.toString(newLong), () -> {
|
||||
return script.askLong("Ask Test", "Enter a long:");
|
||||
});
|
||||
@@ -649,21 +638,21 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
createScript();
|
||||
|
||||
// Compare default value to expected properties value
|
||||
String[] choices = new String[] { "eenie", "meanie", "miney", "mo" };
|
||||
List<String> choices = Arrays.asList("eenie", "meanie", "miney", "mo");
|
||||
String chosen = ask_ComboInput(() -> {
|
||||
return script.askChoice("Ask Test", "Choose one:", choices, "mo");
|
||||
});
|
||||
assertEquals("meanie", chosen);
|
||||
|
||||
// Set choice to a different value
|
||||
String choice_eenie = choices[0];
|
||||
String choice_eenie = choices.get(0);
|
||||
chosen = ask_ComboInput(choice_eenie, () -> {
|
||||
return script.askChoice("Ask Test", "Choose one:", choices, "mo");
|
||||
});
|
||||
assertEquals(choice_eenie, chosen);
|
||||
|
||||
// See if the last-set value is auto-populated
|
||||
String choice_miney = choices[2];
|
||||
String choice_miney = choices.get(2);
|
||||
chosen = ask_ComboInput(() -> {
|
||||
// Note: we are passing a default of 'miney', but expect the last choice of 'eenie'
|
||||
return script.askChoice("Ask Test", "Choose one:", choices, choice_miney);
|
||||
@@ -681,13 +670,13 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
public void testAskChoiceDefaultValue() throws Exception {
|
||||
createScript();
|
||||
|
||||
String[] choices = new String[] { "one fish", "two fish", "red fish", "blue fish" };
|
||||
List<String> choices = Arrays.asList("one fish", "two fish", "red fish", "blue fish");
|
||||
int choiceIndex = 2;
|
||||
String chosen = ask_ComboInput(() -> {
|
||||
return script.askChoice("Ask Default Choice Test",
|
||||
"Which choice would you like to pick?", choices, choices[choiceIndex]);
|
||||
"Which choice would you like to pick?", choices, choices.get(choiceIndex));
|
||||
});
|
||||
assertEquals(choices[choiceIndex], chosen);
|
||||
assertEquals(choices.get(choiceIndex), chosen);
|
||||
}
|
||||
|
||||
// TODO test for askChoices()
|
||||
@@ -739,8 +728,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
}, false);
|
||||
|
||||
DialogComponentProvider askDialog = waitForDialogComponent(env.getTool().getToolFrame(),
|
||||
DialogComponentProvider.class, TIMEOUT_MILLIS);
|
||||
DialogComponentProvider askDialog = waitForDialogComponent(DialogComponentProvider.class);
|
||||
assertNotNull(askDialog);
|
||||
|
||||
if (optionalValue != null) {
|
||||
@@ -774,8 +762,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
}, false);
|
||||
|
||||
DialogComponentProvider askDialog = waitForDialogComponent(env.getTool().getToolFrame(),
|
||||
DialogComponentProvider.class, TIMEOUT_MILLIS);
|
||||
DialogComponentProvider askDialog = waitForDialogComponent(DialogComponentProvider.class);
|
||||
assertNotNull(askDialog);
|
||||
|
||||
if (optionalValue != null) {
|
||||
@@ -808,8 +795,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
}
|
||||
}, false);
|
||||
|
||||
AskDialog askDialog =
|
||||
waitForDialogComponent(env.getTool().getToolFrame(), AskDialog.class, TIMEOUT_MILLIS);
|
||||
AskDialog<?> askDialog = waitForDialogComponent(AskDialog.class);
|
||||
assertNotNull(askDialog);
|
||||
|
||||
if (optionalValue != null) {
|
||||
@@ -890,7 +876,7 @@ public class GhidraScriptAskMethodsTest extends AbstractGhidraHeadedIntegrationT
|
||||
// test stub
|
||||
}
|
||||
};
|
||||
script.set(state, TaskMonitorAdapter.DUMMY_MONITOR, null);
|
||||
script.set(state, TaskMonitor.DUMMY, null);
|
||||
|
||||
URL url = GhidraScriptTest.class.getResource("GhidraScriptAsk.properties");
|
||||
assertNotNull("Test cannot run without properties file!", url);
|
||||
|
||||
@@ -44,7 +44,7 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||
import ghidra.test.TestEnv;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class GhidraScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
@@ -666,7 +666,6 @@ public class GhidraScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
assertEquals(values.size(), userChoices.size());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testAskChoices_NoSharedInterface_ChooseMultiple_Deprecated() throws Exception {
|
||||
|
||||
@@ -674,13 +673,13 @@ public class GhidraScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
final GhidraScript script = getScript();
|
||||
|
||||
Object[] values = { new JPanel(), new String() };
|
||||
String[] labels = { "Panel", "String" };
|
||||
List<Object> values = Arrays.asList(new JPanel(), new String());
|
||||
List<String> labels = Arrays.asList("Panel", "String");
|
||||
|
||||
AtomicReference<Object[]> ref = new AtomicReference<>();
|
||||
AtomicReference<List<Object>> ref = new AtomicReference<>();
|
||||
runSwing(() -> {
|
||||
try {
|
||||
Object[] userChoices =
|
||||
List<Object> userChoices =
|
||||
script.askChoices("Ask Choices Test", "Pick", values, labels);
|
||||
ref.set(userChoices);
|
||||
}
|
||||
@@ -689,16 +688,15 @@ public class GhidraScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
}
|
||||
}, false);
|
||||
|
||||
MultipleOptionsDialog<?> dialog = waitForDialogComponent(env.getTool().getToolFrame(),
|
||||
MultipleOptionsDialog.class, DEFAULT_WINDOW_TIMEOUT);
|
||||
MultipleOptionsDialog<?> dialog = waitForDialogComponent(MultipleOptionsDialog.class);
|
||||
assertNotNull(dialog);
|
||||
pressSelectAll(dialog);
|
||||
pressButtonByText(dialog, "OK");
|
||||
|
||||
waitForSwing();
|
||||
|
||||
Object[] userChoices = ref.get();
|
||||
assertEquals(values.length, userChoices.length);
|
||||
List<Object> userChoices = ref.get();
|
||||
assertEquals(values.size(), userChoices.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -777,7 +775,7 @@ public class GhidraScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
// test stub
|
||||
}
|
||||
};
|
||||
script.set(state, TaskMonitorAdapter.DUMMY_MONITOR, null);
|
||||
script.set(state, TaskMonitor.DUMMY, null);
|
||||
return script;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,42 +18,21 @@
|
||||
// Subfolders at a specific depth from this root form the roots of individual libraries
|
||||
// Library Name, Version, and Variant are created from the directory path elements
|
||||
//@category FunctionID
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import generic.hash.FNV1a64MessageDigest;
|
||||
import generic.hash.MessageDigest;
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.feature.fid.db.FidDB;
|
||||
import ghidra.feature.fid.db.FidFile;
|
||||
import ghidra.feature.fid.db.FidFileManager;
|
||||
import ghidra.feature.fid.db.LibraryRecord;
|
||||
import ghidra.feature.fid.db.*;
|
||||
import ghidra.feature.fid.hash.FidHashQuad;
|
||||
import ghidra.feature.fid.service.FidPopulateResult;
|
||||
import ghidra.feature.fid.service.*;
|
||||
import ghidra.feature.fid.service.FidPopulateResult.Disposition;
|
||||
import ghidra.feature.fid.service.FidPopulateResultReporter;
|
||||
import ghidra.feature.fid.service.FidService;
|
||||
import ghidra.feature.fid.service.Location;
|
||||
import ghidra.framework.model.DomainFile;
|
||||
import ghidra.framework.model.DomainFolder;
|
||||
import ghidra.framework.model.DomainObject;
|
||||
import ghidra.framework.model.*;
|
||||
import ghidra.program.database.ProgramContentHandler;
|
||||
import ghidra.program.model.lang.LanguageID;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.FunctionIterator;
|
||||
import ghidra.program.model.listing.FunctionManager;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
@@ -122,7 +101,7 @@ public class CreateMultipleLibraries extends GhidraScript {
|
||||
}
|
||||
}
|
||||
outputLine("List of unresolved symbols:");
|
||||
TreeSet<String> symbols = new TreeSet<String>();
|
||||
TreeSet<String> symbols = new TreeSet<>();
|
||||
for (Location location : result.getUnresolvedSymbols()) {
|
||||
symbols.add(location.getFunctionName());
|
||||
}
|
||||
@@ -183,7 +162,7 @@ public class CreateMultipleLibraries extends GhidraScript {
|
||||
private boolean checkForDuplicate(ArrayList<DomainFile> programs) throws CancelledException {
|
||||
String fullName =
|
||||
currentLibraryName + ':' + currentLibraryVersion + ':' + currentLibraryVariant;
|
||||
ArrayList<Long> hashList = new ArrayList<Long>();
|
||||
ArrayList<Long> hashList = new ArrayList<>();
|
||||
for (int i = 0; i < programs.size(); ++i) {
|
||||
monitor.checkCanceled();
|
||||
try {
|
||||
@@ -216,7 +195,7 @@ public class CreateMultipleLibraries extends GhidraScript {
|
||||
private boolean detectDups(DomainFolder folder) {
|
||||
boolean isDuplicate = false;
|
||||
try {
|
||||
ArrayList<DomainFile> programs = new ArrayList<DomainFile>();
|
||||
ArrayList<DomainFile> programs = new ArrayList<>();
|
||||
findPrograms(programs, folder);
|
||||
|
||||
isDuplicate = checkForDuplicate(programs);
|
||||
@@ -241,7 +220,7 @@ public class CreateMultipleLibraries extends GhidraScript {
|
||||
return;
|
||||
}
|
||||
BufferedReader reader = new BufferedReader(new FileReader(commonSymbolsFile));
|
||||
commonSymbols = new LinkedList<String>();
|
||||
commonSymbols = new LinkedList<>();
|
||||
String line = reader.readLine();
|
||||
while (line != null) {
|
||||
monitor.checkCanceled();
|
||||
@@ -291,7 +270,7 @@ public class CreateMultipleLibraries extends GhidraScript {
|
||||
}
|
||||
|
||||
private void populateLibrary(DomainFolder folder) {
|
||||
ArrayList<DomainFile> programs = new ArrayList<DomainFile>();
|
||||
ArrayList<DomainFile> programs = new ArrayList<>();
|
||||
try {
|
||||
findPrograms(programs, folder);
|
||||
|
||||
@@ -363,16 +342,16 @@ public class CreateMultipleLibraries extends GhidraScript {
|
||||
// ignore, means we use console
|
||||
}
|
||||
if (askYesNo("Do Duplication Detection", "Do you want to detect duplicates")) {
|
||||
duplicatemap = new TreeMap<Long, String>();
|
||||
duplicatemap = new TreeMap<>();
|
||||
}
|
||||
|
||||
List<FidFile> nonInstallationFidFiles = FidFileManager.getInstance().getUserAddedFiles();
|
||||
Object[] FidFile = nonInstallationFidFiles.toArray();
|
||||
if (nonInstallationFidFiles.isEmpty()) {
|
||||
throw new FileNotFoundException("Could not find any fidb files that can be populated");
|
||||
}
|
||||
fidFile = (FidFile) askChoice("Choose destination FidDB",
|
||||
"Please choose the destination FidDB for population", FidFile, FidFile[0]);
|
||||
fidFile = askChoice("Choose destination FidDB",
|
||||
"Please choose the destination FidDB for population", nonInstallationFidFiles,
|
||||
nonInstallationFidFiles.get(0));
|
||||
|
||||
rootFolder =
|
||||
askProjectFolder("Select root folder containing all libraries (at a depth of " +
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
// Opens all programs under a chosen domain folder, scans them for functions
|
||||
// that match a user supplied FID hash and prints info about the matching function
|
||||
//@category FunctionID
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.feature.fid.hash.FidHashQuad;
|
||||
import ghidra.feature.fid.plugin.HashLookupListMode;
|
||||
@@ -29,9 +32,6 @@ import ghidra.util.NumericUtilities;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class FindFunctionByHash extends GhidraScript {
|
||||
|
||||
FidService service;
|
||||
@@ -40,24 +40,23 @@ public class FindFunctionByHash extends GhidraScript {
|
||||
protected void run() throws Exception {
|
||||
service = new FidService();
|
||||
|
||||
DomainFolder folder =
|
||||
askProjectFolder("Please select a project folder to RECURSIVELY look for a named function:");
|
||||
String hashString =
|
||||
askString("Please enter function hash",
|
||||
"Please enter the (hex) function hash you're looking for:");
|
||||
DomainFolder folder = askProjectFolder(
|
||||
"Please select a project folder to RECURSIVELY look for a named function:");
|
||||
String hashString = askString("Please enter function hash",
|
||||
"Please enter the (hex) function hash you're looking for:");
|
||||
long hash = NumericUtilities.parseHexLong(hashString);
|
||||
HashLookupListMode[] choices =
|
||||
new HashLookupListMode[] { HashLookupListMode.FULL, HashLookupListMode.SPECIFIC };
|
||||
HashLookupListMode hashType =
|
||||
askChoice("Please choose hash type", "Please select the type of hash", choices,
|
||||
choices[1]);
|
||||
List<HashLookupListMode> choices =
|
||||
Arrays.asList(HashLookupListMode.FULL, HashLookupListMode.SPECIFIC);
|
||||
HashLookupListMode hashType = askChoice("Please choose hash type",
|
||||
"Please select the type of hash", choices, choices.get(1));
|
||||
|
||||
ArrayList<DomainFile> programs = new ArrayList<DomainFile>();
|
||||
ArrayList<DomainFile> programs = new ArrayList<>();
|
||||
findPrograms(programs, folder);
|
||||
findFunction(programs, hash, hashType);
|
||||
}
|
||||
|
||||
private void findFunction(ArrayList<DomainFile> programs, long hash, HashLookupListMode hashType) {
|
||||
private void findFunction(ArrayList<DomainFile> programs, long hash,
|
||||
HashLookupListMode hashType) {
|
||||
for (DomainFile domainFile : programs) {
|
||||
if (monitor.isCancelled()) {
|
||||
return;
|
||||
@@ -76,7 +75,8 @@ public class FindFunctionByHash extends GhidraScript {
|
||||
continue;
|
||||
}
|
||||
if ((hashType == HashLookupListMode.FULL && hashQuad.getFullHash() == hash) ||
|
||||
(hashType == HashLookupListMode.SPECIFIC && hashQuad.getSpecificHash() == hash)) {
|
||||
(hashType == HashLookupListMode.SPECIFIC &&
|
||||
hashQuad.getSpecificHash() == hash)) {
|
||||
println("found " + function.getName() + " at " + function.getEntryPoint() +
|
||||
" in " + domainFile.getPathname());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user