Updated ExtensionDetails to be smarter about checking for extensions in

the installation directory
This commit is contained in:
dragonmacher 2023-07-31 20:00:23 -04:00
parent a961b069a4
commit 4552e27670
3 changed files with 75 additions and 21 deletions

View file

@ -16,7 +16,9 @@
package ghidra.framework.project.extensions;
import java.io.File;
import java.util.List;
import generic.jar.ResourceFile;
import generic.json.Json;
import ghidra.framework.Application;
import ghidra.util.Msg;
@ -250,8 +252,16 @@ public class ExtensionDetails implements Comparable<ExtensionDetails> {
}
ApplicationLayout layout = Application.getApplicationLayout();
File appInstallDir = layout.getApplicationInstallationDir().getFile(false);
if (FileUtilities.isPathContainedWithin(appInstallDir, installDir)) {
List<ResourceFile> extDirs = layout.getExtensionInstallationDirs();
if (extDirs.size() < 2) {
Msg.trace(this, "Unexpected extension installation dirs; revisit this assumption");
return false;
}
// extDirs.get(0) is the user extension dir
ResourceFile appExtDir = extDirs.get(1);
if (FileUtilities.isPathContainedWithin(appExtDir.getFile(false), installDir)) {
return true;
}
return false;

View file

@ -108,6 +108,8 @@ public class ExtensionUtils {
private static Extensions getAllInstalledExtensions() {
log.trace("Finding all installed extensions...");
Extensions extensions = new Extensions();
// Find all extension.properties or extension.properties.uninstalled files in
@ -139,6 +141,8 @@ public class ExtensionUtils {
}
}
log.trace(() -> "All installed extensions: " + extensions.getAsString());
return extensions;
}
@ -225,7 +229,7 @@ public class ExtensionUtils {
*/
public static boolean install(File file) {
log.trace("installing file " + file);
log.trace("Installing extension file " + file);
if (file == null) {
log.error("Install file cannot be null");
@ -239,11 +243,12 @@ public class ExtensionUtils {
return false;
}
if (checkForConflictWithDevelopmentExtension(extension)) {
Extensions extensions = getAllInstalledExtensions();
if (checkForConflictWithDevelopmentExtension(extension, extensions)) {
return false;
}
if (checkForDuplicateExtensions(extension)) {
if (checkForDuplicateExtensions(extension, extensions)) {
return false;
}
@ -355,15 +360,19 @@ public class ExtensionUtils {
return s.replaceAll("\n", " ");
}
private static boolean checkForDuplicateExtensions(ExtensionDetails newExtension) {
private static boolean checkForDuplicateExtensions(ExtensionDetails newExtension,
Extensions extensions) {
String name = newExtension.getName();
log.trace("Checking for duplicate extensions for '" + name + "'");
Extensions extensions = getAllInstalledExtensions();
List<ExtensionDetails> matches = extensions.getMatchingExtensions(newExtension);
if (matches.isEmpty()) {
log.trace("No matching extensions installed");
return false;
}
log.trace("Duplicate extensions found by name '" + newExtension.getName() + "'");
log.trace("Duplicate extensions found by name '" + name + "'");
if (matches.size() > 1) {
reportMultipleDuplicateExtensionsWhenInstalling(newExtension, matches);
@ -432,11 +441,15 @@ public class ExtensionUtils {
}
}
private static boolean checkForConflictWithDevelopmentExtension(ExtensionDetails newExtension) {
private static boolean checkForConflictWithDevelopmentExtension(ExtensionDetails newExtension,
Extensions extensions) {
String name = newExtension.getName();
log.trace("Checking for duplicate dev mode extensions for '" + name + "'");
Extensions extensions = getAllInstalledExtensions();
List<ExtensionDetails> matches = extensions.getMatchingExtensions(newExtension);
if (matches.isEmpty()) {
log.trace("No matching extensions installed");
return false;
}
@ -444,11 +457,14 @@ public class ExtensionUtils {
if (extension.isInstalledInInstallationFolder()) {
OkDialog.showError("Duplicate Extensions Found",
"Attempting to install an extension that conflicts with an extension located in " +
"the Ghidra installation folder.\nYou must manually remove the existing " +
"extension to install the new extension.\nExisting extension: " +
extension.getInstallDir());
String message = "Attempting to install an extension that conflicts with an " +
"extension located in the Ghidra installation folder.\nYou must manually " +
"remove the existing extension to install the new extension.\nExisting " +
"extension: " + extension.getInstallDir();
log.trace(removeNewlines(message));
OkDialog.showError("Duplicate Extensions Found", message);
return true;
}
}
@ -686,6 +702,8 @@ public class ExtensionUtils {
if (hasExistingExtension(newDir, monitor)) {
return false;
}
log.trace("Copying extension to " + newDir);
FileUtilities.copyDir(sourceFolder, newDir, monitor);
return true;
}
@ -949,5 +967,35 @@ public class ExtensionUtils {
.map(list -> list.get(0))
.collect(Collectors.toSet());
}
String getAsString() {
StringBuilder buffy = new StringBuilder();
Set<Entry<String, List<ExtensionDetails>>> entries = extensionsByName.entrySet();
for (Entry<String, List<ExtensionDetails>> entry : entries) {
String name = entry.getKey();
buffy.append("Name: ").append(name);
List<ExtensionDetails> extensions = entry.getValue();
if (extensions.size() == 1) {
buffy.append(" - ").append(extensions.get(0).getInstallDir()).append('\n');
}
else {
for (ExtensionDetails e : extensions) {
buffy.append("\t").append(e.getInstallDir()).append('\n');
}
}
}
if (buffy.isEmpty()) {
return "<no extensions installed>";
}
if (!buffy.isEmpty()) {
// remove trailing newline to keep logging consistent
buffy.deleteCharAt(buffy.length() - 1);
}
return buffy.toString();
}
}
}

View file

@ -24,7 +24,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.junit.*;
import org.junit.Before;
import org.junit.Test;
import docking.DialogComponentProvider;
import docking.test.AbstractDockingTest;
@ -78,11 +79,6 @@ public class ExtensionUtilsTest extends AbstractDockingTest {
}
}
@After
public void tearDown() {
sleep(1000);
}
/*
* Verifies that we can install an extension from a .zip file.
*/