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 } servicesProvided = { DataTypeManagerService.class, DataTypeArchiveService.class }
) )
//@formatter:on //@formatter:on
public class DataTypeManagerPlugin extends ProgramPlugin implements DomainObjectListener, public class DataTypeManagerPlugin extends ProgramPlugin
DataTypeManagerService, PopupActionProvider { implements DomainObjectListener, DataTypeManagerService, PopupActionProvider {
private static final String EXTENSIONS_PATH_PREFIX = Path.GHIDRA_HOME + "/Extensions";
private static final String SEARCH_PROVIDER_NAME = "Search DataTypes Provider"; private static final String SEARCH_PROVIDER_NAME = "Search DataTypes Provider";
private static final int RECENTLY_USED_CACHE_SIZE = 10; 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 // checking for the value maintains access-order of the archive
if (recentlyOpenedArchiveMap.get(absoluteFilePath) == null) { if (recentlyOpenedArchiveMap.get(absoluteFilePath) == null) {
RecentlyOpenedArchiveAction action = RecentlyOpenedArchiveAction action =
new RecentlyOpenedArchiveAction(this, absoluteFilePath, RECENTLY_OPENED_MENU); new RecentlyOpenedArchiveAction(this, absoluteFilePath, RECENTLY_OPENED_MENU);
action.setHelpLocation(new HelpLocation(getName(), "Recent_Archives")); 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) { public void addRecentlyOpenedProjectArchive(String projectName, String pathname) {
String projectPathname = DataTypeManagerHandler.getProjectPathname(projectName, pathname); String projectPathname = DataTypeManagerHandler.getProjectPathname(projectName, pathname);
if (recentlyOpenedArchiveMap.get(projectPathname) == null) { if (recentlyOpenedArchiveMap.get(projectPathname) != null) {
return;
}
RecentlyOpenedArchiveAction action = null; RecentlyOpenedArchiveAction action = null;
if (getProjectArchiveFile(projectName, pathname) != null) { if (getProjectArchiveFile(projectName, pathname) != null) {
action = action = new RecentlyOpenedArchiveAction(this, projectPathname, RECENTLY_OPENED_MENU);
new RecentlyOpenedArchiveAction(this, projectPathname, RECENTLY_OPENED_MENU);
action.setHelpLocation(new HelpLocation(getName(), "Recent_Archives")); action.setHelpLocation(new HelpLocation(getName(), "Recent_Archives"));
} }
recentlyOpenedArchiveMap.put(projectPathname, action); recentlyOpenedArchiveMap.put(projectPathname, action);
}
updateRecentlyOpenedArchivesMenu(); updateRecentlyOpenedArchivesMenu();
} }
@ -418,50 +419,25 @@ public class DataTypeManagerPlugin extends ProgramPlugin implements DomainObject
private void createStandardArchivesMenu() { private void createStandardArchivesMenu() {
installArchiveMap = new TreeMap<>(); installArchiveMap = new TreeMap<>();
for (ResourceFile archiveFile : Application String gdt = FileDataTypeManager.SUFFIX;
.findFilesByExtensionInApplication(FileDataTypeManager.SUFFIX)) { List<ResourceFile> gdts = Application.findFilesByExtensionInApplication(gdt);
for (ResourceFile archiveFile : gdts) {
Path path = new Path(archiveFile); Path path = new Path(archiveFile);
String absoluteFilePath = path.getPathAsString(); String absolutePath = path.getPathAsString();
if (absoluteFilePath.indexOf("data/typeinfo") < 0) { if (!absolutePath.contains("/data/typeinfo/")) {
continue; 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")); action.setHelpLocation(new HelpLocation(getName(), "Standard_Archives"));
installArchiveMap.put(absoluteFilePath, action); installArchiveMap.put(absolutePath, action);
} }
for (DockingAction action : installArchiveMap.values()) { for (DockingAction action : installArchiveMap.values()) {
tool.addLocalAction(provider, action); 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. * 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 { 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 projectName; // only used for project archive path
private final String archivePath; private final String archivePath;
private final DataTypeManagerPlugin plugin; private final DataTypeManagerPlugin plugin;
public RecentlyOpenedArchiveAction(DataTypeManagerPlugin plugin, String archivePath, public RecentlyOpenedArchiveAction(DataTypeManagerPlugin plugin, String archivePath,
String menuGroup) { String menuGroup) {
this(plugin, archivePath, getDisplayPath(archivePath), menuGroup);
}
public RecentlyOpenedArchiveAction(DataTypeManagerPlugin plugin, String archivePath,
String displayedPath, String menuGroup) {
super(menuGroup + ": \"" + archivePath + "\"", plugin.getName(), false); super(menuGroup + ": \"" + archivePath + "\"", plugin.getName(), false);
this.plugin = plugin; this.plugin = plugin;
String[] projectPathname = DataTypeManagerHandler.parseProjectPathname(archivePath); String[] projectPathname = DataTypeManagerHandler.parseProjectPathname(archivePath);
@ -53,13 +50,20 @@ public class RecentlyOpenedArchiveAction extends DockingAction {
this.projectName = projectPathname[0]; this.projectName = projectPathname[0];
this.archivePath = projectPathname[1]; 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."); setDescription("Opens the indicated archive in the data type manager.");
setEnabled(true); 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); String[] projectPathname = DataTypeManagerHandler.parseProjectPathname(filepath);
if (projectPathname == null) { if (projectPathname == null) {
return filepath; return filepath;
@ -67,6 +71,44 @@ public class RecentlyOpenedArchiveAction extends DockingAction {
return projectPathname[0] + ":" + projectPathname[1]; 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 @Override
public void actionPerformed(ActionContext context) { public void actionPerformed(ActionContext context) {
if (projectName == null) { if (projectName == null) {
@ -88,22 +130,23 @@ public class RecentlyOpenedArchiveAction extends DockingAction {
} }
private class OpenArchiveTask extends Task { private class OpenArchiveTask extends Task {
private final Path archivePath; private final Path taskArchivePath;
private final DataTypeManagerHandler archiveManager; private final DataTypeManagerHandler archiveManager;
OpenArchiveTask(DataTypeManagerHandler archiveManager, Path archivePath) { OpenArchiveTask(DataTypeManagerHandler archiveManager, Path archivePath) {
super("Opening Archive " + archivePath.getPath().getName(), false, false, true); super("Opening Archive " + archivePath.getPath().getName(), false, false, true);
this.archiveManager = archiveManager; this.archiveManager = archiveManager;
this.archivePath = archivePath; this.taskArchivePath = archivePath;
} }
@Override @Override
public void run(ghidra.util.task.TaskMonitor monitor) { public void run(ghidra.util.task.TaskMonitor monitor) {
try { try {
archiveManager.openArchive(archivePath.getPath(), false, true); archiveManager.openArchive(taskArchivePath.getPath(), false, true);
} }
catch (Throwable t) { catch (Exception e) {
DataTypeManagerHandler.handleArchiveFileException(plugin, archivePath.getPath(), t); DataTypeManagerHandler.handleArchiveFileException(plugin, taskArchivePath.getPath(),
e);
} }
} }
} }