Resource File Types

File Header Magic Numbers still need to be implemented but it's a start
This commit is contained in:
Konloch 2021-07-14 02:59:36 -07:00
parent e16397ebd6
commit c259ac70a2
10 changed files with 120 additions and 75 deletions

View file

@ -1,5 +1,7 @@
package the.bytecode.club.bytecodeviewer; package the.bytecode.club.bytecodeviewer;
import the.bytecode.club.bytecodeviewer.resources.ResourceType;
import java.io.File; import java.io.File;
import java.io.PrintStream; import java.io.PrintStream;
@ -35,7 +37,7 @@ public class Constants
public static final String libsDirectory = getBCVDirectory() + fs + "libs" + fs; public static final String libsDirectory = getBCVDirectory() + fs + "libs" + fs;
public static String krakatauWorkingDirectory = getBCVDirectory() + fs + "krakatau_" + krakatauVersion; public static String krakatauWorkingDirectory = getBCVDirectory() + fs + "krakatau_" + krakatauVersion;
public static String enjarifyWorkingDirectory = getBCVDirectory() + fs + "enjarify_" + enjarifyVersion; 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 ERR = System.err;
public static final PrintStream OUT = System.out; public static final PrintStream OUT = System.out;

View file

@ -1,6 +1,8 @@
package the.bytecode.club.bytecodeviewer.gui.resourcelist; 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.IconResources;
import the.bytecode.club.bytecodeviewer.resources.ResourceType;
import javax.swing.*; import javax.swing.*;
import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeCellRenderer;
@ -14,81 +16,42 @@ import java.util.ArrayList;
*/ */
public class ImageRenderer extends DefaultTreeCellRenderer 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 @Override
public Component getTreeCellRendererComponent( public Component getTreeCellRendererComponent(
JTree tree, Object value, JTree tree, Object value,
boolean sel, boolean expanded, boolean leaf, boolean sel, boolean expanded, boolean leaf,
int row, boolean hasFocus) int row, boolean hasFocus)
{ {
Component ret = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); Component ret = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
if (value instanceof ResourceTreeNode) if (value instanceof ResourceTreeNode)
{ {
ResourceTreeNode node = (ResourceTreeNode) value; ResourceTreeNode node = (ResourceTreeNode) value;
String name = node.toString().toLowerCase(); 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); setIcon(knownResourceType.getIcon());
} iconSet = true;
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);
} }
//hardcoded resource icons go here
else if (name.equals("decoded resources")) else if (name.equals("decoded resources"))
{ {
setIcon(IconResources.decodedIcon); 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> nodes = new ArrayList<>();
ArrayList<TreeNode> totalNodes = new ArrayList<>(); ArrayList<TreeNode> totalNodes = new ArrayList<>();
@ -127,13 +90,19 @@ public class ImageRenderer extends DefaultTreeCellRenderer
} }
} }
if(!iconSet)
{
//java packages
if (isJava) if (isJava)
setIcon(IconResources.packagesIcon); setIcon(IconResources.packagesIcon);
else else //regular folders
{
setIcon(IconResources.folderIcon); setIcon(IconResources.folderIcon);
} }
} }
//unknown files
else if (knownResourceType == null)
setIcon(IconResources.fileIcon);
} }
return ret; return ret;

View file

@ -7,6 +7,7 @@ import javax.swing.JButton;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import org.apache.commons.io.FilenameUtils;
import org.imgscalr.Scalr; import org.imgscalr.Scalr;
import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Configuration; 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.components.SearchableRSyntaxTextArea;
import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor; import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor;
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer; 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.MiscUtils;
import the.bytecode.club.bytecodeviewer.util.SyntaxLanguage; import the.bytecode.club.bytecodeviewer.util.SyntaxLanguage;
@ -70,14 +72,23 @@ public class FileViewer extends ResourceViewer
public void setContents() public void setContents()
{ {
final String nameLowerCase = this.name.toLowerCase(); final String nameLowerCase = this.name.toLowerCase();
final String onlyName = FilenameUtils.getName(nameLowerCase);
final String contentsAsString = new String(contents); final String contentsAsString = new String(contents);
//image viewer //image viewer
if (!MiscUtils.isPureAscii(contentsAsString)) if (!MiscUtils.isPureAscii(contentsAsString))
{ {
//TODO webp? //TODO:
if (nameLowerCase.endsWith(".png") || nameLowerCase.endsWith(".jpg") || nameLowerCase.endsWith(".jpeg") || // + Webp?
nameLowerCase.endsWith(".gif") || nameLowerCase.endsWith(".tif") || nameLowerCase.endsWith(".bmp")) // + 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; canRefresh = true;
@ -101,9 +112,6 @@ public class FileViewer extends ResourceViewer
}); });
return; return;
} }
//check for CAFEBABE
//ClassRead then quick-decompile using Pane1 Decompiler
// (If none selected, try Pane2, Pane3, default to Proycon)
//hex viewer //hex viewer
else if (BytecodeViewer.viewer.forcePureAsciiAsText.isSelected()) else if (BytecodeViewer.viewer.forcePureAsciiAsText.isSelected())

