Merge remote-tracking branch

'origin/GP-3466-dragonmacher-extenions-version-check' into patch
(Closes #1193)
This commit is contained in:
Ryan Kurtz 2023-06-22 10:54:21 -04:00
commit 5e87119ef1
3 changed files with 98 additions and 83 deletions

View File

@ -99,9 +99,6 @@ class ExtensionTableModel extends ThreadedTableModel<ExtensionDetails, Object> {
} }
ExtensionDetails extension = getSelectedExtension(rowIndex); ExtensionDetails extension = getSelectedExtension(rowIndex);
if (!isValidVersion(extension)) {
return false;
}
// Do not allow GUI uninstallation of extensions manually installed in installation // Do not allow GUI uninstallation of extensions manually installed in installation
// directory // directory

View File

@ -157,9 +157,14 @@ public class ExtensionTableProvider extends DialogComponentProvider {
continue; continue;
} }
if (!hasCorrectVersion(file)) { String extensionVersion = getExtensionVersion(file);
Msg.showError(this, null, "Installation Error", "Extension version for [" + if (extensionVersion == null) {
file.getName() + "] is incompatible with Ghidra."); Msg.showError(this, null, "Installation Error",
"Unable to read extension version for [" + file + "]");
continue;
}
if (!ExtensionUtils.validateExtensionVersion(extensionVersion)) {
continue; continue;
} }
@ -188,53 +193,41 @@ public class ExtensionTableProvider extends DialogComponentProvider {
addAction(addAction); addAction(addAction);
} }
/** private String getExtensionVersion(File file) {
* Verifies that the extension(s) represented by the given file (or directory) have
* a version that is compatible with the current version of Ghidra.
*
* @param file the file or directory to inspect
* @return true if the extension(s) has the correct version
*/
private boolean hasCorrectVersion(File file) {
String ghidraVersion = Application.getApplicationVersion(); // If the given file is a directory...
if (!file.isFile()) {
List<ResourceFile> propFiles =
ExtensionUtils.findExtensionPropertyFiles(new ResourceFile(file), true);
for (ResourceFile props : propFiles) {
ExtensionDetails ext = ExtensionUtils.createExtensionDetailsFromPropertyFile(props);
String version = ext.getVersion();
if (version != null) {
return version;
}
}
return null;
}
// If the given file is a zip... // If the given file is a zip...
if (file.isFile()) {
try { try {
if (ExtensionUtils.isZip(file)) { if (ExtensionUtils.isZip(file)) {
Properties props = ExtensionUtils.getPropertiesFromArchive(file); Properties props = ExtensionUtils.getPropertiesFromArchive(file);
if (props == null) { if (props == null) {
return false; // no prop file exists return null; // no prop file exists
} }
ExtensionDetails extension = ExtensionDetails ext = ExtensionUtils.createExtensionDetailsFromProperties(props);
ExtensionUtils.createExtensionDetailsFromProperties(props); String version = ext.getVersion();
String extVersion = extension.getVersion(); if (version != null) {
if (extVersion != null && extVersion.equals(ghidraVersion)) { return version;
return true;
} }
} }
} }
catch (ExtensionException e) { catch (ExtensionException e) {
// just fall through // just fall through
} }
return null;
return false;
}
// If the given file is a directory...
List<ResourceFile> propFiles =
ExtensionUtils.findExtensionPropertyFiles(new ResourceFile(file), true);
for (ResourceFile propFile : propFiles) {
ExtensionDetails extension =
ExtensionUtils.createExtensionDetailsFromPropertyFile(propFile);
String extVersion = extension.getVersion();
if (extVersion != null && extVersion.equals(ghidraVersion)) {
return true;
}
}
return false;
} }
/** /**

View File

@ -27,6 +27,7 @@ import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import docking.DockingWindowManager; import docking.DockingWindowManager;
import docking.widgets.OptionDialog;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
import ghidra.framework.Application; import ghidra.framework.Application;
import ghidra.framework.options.PreferenceState; import ghidra.framework.options.PreferenceState;
@ -297,10 +298,9 @@ public class ExtensionUtils {
// Verify that the version of the extension is valid for this version of Ghidra. If not, // Verify that the version of the extension is valid for this version of Ghidra. If not,
// just exit without installing. // just exit without installing.
String ghidraVersion = Application.getApplicationVersion(); if (!validateExtensionVersion(extension.getVersion())) {
if (!extension.getVersion().equals(ghidraVersion)) { Msg.warn(ExtensionUtils.class, "Extension version for [" + extension.getName() +
Msg.warn(null, "Extension version for [" + extension.getName() + "] does not match Ghidra version; did not install.");
"] does not match Ghidra version; cannot install.");
return false; return false;
} }
@ -350,6 +350,31 @@ public class ExtensionUtils {
return false; return false;
} }
/**
* Compares the given extension version to the current Ghidra version. If they are different,
* then the user will be prompted to confirm the installation. This method will return true
* if the versions match or the user has chosen to install anyway.
*
* @param extensionVersion the extension version
* @return true if the versions match or the user has chosen to install anyway
*/
public static boolean validateExtensionVersion(String extensionVersion) {
if (extensionVersion == null) {
return false;
}
String ghidraVersion = Application.getApplicationVersion();
if (extensionVersion.equals(ghidraVersion)) {
return true;
}
int choice = OptionDialog.showOptionDialogWithCancelAsDefaultButton(null,
"Extension Version Mismatch",
"Extension version mismatch.\nExtension version: " + extensionVersion + "\n" +
"Ghidra version: " + ghidraVersion,
"Install Anyway");
return choice == OptionDialog.OPTION_ONE;
}
/** /**
* Returns true if the given file or directory is a valid ghidra extension. * Returns true if the given file or directory is a valid ghidra extension.
* <p> * <p>