From 8c6e50b54f461b44097befbe1c5a663574775c0c Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Tue, 28 May 2024 18:02:38 -0400 Subject: [PATCH] Fixed menu names for archives that live inside of a distribution --- .../core/datamgr/DataTypeManagerPlugin.java | 68 ++++++------------- .../actions/RecentlyOpenedArchiveAction.java | 67 ++++++++++++++---- 2 files changed, 77 insertions(+), 58 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java index cf1bf7683b..d1ceb604e8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java @@ -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) { - RecentlyOpenedArchiveAction action = null; - if (getProjectArchiveFile(projectName, pathname) != null) { - action = - new RecentlyOpenedArchiveAction(this, projectPathname, RECENTLY_OPENED_MENU); - action.setHelpLocation(new HelpLocation(getName(), "Recent_Archives")); - } - recentlyOpenedArchiveMap.put(projectPathname, action); + if (recentlyOpenedArchiveMap.get(projectPathname) != null) { + return; } + + RecentlyOpenedArchiveAction action = null; + if (getProjectArchiveFile(projectName, pathname) != null) { + 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 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. */ diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/RecentlyOpenedArchiveAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/RecentlyOpenedArchiveAction.java index b911771d1f..e6268c91c3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/RecentlyOpenedArchiveAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/actions/RecentlyOpenedArchiveAction.java @@ -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); } } }