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

View file

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

View file

@ -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())

View file

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

View file

@ -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
{

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));
ResourceContainer container = new ResourceContainer(file);
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
{
final ClassNode cn = JarUtils.getNode(bytes);

View file

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

View file

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

View file

@ -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]);