View file

@ -13,7 +13,6 @@ import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.api.Plugin; import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.plugin.PluginLaunchStrategy; import the.bytecode.club.bytecodeviewer.plugin.PluginLaunchStrategy;
import the.bytecode.club.bytecodeviewer.util.JarUtils;
import the.bytecode.club.bytecodeviewer.util.MiscUtils; import the.bytecode.club.bytecodeviewer.util.MiscUtils;
/*************************************************************************** /***************************************************************************
@ -88,7 +87,7 @@ public class CompiledJavaPluginLaunchStrategy implements PluginLaunchStrategy {
if (name.endsWith(".class")) if (name.endsWith(".class"))
{ {
byte[] bytes = MiscUtils.getBytes(jis); byte[] bytes = MiscUtils.getBytes(jis);
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe")) if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
{ {
try { try {
ClassReader cr = new ClassReader(bytes); ClassReader cr = new ClassReader(bytes);

View file

@ -104,7 +104,7 @@ public class ResourceContainerImporter
public ResourceContainerImporter addClassResource(String name, InputStream stream) throws IOException public ResourceContainerImporter addClassResource(String name, InputStream stream) throws IOException
{ {
byte[] bytes = MiscUtils.getBytes(stream); byte[] bytes = MiscUtils.getBytes(stream);
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe")) if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
{ {
try try
{ {

View file

@ -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;
}
}

View file

@ -24,7 +24,7 @@ public class ClassResourceImporter implements Importer
byte[] bytes = MiscUtils.getBytes(new FileInputStream(file)); byte[] bytes = MiscUtils.getBytes(new FileInputStream(file));
ResourceContainer container = new ResourceContainer(file); ResourceContainer container = new ResourceContainer(file);
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe")) if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
{ {
final ClassNode cn = JarUtils.getNode(bytes); final ClassNode cn = JarUtils.getNode(bytes);

View file

@ -70,7 +70,7 @@ public class DirectoryResourceImporter implements Importer
else if (fileName.endsWith(".class")) else if (fileName.endsWith(".class"))
{ {
byte[] bytes = Files.readAllBytes(Paths.get(child.getAbsolutePath())); 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); final ClassNode cn = JarUtils.getNode(bytes);
allDirectoryClasses.put(FilenameUtils.removeExtension(trimmedPath), cn); allDirectoryClasses.put(FilenameUtils.removeExtension(trimmedPath), cn);

View file

@ -77,7 +77,7 @@ public class JarUtils
if (!entry.isDirectory()) if (!entry.isDirectory())
files.put(name, bytes); files.put(name, bytes);
} else { } else {
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe")) if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
{ {
try { try {
final ClassNode cn = getNode(bytes); final ClassNode cn = getNode(bytes);
@ -133,7 +133,7 @@ public class JarUtils
if (!name.endsWith(".class")) { if (!name.endsWith(".class")) {
files.put(name, bytes); files.put(name, bytes);
} else { } else {
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe")) if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
{ {
try { try {
final ClassNode cn = getNode(bytes); final ClassNode cn = getNode(bytes);
@ -165,7 +165,7 @@ public class JarUtils
final String name = entry.getName(); final String name = entry.getName();
if (name.endsWith(".class")) { if (name.endsWith(".class")) {
byte[] bytes = MiscUtils.getBytes(jis); byte[] bytes = MiscUtils.getBytes(jis);
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe")) if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
{ {
try { try {
final ClassNode cn = getNode(bytes); final ClassNode cn = getNode(bytes);

View file

@ -160,7 +160,7 @@ public class MiscUtils
return i; return i;
} }
public static String getFileHeader(byte[] fileContents) public static String getFileHeaderMagicNumber(byte[] fileContents)
{ {
return String.format("%02X%02X%02X%02X", fileContents[0], return String.format("%02X%02X%02X%02X", fileContents[0],
fileContents[1], fileContents[2],fileContents[3]); fileContents[1], fileContents[2],fileContents[3]);