diff --git a/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/fileinfo/FileAttributeType.java b/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/fileinfo/FileAttributeType.java index a7bffc7d57..7464dfb954 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/fileinfo/FileAttributeType.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/formats/gfilesystem/fileinfo/FileAttributeType.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -56,6 +56,7 @@ public enum FileAttributeType { SYMLINK_DEST_ATTR("Symbolic link destination", MISC_INFO, String.class), COMMENT_ATTR("Comment", MISC_INFO, String.class), + FILENAME_EXT_OVERRIDE("Extension override", MISC_INFO, String.class), // no leading '.' UNKNOWN_ATTRIBUTE("Other attribute", ADDITIONAL_INFO, Object.class); @@ -63,7 +64,7 @@ public enum FileAttributeType { private final FileAttributeTypeGroup group; private final Class valueType; - private FileAttributeType(String displayName, FileAttributeTypeGroup group, + FileAttributeType(String displayName, FileAttributeTypeGroup group, Class valueType) { this.displayName = displayName; this.group = group; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterUtilities.java b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterUtilities.java index 48bb4d5a15..12e8dc4adb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterUtilities.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugin/importer/ImporterUtilities.java @@ -59,16 +59,13 @@ public class ImporterUtilities { /** * File extension filter for well known 'loadable' files for GhidraFileChoosers. - * - * TODO: will be refactored to use file_extension_icon.xml file info. */ public static final GhidraFileFilter LOADABLE_FILES_FILTER = ExtensionFileFilter.forExtensions( - "Loadable files", "exe", "dll", "obj", "drv", "bin", "hex", "o", "a", "so", "class", "lib", "dylib"); + "Loadable files", "exe", "dll", "obj", "drv", "bin", "hex", "o", "a", "so", "class", "lib", + "dylib"); /** * File extension filter for well known 'container' files for GhidraFileChoosers. - * - * TODO: will be refactored to use file_extension_icon.xml file info. */ public static final GhidraFileFilter CONTAINER_FILES_FILTER = ExtensionFileFilter.forExtensions("Container files", "zip", "tar", "tgz", "jar", "gz", diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBComponentProvider.java index d5b8e32b55..c2cb043236 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBComponentProvider.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -192,9 +192,18 @@ public class FSBComponentProvider extends ComponentProviderAdapter overlays.add(FSBIcons.MISSING_PASSWORD_OVERLAY_ICON); } + String ext = node.getFilenameExtOverride(); + if (ext != null && !ext.isEmpty()) { + if (ext.startsWith(".")) { + Msg.error(this, + "Extension override '" + ext + "' should not begin with a dot"); + } else { + filename += "." + ext; + } + } + Icon icon = fsbIcons.getIcon(filename, overlays); setIcon(icon); - } }); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBFileNode.java b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBFileNode.java index 4c6b6c4347..16092d4927 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBFileNode.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBFileNode.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -38,6 +38,7 @@ public class FSBFileNode extends FSBNode { protected boolean hasPassword; protected String symlinkDest; protected long lastModified; + protected String filenameExtOverride; FSBFileNode(GFile file) { this.file = file; @@ -83,6 +84,17 @@ public class FSBFileNode extends FSBNode { return symlinkDest != null; } + public String getFilenameExtOverride() { + return filenameExtOverride; + } + + @Override + public String getFileExtension() { + return filenameExtOverride != null && !filenameExtOverride.isEmpty() + ? filenameExtOverride + : super.getFileExtension(); + } + @Override public int hashCode() { return file.hashCode(); @@ -95,6 +107,7 @@ public class FSBFileNode extends FSBNode { symlinkDest = fattrs.get(SYMLINK_DEST_ATTR, String.class, null); Date lastModDate = fattrs.get(MODIFIED_DATE_ATTR, Date.class, null); lastModified = lastModDate != null ? lastModDate.getTime() : 0; + filenameExtOverride = fattrs.get(FILENAME_EXT_OVERRIDE, String.class, null); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBNode.java b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBNode.java index 77394ccffe..1ef3d60012 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBNode.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBNode.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,6 +22,8 @@ import java.util.stream.Collectors; import javax.swing.Icon; import javax.swing.tree.TreePath; +import org.apache.commons.io.FilenameUtils; + import docking.widgets.tree.GTreeNode; import docking.widgets.tree.GTreeSlowLoadingNode; import ghidra.formats.gfilesystem.*; @@ -65,6 +67,15 @@ public abstract class FSBNode extends GTreeSlowLoadingNode { return getFSRL().getName(); } + /** + * Returns the extension of this node's name, or "" if none + * + * @return extension of this node's name, or "" if none + */ + public String getFileExtension() { + return FilenameUtils.getExtension(getName()); + } + public FSBRootNode getFSBRootNode() { GTreeNode node = getParent(); while (node != null) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/filehandlers/ImageFSBFileHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/filehandlers/ImageFSBFileHandler.java index 0dc29075f2..ce11503015 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/filehandlers/ImageFSBFileHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/filehandlers/ImageFSBFileHandler.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,8 +22,6 @@ import java.util.Set; import javax.swing.*; -import org.apache.commons.io.FilenameUtils; - import docking.action.DockingAction; import docking.action.builder.ActionBuilder; import docking.widgets.label.GIconLabel; @@ -48,9 +46,7 @@ public class ImageFSBFileHandler implements FSBFileHandler { @Override public boolean fileDefaultAction(FSBFileNode fileNode) { - FSRL fsrl = fileNode.getFSRL(); - String extension = FilenameUtils.getExtension(fsrl.getName().toLowerCase()); - if (COMMON_IMAGE_EXTENSIONS.contains(extension)) { + if (COMMON_IMAGE_EXTENSIONS.contains(fileNode.getFileExtension().toLowerCase())) { FSBComponentProvider fsbComponent = context.fsbComponent(); fsbComponent.runTask(monitor -> doViewAsImage(fileNode.getFSRL(), fsbComponent.getComponent(), monitor)); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/filehandlers/TextFSBFileHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/filehandlers/TextFSBFileHandler.java index 329a8255ac..163faffa9d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/filehandlers/TextFSBFileHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/filehandlers/TextFSBFileHandler.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -46,7 +46,7 @@ public class TextFSBFileHandler implements FSBFileHandler { @Override public boolean fileDefaultAction(FSBFileNode fileNode) { - if (fileNode.getName().toLowerCase().endsWith(".txt")) { + if (fileNode.getFileExtension().equalsIgnoreCase("txt")) { FSBComponentProvider fsbComponent = context.fsbComponent(); fsbComponent.runTask( monitor -> doViewAsText(fileNode.getFSRL(), fsbComponent.getComponent(), monitor));