Fixed menu names for archives that live inside of a distribution

This commit is contained in:
dragonmacher 2024-05-28 18:02:38 -04:00
parent db608a1a13
commit 8c6e50b54f
2 changed files with 77 additions and 58 deletions

View file

@ -83,10 +83,8 @@ import ghidra.util.task.TaskMonitor;
servicesProvided = { DataTypeManagerService.class, DataTypeArchiveService.class }
)
//@formatter:on
public class DataTypeManagerPlugin extends ProgramPlugin implements DomainObjectListener,
DataTypeManagerService, PopupActionProvider {
private static final String EXTENSIONS_PATH_PREFIX = Path.GHIDRA_HOME + "/Extensions";
public class DataTypeManagerPlugin extends ProgramPlugin
implements DomainObjectListener, DataTypeManagerService, PopupActionProvider {
private static final String SEARCH_PROVIDER_NAME = "Search DataTypes Provider";
private static final int RECENTLY_USED_CACHE_SIZE = 10;
@ -192,6 +190,7 @@ public class DataTypeManagerPlugin extends ProgramPlugin implements DomainObject
// checking for the value maintains access-order of the archive
if (recentlyOpenedArchiveMap.get(absoluteFilePath) == null) {
RecentlyOpenedArchiveAction action =
new RecentlyOpenedArchiveAction(this, absoluteFilePath, RECENTLY_OPENED_MENU);
action.setHelpLocation(new HelpLocation(getName(), "Recent_Archives"));
@ -207,15 +206,17 @@ public class DataTypeManagerPlugin extends ProgramPlugin implements DomainObject
*/
public void addRecentlyOpenedProjectArchive(String projectName, String pathname) {
String projectPathname = DataTypeManagerHandler.getProjectPathname(projectName, pathname);
if (recentlyOpenedArchiveMap.get(projectPathname) == null) {
if (recentlyOpenedArchiveMap.get(projectPathname) != null) {
return;
}
RecentlyOpenedArchiveAction action = null;
if (getProjectArchiveFile(projectName, pathname) != null) {
action =
new RecentlyOpenedArchiveAction(this, projectPathname, RECENTLY_OPENED_MENU);
action = new RecentlyOpenedArchiveAction(this, projectPathname, RECENTLY_OPENED_MENU);
action.setHelpLocation(new HelpLocation(getName(), "Recent_Archives"));
}
recentlyOpenedArchiveMap.put(projectPathname, action);
}
updateRecentlyOpenedArchivesMenu();
}
@ -418,50 +419,25 @@ public class DataTypeManagerPlugin extends ProgramPlugin implements DomainObject
private void createStandardArchivesMenu() {
installArchiveMap = new TreeMap<>();
for (ResourceFile archiveFile : Application
.findFilesByExtensionInApplication(FileDataTypeManager.SUFFIX)) {
String gdt = FileDataTypeManager.SUFFIX;
List<ResourceFile> gdts = Application.findFilesByExtensionInApplication(gdt);
for (ResourceFile archiveFile : gdts) {
Path path = new Path(archiveFile);
String absoluteFilePath = path.getPathAsString();
if (absoluteFilePath.indexOf("data/typeinfo") < 0) {
String absolutePath = path.getPathAsString();
if (!absolutePath.contains("/data/typeinfo/")) {
continue;
}
RecentlyOpenedArchiveAction action = new RecentlyOpenedArchiveAction(this,
absoluteFilePath, getShortArchivePath(absoluteFilePath), STANDARD_ARCHIVE_MENU);
RecentlyOpenedArchiveAction action =
new RecentlyOpenedArchiveAction(this, absolutePath, STANDARD_ARCHIVE_MENU);
action.setHelpLocation(new HelpLocation(getName(), "Standard_Archives"));
installArchiveMap.put(absoluteFilePath, action);
installArchiveMap.put(absolutePath, action);
}
for (DockingAction action : installArchiveMap.values()) {
tool.addLocalAction(provider, action);
}
}
private String getShortArchivePath(String fullPath) {
String path = fullPath;
String extensionPrefix = "";
if (fullPath.startsWith(EXTENSIONS_PATH_PREFIX)) {
int index = fullPath.indexOf("/", EXTENSIONS_PATH_PREFIX.length() + 1);
if (index >= 0) {
extensionPrefix =
fullPath.substring(EXTENSIONS_PATH_PREFIX.length() + 1, index) + ": ";
fullPath = fullPath.substring(index + 1);
}
}
int index1 = fullPath.lastIndexOf('/');
if (index1 >= 0) {
int index2 = fullPath.lastIndexOf('/', index1 - 1);
if (index2 >= 0) {
path = fullPath.substring(index2 + 1);
if (!path.startsWith("typeinfo/")) {
return extensionPrefix + path;
}
}
path = fullPath.substring(index1 + 1);
}
return extensionPrefix + path;
}
/**
* Create the actions for the menu on the tool.
*/

View file

@ -31,17 +31,14 @@ import ghidra.util.task.TaskLauncher;
*/
public class RecentlyOpenedArchiveAction extends DockingAction {
private static final String EXTENSIONS_PATH_PREFIX = Path.GHIDRA_HOME + "/Extensions/Ghidra";
private final String projectName; // only used for project archive path
private final String archivePath;
private final DataTypeManagerPlugin plugin;
public RecentlyOpenedArchiveAction(DataTypeManagerPlugin plugin, String archivePath,
String menuGroup) {
this(plugin, archivePath, getDisplayPath(archivePath), menuGroup);
}
public RecentlyOpenedArchiveAction(DataTypeManagerPlugin plugin, String archivePath,
String displayedPath, String menuGroup) {
super(menuGroup + ": \"" + archivePath + "\"", plugin.getName(), false);
this.plugin = plugin;
String[] projectPathname = DataTypeManagerHandler.parseProjectPathname(archivePath);
@ -53,13 +50,20 @@ public class RecentlyOpenedArchiveAction extends DockingAction {
this.projectName = projectPathname[0];
this.archivePath = projectPathname[1];
}
setMenuBarData(new MenuData(new String[] { menuGroup, displayedPath }, null, menuGroup));
String menuPath = getMenuPath(archivePath);
setMenuBarData(new MenuData(new String[] { menuGroup, menuPath }, null, menuGroup));
setDescription("Opens the indicated archive in the data type manager.");
setEnabled(true);
}
private static String getDisplayPath(String filepath) {
private static String getMenuPath(String filepath) {
if (filepath.contains("/data/typeinfo/")) {
return getTypeInfoRelativeName(filepath);
}
String[] projectPathname = DataTypeManagerHandler.parseProjectPathname(filepath);
if (projectPathname == null) {
return filepath;
@ -67,6 +71,44 @@ public class RecentlyOpenedArchiveAction extends DockingAction {
return projectPathname[0] + ":" + projectPathname[1];
}
/*
Inputs:
$GHIDRA_HOME/Extensions/Ghidra/Extension1/data/typeinfo/foo.gdt -> "Extension1: "
$GHIDRA_HOME/Features/Base/data/typeinfo/foo.gdt -> ""
*/
private static String getExtensionName(String fullPath) {
if (!fullPath.startsWith(EXTENSIONS_PATH_PREFIX)) {
return "";
}
int start = EXTENSIONS_PATH_PREFIX.length() + 1;
int slashIndex = fullPath.indexOf("/", start);
if (slashIndex < 0) {
return ""; // no folder; shouldn't happen
}
// return the first folder name, which is the extension name
return fullPath.substring(start, slashIndex) + ": ";
}
/*
Input path is expected to contain '/data/typeinfo'. It may or may not be an extension path.
$GHIDRA_HOME/Extensions/Ghidra/Extension1/data/typeinfo/foo.gdt -> "Extension1: "
$GHIDRA_HOME/Features/Base/data/typeinfo/foo.gdt -> ""
*/
private static String getTypeInfoRelativeName(String fullPath) {
String[] parts = fullPath.split("/data/typeinfo/");
String relativePath = parts[1];
// e.g., "Extension1: " or ""
String extensionName = getExtensionName(fullPath);
return extensionName + relativePath;
}
@Override
public void actionPerformed(ActionContext context) {
if (projectName == null) {
@ -88,22 +130,23 @@ public class RecentlyOpenedArchiveAction extends DockingAction {
}
private class OpenArchiveTask extends Task {
private final Path archivePath;
private final Path taskArchivePath;
private final DataTypeManagerHandler archiveManager;
OpenArchiveTask(DataTypeManagerHandler archiveManager, Path archivePath) {
super("Opening Archive " + archivePath.getPath().getName(), false, false, true);
this.archiveManager = archiveManager;
this.archivePath = archivePath;
this.taskArchivePath = archivePath;
}
@Override
public void run(ghidra.util.task.TaskMonitor monitor) {
try {
archiveManager.openArchive(archivePath.getPath(), false, true);
archiveManager.openArchive(taskArchivePath.getPath(), false, true);
}
catch (Throwable t) {
DataTypeManagerHandler.handleArchiveFileException(plugin, archivePath.getPath(), t);
catch (Exception e) {
DataTypeManagerHandler.handleArchiveFileException(plugin, taskArchivePath.getPath(),
e);
}
}
}