Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz 2023-07-24 18:00:22 -04:00
commit 8028c54abe
8 changed files with 185 additions and 25 deletions

View File

@ -310,7 +310,7 @@ public class DebuggerPcodeStepperProvider extends ComponentProviderAdapter {
}
protected static String htmlColor(Color color, String display) {
return String.format("<font color=\"%s\">%s</font>", WebColors.toString(color),
return String.format("<font color=\"%s\">%s</font>", WebColors.toString(color, false),
HTMLUtilities.escapeHTML(display));
}

View File

@ -123,7 +123,7 @@ public abstract class AbstractAddressRangeFilter<T> extends AncillaryFilter<T>
//
// Lower Score Panel
//
String fgColor = WebColors.toString(FG_TOOLTIP_DEFAULT);
String fgColor = WebColors.toString(FG_TOOLTIP_DEFAULT, false);
lowerRangePanel = new JPanel(new GridLayout(2, 1));
JLabel lowLabel =
new GHtmlLabel("<html><font size=\"2\" color=\"" + fgColor + "\">low</font>");

View File

@ -88,7 +88,8 @@ public class ColorEditor extends PropertyEditorSupport {
private void updateColor(Color newColor) {
// change the color to a darker value if the color being set is light
String colorString = WebColors.toString(ColorUtils.contrastForegroundColor(newColor));
String colorString =
WebColors.toString(ColorUtils.contrastForegroundColor(newColor), false);
previewLabel.setText(
"<HTML><CENTER><I><FONT SIZE=2 COLOR=" + colorString + ">click</FONT></I></CENTER>");

View File

@ -132,6 +132,21 @@ public class ClientUtil {
return rsa;
}
/**
* Determine if a connected {@link RepositoryServerAdapter} already exists for the specified server.
* @param host server name or address
* @param port server port, 0 indicates that default port applies.
* @return true if connection already exists, else false
*/
public static boolean isConnected(String host, int port) {
if (port <= 0) {
port = GhidraServerHandle.DEFAULT_PORT;
}
ServerInfo server = new ServerInfo(host, port);
RepositoryServerAdapter rsa = serverHandles.get(server);
return rsa != null && rsa.isConnected();
}
/**
* Eliminate the specified repository server from the connection cache
* @param host host name or IP address

View File

@ -23,6 +23,11 @@ import java.util.Map;
* Class for web color support. This class defines many of the colors used by html. This class
* includes methods for converting a color to a string (name or hex value) and for converting
* those strings back to a color.
* <p>
* Usage Note: Java's HTML rendering engine supports colors in hex form ('#aabb11'). Also, the
* engine supports many web color names ('silver'). However, not all web color names defined in
* this file are supported. Thus, when specifying HTML colors, do not rely on these web color
* names.
*/
public abstract class WebColors {
private static final Map<String, Color> nameToColorMap = new HashMap<>();
@ -229,7 +234,7 @@ public abstract class WebColors {
}
/**
* Returns the hex value string for the given color
* Returns the hex value string for the given color
* @param color the color
* @return the string
*/
@ -382,7 +387,7 @@ public abstract class WebColors {
value = value.substring(4, value.length() - 1);
}
// strip off to comma separated values
// strip off to comma separated values
String[] split = value.split(",");
if (split.length != 3) {
return null;
@ -404,7 +409,7 @@ public abstract class WebColors {
value = value.substring(5, value.length() - 1);
}
// strip off to comma separated values
// strip off to comma separated values
value = value.replaceAll(" ", "");
String[] split = value.split(",");
if (split.length != 4) {

View File

@ -23,8 +23,10 @@ import java.util.*;
import javax.swing.Icon;
import ghidra.framework.client.*;
import ghidra.framework.model.*;
import ghidra.framework.protocol.ghidra.GhidraURL;
import ghidra.framework.remote.RepositoryItem;
import ghidra.framework.store.ItemCheckoutStatus;
import ghidra.framework.store.Version;
import ghidra.framework.store.db.PackedDatabase;
@ -114,25 +116,81 @@ public class DomainFileProxy implements DomainFile {
return parentPath + DomainFolder.SEPARATOR + getName();
}
private URL getSharedFileURL(URL sharedProjectURL) {
try {
// Direct URL construction done so that ghidra protocol
// extension may be supported
String urlStr = sharedProjectURL.toExternalForm();
if (urlStr.endsWith("/")) {
urlStr = urlStr.substring(0, urlStr.length() - 1);
}
urlStr += getPathname();
return new URL(urlStr);
}
catch (MalformedURLException e) {
// ignore
}
return null;
}
private URL getSharedFileURL(Properties properties) {
if (properties == null) {
return null;
}
String serverName = properties.getProperty(ProjectFileManager.SERVER_NAME);
String repoName = properties.getProperty(ProjectFileManager.REPOSITORY_NAME);
if (serverName == null || repoName == null) {
return null;
}
int port = Integer.parseInt(properties.getProperty(ProjectFileManager.PORT_NUMBER, "0"));
if (!ClientUtil.isConnected(serverName, port)) {
return null; // avoid initiating a server connection.
}
RepositoryAdapter repository = null;
try {
RepositoryServerAdapter repositoryServer =
ClientUtil.getRepositoryServer(serverName, port);
Set<String> repoNames = Set.of(repositoryServer.getRepositoryNames());
if (!repoNames.contains(repoName)) {
return null; // only consider repos which user has access to
}
repository = repositoryServer.getRepository(repoName);
if (repository == null) {
return null;
}
repository.connect();
RepositoryItem item = repository.getItem(parentPath, name);
if (item == null || !Objects.equals(item.getFileID(), fileID)) {
return null;
}
ServerInfo serverInfo = repository.getServerInfo();
return GhidraURL.makeURL(serverInfo.getServerName(),
serverInfo.getPortNumber(), repository.getName(),
item.getPathName());
}
catch (IOException e) {
// ignore
}
finally {
if (repository != null) {
repository.disconnect();
}
}
return null;
}
@Override
public URL getSharedProjectURL() {
if (projectLocation != null && version == DomainFile.DEFAULT_VERSION) {
URL projectURL = projectLocation.getURL();
if (GhidraURL.isServerRepositoryURL(projectURL)) {
try {
// Direct URL construction done so that ghidra protocol
// extension may be supported
String urlStr = projectURL.toExternalForm();
if (urlStr.endsWith("/")) {
urlStr = urlStr.substring(0, urlStr.length() - 1);
}
urlStr += getPathname();
return new URL(urlStr);
}
catch (MalformedURLException e) {
// ignore
}
return getSharedFileURL(projectURL);
}
Properties properties =
ProjectFileManager.readProjectProperties(projectLocation.getProjectDir());
return getSharedFileURL(properties);
}
return null;
}

View File

@ -49,10 +49,11 @@ public class ProjectFileManager implements ProjectData {
private static final String TEST_REPOSITORY_PATH = System.getProperty("Repository");
private static final String SERVER_NAME = "SERVER";
private static final String PORT_NUMBER = "PORT_NUMBER";
private static final String REPOSITORY_NAME = "REPOSITORY_NAME";
private static final String OWNER = "OWNER";
public static final String SERVER_NAME = "SERVER";
public static final String PORT_NUMBER = "PORT_NUMBER";
public static final String REPOSITORY_NAME = "REPOSITORY_NAME";
public static final String OWNER = "OWNER";
private static final String PROPERTY_FILENAME = "project";
private static final int USER_DATA_RECONCILE_DELAY_MS = 5 * 60 * 1000; // 5-minutes
@ -204,6 +205,38 @@ public class ProjectFileManager implements ProjectData {
}
}
/**
* Read the contents of the project properties file to include the following values if relavent:
* {@value #OWNER}, {@value #SERVER_NAME}, {@value #REPOSITORY_NAME}, {@value #PORT_NUMBER}
* @param projectDir project directory (*.rep)
* @return project properties or null if invalid project directory specified
*/
public static Properties readProjectProperties(File projectDir) {
try {
PropertyFile pf =
new PropertyFile(projectDir, PROPERTY_FILENAME, "/", PROPERTY_FILENAME);
if (pf.exists()) {
Properties properties = new Properties();
properties.setProperty(OWNER, pf.getString(OWNER, null));
String serverName = pf.getString(SERVER_NAME, null);
String repoName = pf.getString(REPOSITORY_NAME, null);
int port = pf.getInt(PORT_NUMBER, 0);
if (serverName != null && repoName != null) {
properties.setProperty(SERVER_NAME, serverName);
properties.setProperty(REPOSITORY_NAME, repoName);
properties.setProperty(PORT_NUMBER, Integer.toString(port));
}
return properties;
}
}
catch (IOException e) {
// ignore
}
return null;
}
private void init(boolean create, boolean isInWritableProject)
throws IOException, LockException {

View File

@ -22,8 +22,8 @@ import db.DBConstants;
import generic.jar.ResourceFile;
import ghidra.framework.store.db.PackedDBHandle;
import ghidra.framework.store.db.PackedDatabase;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.*;
import ghidra.program.util.DefaultLanguageService;
import ghidra.util.InvalidNameException;
import ghidra.util.UniversalID;
import ghidra.util.exception.*;
@ -98,6 +98,54 @@ public class FileDataTypeManager extends StandAloneDataTypeManager
}
}
/**
* Create a new data-type file archive using the default data organization
* @param packedDbfile archive file (filename must end with DataTypeFileManager.SUFFIX)
* @return data-type manager backed by specified packedDbFile
* @throws IOException if an IO error occurs
*/
public static FileDataTypeManager createFileArchive(File packedDbfile, LanguageID languageId,
CompilerSpecID compilerSpecId)
throws LanguageNotFoundException, CompilerSpecNotFoundException, IOException {
try {
FileDataTypeManager dtm =
new FileDataTypeManager(new ResourceFile(packedDbfile), DBConstants.CREATE,
TaskMonitor.DUMMY);
LanguageService languageService = DefaultLanguageService.getLanguageService();
Language language = languageService.getLanguage(languageId);
CompilerSpec compilerSpec = language.getCompilerSpecByID(compilerSpecId);
//dtm.setProgramArchitecture()
return dtm;
}
catch (CancelledException e) {
throw new AssertException(e); // unexpected without task monitor use
}
}
/**
* Create a new data-type file archive using the default data organization
* @param packedDbfile archive file (filename must end with DataTypeFileManager.SUFFIX)
* @return data-type manager backed by specified packedDbFile
* @throws IOException if an IO error occurs
*/
public static FileDataTypeManager createFileArchive(File packedDbfile, String languageId,
String compilerSpecId) throws IOException {
try {
FileDataTypeManager dtm =
new FileDataTypeManager(new ResourceFile(packedDbfile), DBConstants.CREATE,
TaskMonitor.DUMMY);
//dtm.setProgramArchitecture()
return dtm;
}
catch (CancelledException e) {
throw new AssertException(e); // unexpected without task monitor use
}
}
/**
* Open an existing data-type file archive using the default data organization.
* <p>