Merge remote-tracking branch 'origin/GT-3639_adamopolous_PR-1960_ryanmkurtz_Extensions'

This commit is contained in:
ghidorahrex 2020-07-14 08:58:15 -04:00
commit 0dfc8e777f
11 changed files with 139 additions and 82 deletions

View file

@ -17,6 +17,7 @@ package ghidra.framework.plugintool.dialog;
import java.awt.Color;
import java.awt.Component;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@ -33,6 +34,7 @@ import ghidra.util.exception.CancelledException;
import ghidra.util.table.column.AbstractGColumnRenderer;
import ghidra.util.table.column.GColumnRenderer;
import ghidra.util.task.TaskMonitor;
import utilities.util.FileUtilities;
/**
* Model for the {@link ExtensionTablePanel}. This defines 5 columns for displaying information in
@ -95,7 +97,7 @@ class ExtensionTableModel extends ThreadedTableModel<ExtensionDetails, List<Exte
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (Application.inSingleJarMode()) {
if (Application.inSingleJarMode() || SystemUtilities.isInDevelopmentMode()) {
return false;
}
@ -104,6 +106,14 @@ class ExtensionTableModel extends ThreadedTableModel<ExtensionDetails, List<Exte
return false;
}
// Do not allow GUI uninstallation of extensions manually installed in installation
// directory
if (extension.getInstallPath() != null && FileUtilities.isPathContainedWithin(
Application.getApplicationLayout().getApplicationInstallationDir().getFile(false),
new File(extension.getInstallPath()))) {
return false;
}
return (columnIndex == INSTALLED_COL);
}
@ -123,7 +133,13 @@ class ExtensionTableModel extends ThreadedTableModel<ExtensionDetails, List<Exte
// If the user does not have write permissions on the installation dir, they cannot
// install.
ResourceFile installDir = Application.getApplicationLayout().getExtensionInstallationDir();
ResourceFile installDir =
Application.getApplicationLayout().getExtensionInstallationDirs().get(0);
if (!installDir.exists() && !installDir.mkdir()) {
Msg.showError(this, null, "Directory Error",
"Cannot install/uninstall extensions: Failed to create extension installation directory.\n" +
"See the \"Ghidra Extension Notes\" section of the Ghidra Installation Guide for more information.");
}
if (!installDir.canWrite()) {
Msg.showError(this, null, "Permissions Error",
"Cannot install/uninstall extensions: Invalid write permissions on installation directory.\n" +

View file

@ -123,7 +123,12 @@ public class ExtensionTableProvider extends DialogComponentProvider {
// Don't let the user attempt to install anything if they don't have write
// permissions on the installation dir.
ResourceFile installDir =
Application.getApplicationLayout().getExtensionInstallationDir();
Application.getApplicationLayout().getExtensionInstallationDirs().get(0);
if (!installDir.exists() && !installDir.mkdir()) {
Msg.showError(this, null, "Directory Error",
"Cannot install/uninstall extensions: Failed to create extension installation directory.\n" +
"See the \"Ghidra Extension Notes\" section of the Ghidra Installation Guide for more information.");
}
if (!installDir.canWrite()) {
Msg.showError(this, null, "Permissions Error",
"Cannot install/uninstall extensions: Invalid write permissions on installation directory.\n" +

View file

@ -133,26 +133,34 @@ public class ExtensionUtils {
ApplicationLayout layout = Application.getApplicationLayout();
if (layout.getExtensionInstallationDir() == null ||
!layout.getExtensionInstallationDir().exists()) {
return Collections.emptySet();
}
// The set to return;
Set<ExtensionDetails> extensions = new HashSet<>();
// Find all extension.properties or extension.properties.uninstalled files in
// the install directory and create a ExtensionDetails object for each.
ResourceFile installDir = layout.getExtensionInstallationDir();
List<ResourceFile> propFiles = findExtensionPropertyFiles(installDir, includeUninstalled);
for (ResourceFile propFile : propFiles) {
ExtensionDetails details = createExtensionDetailsFromPropertyFile(propFile);
for (ResourceFile installDir : layout.getExtensionInstallationDirs()) {
if (!installDir.isDirectory()) {
continue;
}
List<ResourceFile> propFiles =
findExtensionPropertyFiles(installDir, includeUninstalled);
for (ResourceFile propFile : propFiles) {
// We found this extension in the installation directory, so set the install path
// property and add to the final set.
details.setInstallPath(propFile.getParentFile().getAbsolutePath());
extensions.add(details);
ExtensionDetails details = createExtensionDetailsFromPropertyFile(propFile);
// We found this extension in the installation directory, so set the install path
// property and add to the final set.
details.setInstallPath(propFile.getParentFile().getAbsolutePath());
if (!extensions.contains(details)) {
extensions.add(details);
}
else {
Msg.warn(null,
"Skipping extension \"" + details.getName() + "\" found at " +
details.getInstallPath() +
". Extension by that name installed in higher priority location.");
}
}
}
return extensions;
@ -219,8 +227,13 @@ public class ExtensionUtils {
* @return true if installed
*/
public static boolean isInstalled(String extensionName) {
return new File(Application.getApplicationLayout().getExtensionInstallationDir() +
File.separator + extensionName).exists();
for (ResourceFile installDir : Application.getApplicationLayout()
.getExtensionInstallationDirs()) {
if (new ResourceFile(installDir, extensionName).exists()) {
return true;
}
}
return false;
}
/**
@ -267,16 +280,15 @@ public class ExtensionUtils {
return false;
}
File installDir = new ResourceFile(
Application.getApplicationLayout().getExtensionInstallationDirs().get(0),
extension.getName()).getFile(false);
if (extension.getArchivePath() == null) {
// Special Case: If the archive path is null then this must be an extension that
// was installed from an external location, then uninstalled. In this case, there
// should be a Module.manifest.uninstalled and extension.properties.uninstalled
// present. If so, just restore them. If not, there's a problem.
String installPath = Application.getApplicationLayout().getExtensionInstallationDir() +
File.separator + extension.getName();
File installDir = new File(installPath);
if (installDir.exists()) {
return restoreStateFiles(installDir);
}
@ -299,19 +311,13 @@ public class ExtensionUtils {
// the GUI then tries to reinstall it without restarting Ghidra, the extension hasn't actually
// been removed yet; just the manifest file has been renamed. In this case we don't need to go through
// the full install process of unzipping or copying files to the install location. All we need
// to do is rename the manifest file from Module.manifest.uninstall back to Module.manifest.
String installPath = Application.getApplicationLayout().getExtensionInstallationDir() + File.separator +
extension.getName();
File installDir = new File(installPath);
// to do is rename the manifest file from Module.manifest.uninstall back to Module.manifest.
if (installDir.exists()) {
return restoreStateFiles(installDir);
}
if (install(file)) {
extension.setInstallPath(
Application.getApplicationLayout().getExtensionInstallationDir() + File.separator +
extension.getName());
extension.setInstallPath(installDir + File.separator + extension.getName());
return true;
}
@ -554,7 +560,9 @@ public class ExtensionUtils {
File errorFile = e.getErrorFile();
if (errorFile != null) {
// Get the root of the extension in the install location.
ResourceFile installDir = Application.getApplicationLayout().getExtensionInstallationDir();
ResourceFile installDir = Application.getApplicationLayout()
.getExtensionInstallationDirs()
.get(0);
// Get the root directory of the extension (strip off the install folder location and
// grab the first part of the remaining path).
@ -755,7 +763,7 @@ public class ExtensionUtils {
File newDir = null;
try {
newDir =
new File(Application.getApplicationLayout().getExtensionInstallationDir() +
new File(Application.getApplicationLayout().getExtensionInstallationDirs().get(0) +
File.separator + extension.getName());
FileUtilities.deleteDir(newDir, monitor);
FileUtilities.copyDir(extension, newDir, monitor);
@ -788,11 +796,10 @@ public class ExtensionUtils {
ExtensionExceptionType.ZIP_ERROR);
}
if (layout.getExtensionInstallationDir() == null ||
!layout.getExtensionInstallationDir().exists()) {
ResourceFile installDir = layout.getExtensionInstallationDirs().get(0);
if (installDir == null || !installDir.exists()) {
throw new ExtensionException(
"Extension installation directory is not valid: " +
layout.getExtensionInstallationDir(),
"Extension installation directory is not valid: " + installDir,
ExtensionExceptionType.INVALID_INSTALL_LOCATION);
}
@ -803,8 +810,7 @@ public class ExtensionUtils {
ZipArchiveEntry entry = entries.nextElement();
String filePath =
(layout.getExtensionInstallationDir() + File.separator + entry.getName());
String filePath = installDir + File.separator + entry.getName();
File file = new File(filePath);