Resource File Types
File Header Magic Numbers still need to be implemented but it's a start
This commit is contained in:
parent
e16397ebd6
commit
c259ac70a2
10 changed files with 120 additions and 75 deletions
|
@ -1,5 +1,7 @@
|
|||
package the.bytecode.club.bytecodeviewer;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.resources.ResourceType;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
|
||||
|
@ -35,7 +37,7 @@ public class Constants
|
|||
public static final String libsDirectory = getBCVDirectory() + fs + "libs" + fs;
|
||||
public static String krakatauWorkingDirectory = getBCVDirectory() + fs + "krakatau_" + krakatauVersion;
|
||||
public static String enjarifyWorkingDirectory = getBCVDirectory() + fs + "enjarify_" + enjarifyVersion;
|
||||
public static final String[] SUPPORTED_FILE_EXTENSIONS = new String[]{"jar", "zip", "class", "apk", "xapk", "dex", "war", "jsp"};
|
||||
public static final String[] SUPPORTED_FILE_EXTENSIONS = ResourceType.supportedBCVExtensionMap.keySet().toArray(new String[0]);
|
||||
|
||||
public static final PrintStream ERR = System.err;
|
||||
public static final PrintStream OUT = System.out;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package the.bytecode.club.bytecodeviewer.gui.resourcelist;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import the.bytecode.club.bytecodeviewer.resources.IconResources;
|
||||
import the.bytecode.club.bytecodeviewer.resources.ResourceType;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
|
@ -14,81 +16,42 @@ import java.util.ArrayList;
|
|||
*/
|
||||
public class ImageRenderer extends DefaultTreeCellRenderer
|
||||
{
|
||||
//called every time there is a pane update, I.E. whenever you expand a folder
|
||||
//called every time there is a pane update
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(
|
||||
JTree tree, Object value,
|
||||
boolean sel, boolean expanded, boolean leaf,
|
||||
int row, boolean hasFocus)
|
||||
{
|
||||
|
||||
Component ret = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
|
||||
|
||||
if (value instanceof ResourceTreeNode)
|
||||
{
|
||||
ResourceTreeNode node = (ResourceTreeNode) value;
|
||||
String name = node.toString().toLowerCase();
|
||||
String onlyName = FilenameUtils.getName(name);
|
||||
boolean iconSet = false;
|
||||
|
||||
if (name.endsWith(".jar") || name.endsWith(".war") || name.endsWith(".ear"))
|
||||
//guess file type based on extension
|
||||
ResourceType knownResourceType = onlyName.contains(":") ? null
|
||||
: ResourceType.extensionMap.get(FilenameUtils.getExtension(onlyName).toLowerCase());
|
||||
|
||||
//set the icon to a known file type
|
||||
if (knownResourceType != null)
|
||||
{
|
||||
setIcon(IconResources.jarIcon);
|
||||
}
|
||||
else if (name.endsWith(".zip"))
|
||||
{
|
||||
setIcon(IconResources.zipIcon);
|
||||
}
|
||||
else if (name.endsWith(".bat"))
|
||||
{
|
||||
setIcon(IconResources.batIcon);
|
||||
}
|
||||
else if (name.endsWith(".sh"))
|
||||
{
|
||||
setIcon(IconResources.shIcon);
|
||||
}
|
||||
else if (name.endsWith(".cs"))
|
||||
{
|
||||
setIcon(IconResources.csharpIcon);
|
||||
}
|
||||
else if (name.endsWith(".c") || name.endsWith(".cpp") || name.endsWith(".h"))
|
||||
{
|
||||
setIcon(IconResources.cplusplusIcon);
|
||||
}
|
||||
else if (name.endsWith(".xapk") || name.endsWith(".apk") || name.endsWith(".dex"))
|
||||
{
|
||||
setIcon(IconResources.androidIcon);
|
||||
}
|
||||
else if (name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg")
|
||||
|| name.endsWith(".bmp") || name.endsWith(".gif"))
|
||||
{
|
||||
setIcon(IconResources.imageIcon);
|
||||
}
|
||||
else if (name.endsWith(".class"))
|
||||
{
|
||||
setIcon(IconResources.classIcon);
|
||||
}
|
||||
else if (name.endsWith(".java"))
|
||||
{
|
||||
setIcon(IconResources.javaIcon);
|
||||
}
|
||||
else if (name.endsWith(".txt") || name.endsWith(".md"))
|
||||
{
|
||||
setIcon(IconResources.textIcon);
|
||||
setIcon(knownResourceType.getIcon());
|
||||
iconSet = true;
|
||||
}
|
||||
//hardcoded resource icons go here
|
||||
else if (name.equals("decoded resources"))
|
||||
{
|
||||
setIcon(IconResources.decodedIcon);
|
||||
iconSet = true;
|
||||
}
|
||||
else if (name.endsWith(".properties") || name.endsWith(".xml") || name.endsWith(".jsp")
|
||||
|| name.endsWith(".mf") || name.endsWith(".config") || name.endsWith(".cfg"))
|
||||
|
||||
//folders
|
||||
if (node.getChildCount() > 0)
|
||||
{
|
||||
setIcon(IconResources.configIcon);
|
||||
}
|
||||
else if (node.getChildCount() <= 0)
|
||||
{ //random file
|
||||
setIcon(IconResources.fileIcon);
|
||||
}
|
||||
else
|
||||
{ //folder
|
||||
ArrayList<TreeNode> nodes = new ArrayList<>();
|
||||
ArrayList<TreeNode> totalNodes = new ArrayList<>();
|
||||
|
||||
|
@ -127,13 +90,19 @@ public class ImageRenderer extends DefaultTreeCellRenderer
|
|||
}
|
||||
}
|
||||
|
||||
if (isJava)
|
||||
setIcon(IconResources.packagesIcon);
|
||||
else
|
||||
if(!iconSet)
|
||||
{
|
||||
setIcon(IconResources.folderIcon);
|
||||
//java packages
|
||||
if (isJava)
|
||||
setIcon(IconResources.packagesIcon);
|
||||
else //regular folders
|
||||
setIcon(IconResources.folderIcon);
|
||||
}
|
||||
}
|
||||
|
||||
//unknown files
|
||||
else if (knownResourceType == null)
|
||||
setIcon(IconResources.fileIcon);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -7,6 +7,7 @@ import javax.swing.JButton;
|
|||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.imgscalr.Scalr;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||
|
@ -14,6 +15,7 @@ import the.bytecode.club.bytecodeviewer.gui.components.ImageJLabel;
|
|||
import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea;
|
||||
import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor;
|
||||
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
|
||||
import the.bytecode.club.bytecodeviewer.resources.ResourceType;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.SyntaxLanguage;
|
||||
|
||||
|
@ -70,14 +72,23 @@ public class FileViewer extends ResourceViewer
|
|||
public void setContents()
|
||||
{
|
||||
final String nameLowerCase = this.name.toLowerCase();
|
||||
final String onlyName = FilenameUtils.getName(nameLowerCase);
|
||||
final String contentsAsString = new String(contents);
|
||||
|
||||
//image viewer
|
||||
if (!MiscUtils.isPureAscii(contentsAsString))
|
||||
{
|
||||
//TODO webp?
|
||||
if (nameLowerCase.endsWith(".png") || nameLowerCase.endsWith(".jpg") || nameLowerCase.endsWith(".jpeg") ||
|
||||
nameLowerCase.endsWith(".gif") || nameLowerCase.endsWith(".tif") || nameLowerCase.endsWith(".bmp"))
|
||||
//TODO:
|
||||
// + Webp?
|
||||
// + Add file header checks
|
||||
// + Check for CAFEBABE
|
||||
// + ClassRead then quick-decompile using Pane1 Decompiler
|
||||
// (If none selected, try Pane2, Pane3, default to Proycon)
|
||||
|
||||
|
||||
//check by file extension to display image
|
||||
if (!onlyName.contains(":") &&
|
||||
ResourceType.imageExtensionMap.containsKey(FilenameUtils.getExtension(onlyName)))
|
||||
{
|
||||
canRefresh = true;
|
||||
|
||||
|
@ -101,9 +112,6 @@ public class FileViewer extends ResourceViewer
|
|||
});
|
||||
return;
|
||||
}
|
||||
//check for CAFEBABE
|
||||
//ClassRead then quick-decompile using Pane1 Decompiler
|
||||
// (If none selected, try Pane2, Pane3, default to Proycon)
|
||||
|
||||
//hex viewer
|
||||
else if (BytecodeViewer.viewer.forcePureAsciiAsText.isSelected())
|
||||
|
|
|
@ -13,7 +13,6 @@ import org.objectweb.asm.tree.ClassNode;
|
|||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.api.Plugin;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.PluginLaunchStrategy;
|
||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -88,7 +87,7 @@ public class CompiledJavaPluginLaunchStrategy implements PluginLaunchStrategy {
|
|||
if (name.endsWith(".class"))
|
||||
{
|
||||
byte[] bytes = MiscUtils.getBytes(jis);
|
||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||
if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
|
||||
{
|
||||
try {
|
||||
ClassReader cr = new ClassReader(bytes);
|
||||
|
|
|
@ -104,7 +104,7 @@ public class ResourceContainerImporter
|
|||
public ResourceContainerImporter addClassResource(String name, InputStream stream) throws IOException
|
||||
{
|
||||
byte[] bytes = MiscUtils.getBytes(stream);
|
||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||
if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package the.bytecode.club.bytecodeviewer.resources;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
* @since 7/13/2021
|
||||
*/
|
||||
|
||||
public enum ResourceType
|
||||
{
|
||||
CLASS_FILE(IconResources.classIcon, "class"),
|
||||
JAVA_ARCHIVE(IconResources.jarIcon, "jar", "war", "ear"),
|
||||
ZIP_ARCHIVE(IconResources.zipIcon, "zip"),
|
||||
ANDROID_ARCHIVE(IconResources.androidIcon, "apk", "wapk", "dex"),
|
||||
IMAGE_FILE(IconResources.imageIcon, "png", "jpg", "jpeg", "bmp", "wbmp", "gif", "tif"),
|
||||
CONFIG_TEXT_FILE(IconResources.configIcon, "properties", "xml", "jsp", "mf", "config", "config", "yaml", "ini", "json"),
|
||||
JAVA_FILE(IconResources.javaIcon, "java"),
|
||||
TEXT_FILE(IconResources.textIcon, "txt", "md", "log"),
|
||||
CPP_FILE(IconResources.cplusplusIcon, "c", "cpp", "h"),
|
||||
CSHAR_FILE(IconResources.csharpIcon, "cs"),
|
||||
BAT_FILE(IconResources.batIcon, "bat", "batch"),
|
||||
SH_FILE(IconResources.shIcon, "sh", "bash"),
|
||||
;
|
||||
|
||||
public static final HashMap<String, ResourceType> extensionMap = new HashMap<>();
|
||||
public static final HashMap<String, ResourceType> imageExtensionMap = new HashMap<>();
|
||||
public static final HashMap<String, ResourceType> supportedBCVExtensionMap = new HashMap<>();
|
||||
|
||||
private final ImageIcon icon;
|
||||
private final String[] extensions;
|
||||
//private final byte[][] headerMagicNumber;
|
||||
|
||||
static
|
||||
{
|
||||
//add all extensions
|
||||
for(ResourceType t : values())
|
||||
for(String extension : t.extensions)
|
||||
extensionMap.put(extension, t);
|
||||
|
||||
//add image extensions
|
||||
for(String extension : IMAGE_FILE.extensions)
|
||||
imageExtensionMap.put(extension, IMAGE_FILE);
|
||||
|
||||
//add extensions BCV can be opened with
|
||||
for(String extension : CLASS_FILE.extensions)
|
||||
supportedBCVExtensionMap.put(extension, CLASS_FILE);
|
||||
for(String extension : JAVA_ARCHIVE.extensions)
|
||||
supportedBCVExtensionMap.put(extension, JAVA_ARCHIVE);
|
||||
for(String extension : ZIP_ARCHIVE.extensions)
|
||||
supportedBCVExtensionMap.put(extension, ZIP_ARCHIVE);
|
||||
for(String extension : ANDROID_ARCHIVE.extensions)
|
||||
supportedBCVExtensionMap.put(extension, ANDROID_ARCHIVE);
|
||||
}
|
||||
|
||||
ResourceType(ImageIcon icon, String... extensions)
|
||||
{
|
||||
this.icon = icon;
|
||||
this.extensions = extensions;
|
||||
}
|
||||
|
||||
public ImageIcon getIcon()
|
||||
{
|
||||
return icon;
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ public class ClassResourceImporter implements Importer
|
|||
byte[] bytes = MiscUtils.getBytes(new FileInputStream(file));
|
||||
ResourceContainer container = new ResourceContainer(file);
|
||||
|
||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||
if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
|
||||
{
|
||||
final ClassNode cn = JarUtils.getNode(bytes);
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ public class DirectoryResourceImporter implements Importer
|
|||
else if (fileName.endsWith(".class"))
|
||||
{
|
||||
byte[] bytes = Files.readAllBytes(Paths.get(child.getAbsolutePath()));
|
||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||
if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
|
||||
{
|
||||
final ClassNode cn = JarUtils.getNode(bytes);
|
||||
allDirectoryClasses.put(FilenameUtils.removeExtension(trimmedPath), cn);
|
||||
|
|
|
@ -77,7 +77,7 @@ public class JarUtils
|
|||
if (!entry.isDirectory())
|
||||
files.put(name, bytes);
|
||||
} else {
|
||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||
if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
|
||||
{
|
||||
try {
|
||||
final ClassNode cn = getNode(bytes);
|
||||
|
@ -133,7 +133,7 @@ public class JarUtils
|
|||
if (!name.endsWith(".class")) {
|
||||
files.put(name, bytes);
|
||||
} else {
|
||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||
if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
|
||||
{
|
||||
try {
|
||||
final ClassNode cn = getNode(bytes);
|
||||
|
@ -165,7 +165,7 @@ public class JarUtils
|
|||
final String name = entry.getName();
|
||||
if (name.endsWith(".class")) {
|
||||
byte[] bytes = MiscUtils.getBytes(jis);
|
||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||
if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
|
||||
{
|
||||
try {
|
||||
final ClassNode cn = getNode(bytes);
|
||||
|
|
|
@ -160,7 +160,7 @@ public class MiscUtils
|
|||
return i;
|
||||
}
|
||||
|
||||
public static String getFileHeader(byte[] fileContents)
|
||||
public static String getFileHeaderMagicNumber(byte[] fileContents)
|
||||
{
|
||||
return String.format("%02X%02X%02X%02X", fileContents[0],
|
||||
fileContents[1], fileContents[2],fileContents[3]);
|
||||
|
|
Loading…
Reference in a new issue