Improved Importing

This commit is contained in:
Konloch 2021-07-10 09:05:08 -07:00
parent a7e399add9
commit d98f3d3e31
29 changed files with 510 additions and 465 deletions

View file

@ -12,6 +12,7 @@ import me.konloch.kontainer.io.DiskReader;
import org.apache.commons.io.FileUtils;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bootloader.Boot;
import the.bytecode.club.bytecodeviewer.api.BCV;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
import the.bytecode.club.bytecodeviewer.gui.components.*;
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.TabbedPane;
@ -168,11 +169,6 @@ public class BytecodeViewer
//setup look and feel
Configuration.lafTheme.setLAF();
if (PREVIEW_COPY && !CommandLineInput.containsCommand(args))
showMessage("WARNING: This is a preview/dev copy, you WON'T be alerted when " + VERSION + " is "
+ "actually out if you use this." + nl +
"Make sure to watch the repo: https://github.com/Konloch/bytecode-viewer for " + VERSION + "'s release");
//set swing specific system properties
System.setProperty("swing.aatext", "true");
@ -189,7 +185,6 @@ public class BytecodeViewer
//handle CLI
int CLI = CommandLineInput.parseCommandLine(args);
if (CLI == CommandLineInput.STOP)
return;
@ -200,10 +195,14 @@ public class BytecodeViewer
Boot.boot(args, CLI != CommandLineInput.GUI);
}
else
{
installFatJar.start();
}
if (CLI == CommandLineInput.GUI)
{
BytecodeViewer.boot(false);
}
else
{
BytecodeViewer.boot(true);
@ -350,15 +349,20 @@ public class BytecodeViewer
/**
* Returns the ClassNode by the specified name
*
* TODO anything relying on this should be rewritten to search using the file container
*
* @param name the class name
* @return the ClassNode instance
*/
public static ClassNode getClassNode(String name)
@Deprecated
public static ClassNode blindlySearchForClassNode(String name)
{
for (FileContainer container : files)
for (ClassNode c : container.classes)
if (c.name.equals(name))
return c;
{
ClassNode node = container.getClassNode(name);
if(node != null)
return node;
}
return null;
}
@ -382,18 +386,6 @@ public class BytecodeViewer
return files;
}
/**
* Returns a ClassNode by name specific namefrom a specific File Container
*/
public static ClassNode getClassNode(FileContainer container, String name)
{
for (ClassNode c : container.classes)
if (c.name.equals(name))
return c;
return null;
}
/**
* Grabs the file contents of the loaded resources.
*
@ -403,8 +395,8 @@ public class BytecodeViewer
public static byte[] getFileContents(String name)
{
for (FileContainer container : files)
if (container.files.containsKey(name))
return container.files.get(name);
if (container.resourceFiles.containsKey(name))
return container.resourceFiles.get(name);
return null;
}
@ -426,8 +418,13 @@ public class BytecodeViewer
public static void updateNode(ClassNode oldNode, ClassNode newNode)
{
for (FileContainer container : files)
if (container.classes.remove(oldNode))
container.classes.add(newNode);
{
if (container.resourceClasses.containsKey(oldNode.name))
{
container.resourceClasses.remove(oldNode.name);
container.resourceClasses.put(newNode.name, newNode);
}
}
}
/**
@ -440,7 +437,7 @@ public class BytecodeViewer
ArrayList<ClassNode> a = new ArrayList<>();
for (FileContainer container : files)
for (ClassNode c : container.classes)
for (ClassNode c : container.resourceClasses.values())
if (!a.contains(c))
a.add(c);
@ -648,7 +645,20 @@ public class BytecodeViewer
return;
}
BCVResourceUtils.resetWorkspace();
resetWorkspace();
}
/**
* Resets the workspace
*/
public static void resetWorkspace()
{
BytecodeViewer.files.clear();
LazyNameUtil.reset();
BytecodeViewer.viewer.resourcePane.resetWorkspace();
BytecodeViewer.viewer.workPane.resetWorkspace();
BytecodeViewer.viewer.searchBoxPane.resetWorkspace();
BCV.getClassNodeLoader().clear();
}
/**

View file

@ -215,7 +215,7 @@ public class CommandLineInput {
Decompiler.PROCYON_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
} else {
try {
ClassNode cn = BytecodeViewer.getClassNode(target);
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
final ClassWriter cw = accept(cn);
String contents = Decompiler.PROCYON_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
@ -233,7 +233,7 @@ public class CommandLineInput {
Decompiler.CFR_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
} else {
try {
ClassNode cn = BytecodeViewer.getClassNode(target);
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
final ClassWriter cw = accept(cn);
String contents = Decompiler.CFR_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
@ -251,7 +251,7 @@ public class CommandLineInput {
Decompiler.FERNFLOWER_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
} else {
try {
ClassNode cn = BytecodeViewer.getClassNode(target);
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
final ClassWriter cw = accept(cn);
String contents = Decompiler.FERNFLOWER_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
@ -269,7 +269,7 @@ public class CommandLineInput {
Decompiler.KRAKATAU_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
} else {
try {
ClassNode cn = BytecodeViewer.getClassNode(target);
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
final ClassWriter cw = accept(cn);
String contents = Decompiler.KRAKATAU_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
@ -288,7 +288,7 @@ public class CommandLineInput {
//Decompiler.krakatauDA.decompileToZip(output.getAbsolutePath());
} else {
try {
ClassNode cn = BytecodeViewer.getClassNode(target);
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
final ClassWriter cw = accept(cn);
String contents = Decompiler.KRAKATAU_DISASSEMBLER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
@ -307,7 +307,7 @@ public class CommandLineInput {
//Decompiler.jdgui.decompileToZip(output.getAbsolutePath());
} else {
try {
ClassNode cn = BytecodeViewer.getClassNode(target);
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
final ClassWriter cw = accept(cn);
String contents = Decompiler.JD_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
@ -326,7 +326,7 @@ public class CommandLineInput {
//Decompiler.smali.decompileToZip(output.getAbsolutePath());
} else {
try {
ClassNode cn = BytecodeViewer.getClassNode(target);
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
final ClassWriter cw = accept(cn);
String contents = Decompiler.SMALI_DISASSEMBLER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
@ -345,7 +345,7 @@ public class CommandLineInput {
//Decompiler.smali.decompileToZip(output.getAbsolutePath());
} else {
try {
ClassNode cn = BytecodeViewer.getClassNode(target);
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
final ClassWriter cw = accept(cn);
String contents = Decompiler.JADX_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);

View file

@ -11,6 +11,7 @@ import java.util.ArrayList;
import java.util.List;
import static the.bytecode.club.bytecodeviewer.BytecodeViewer.gson;
import static the.bytecode.club.bytecodeviewer.Configuration.maxRecentFiles;
import static the.bytecode.club.bytecodeviewer.Constants.*;
/**
@ -38,8 +39,8 @@ public class Settings
else
recentPlugins = DiskReader.loadArrayList(getBCVDirectory() + fs + "recentplugins.bcv", false);
MiscUtils.deduplicateAndTrim(recentFiles, 25);
MiscUtils.deduplicateAndTrim(recentPlugins, 25);
MiscUtils.deduplicateAndTrim(recentFiles, maxRecentFiles);
MiscUtils.deduplicateAndTrim(recentPlugins, maxRecentFiles);
}
catch (Exception e)
{
@ -56,7 +57,7 @@ public class Settings
{
recentFiles.remove(f.getAbsolutePath()); // already added on the list
recentFiles.add(0, f.getAbsolutePath());
MiscUtils.deduplicateAndTrim(recentFiles, 25);
MiscUtils.deduplicateAndTrim(recentFiles, maxRecentFiles);
DiskWriter.replaceFile(filesName, MiscUtils.listToString(recentFiles), false);
resetRecentFilesMenu();
}
@ -87,7 +88,7 @@ public class Settings
{
recentPlugins.remove(f.getAbsolutePath()); // already added on the list
recentPlugins.add(0, f.getAbsolutePath());
MiscUtils.deduplicateAndTrim(recentPlugins, 25);
MiscUtils.deduplicateAndTrim(recentPlugins, maxRecentFiles);
DiskWriter.replaceFile(pluginsName, MiscUtils.listToString(recentPlugins), false);
resetRecentFilesMenu();
}

View file

@ -1,6 +1,7 @@
package the.bytecode.club.bytecodeviewer.api;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
@ -12,11 +13,8 @@ public class ASMUtil
{
/**
* Creates a new ClassNode instances from the provided byte[]
*
* @param b the class file's byte[]
* @return the ClassNode instance
*/
public static ClassNode getClassNode(final byte[] b)
public static ClassNode bytesToNode(final byte[] b)
{
ClassReader cr = new ClassReader(b);
ClassNode cn = new ClassNode();
@ -28,6 +26,26 @@ public class ASMUtil
return cn;
}
/**
* Writes a valid byte[] from the provided classnode
*/
public static byte[] nodeToBytes(ClassNode cn)
{
final ClassWriter cw = new ClassWriter(0);
try {
cn.accept(cw);
} catch (Exception e) {
e.printStackTrace();
try {
Thread.sleep(200);
cn.accept(cw);
} catch (InterruptedException ignored) { }
}
return cw.toByteArray();
}
public static MethodNode getMethodByName(ClassNode cn, String name)
{
for(MethodNode m : cn.methods)

View file

@ -174,7 +174,7 @@ public class BCV
*/
public static ClassNode getClassNode(String name) {
return the.bytecode.club.bytecodeviewer.BytecodeViewer
.getClassNode(name);
.blindlySearchForClassNode(name);
}
/**

View file

@ -9,7 +9,6 @@ import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.InnerClassNode;
import org.objectweb.asm.tree.MethodNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
import static the.bytecode.club.bytecodeviewer.Constants.*;
@ -101,7 +100,7 @@ public class ClassNodeDecompiler
if ((innerClassName != null)
&& !decompiledClasses.contains(innerClassName)) {
decompiledClasses.add(innerClassName);
ClassNode cn1 = BytecodeViewer.getClassNode(innerClassName);
ClassNode cn1 = BytecodeViewer.blindlySearchForClassNode(innerClassName);
if (cn1 != null) {
sb.appendPrefix(" ");
sb.append(nl + nl);

View file

@ -30,7 +30,6 @@ public class HTMLPane extends JEditorPane
{
HTMLPane pane = new HTMLPane();
text = text.replace("{previewCopy}", String.valueOf(PREVIEW_COPY));
text = text.replace("{fatJar}", String.valueOf(FAT_JAR));
text = text.replace("{java}", Configuration.java);
text = text.replace("{javac}", Configuration.javac);

View file

@ -29,7 +29,6 @@ import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.gui.components.VisibleComponent;
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
import the.bytecode.club.bytecodeviewer.translation.Translation;
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckBox;
@ -169,9 +168,9 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
ImageRenderer renderer = new ImageRenderer();
tree.setCellRenderer(renderer);
if (!container.classes.isEmpty())
if (!container.resourceClasses.isEmpty())
{
for (ClassNode c : container.classes)
for (ClassNode c : container.resourceClasses.values())
{
String name = c.name;
final String[] spl = name.split("/");
@ -211,9 +210,9 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
}
}
if (!container.files.isEmpty())
if (!container.resourceFiles.isEmpty())
{
for (final Entry<String, byte[]> entry : container.files.entrySet())
for (final Entry<String, byte[]> entry : container.resourceFiles.entrySet())
{
String name = entry.getKey();
final String[] spl = name.split("/");
@ -311,7 +310,7 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
String name = nameBuffer.toString();
if (name.endsWith(".class"))
{
final ClassNode cn = BytecodeViewer.getClassNode(Objects.requireNonNull(container),
final ClassNode cn = Objects.requireNonNull(container).getClassNode(
name.substring(0, name.length() - ".class".length()));
if (cn != null)

View file

@ -43,7 +43,7 @@ class PerformSearch extends BackgroundSearchThread
}
for (FileContainer container : BytecodeViewer.files)
for (ClassNode c : container.classes)
for (ClassNode c : container.resourceClasses.values())
searchBoxPane.searchType.details.search(container, c, srn, searchBoxPane.exact.isSelected());
Objects.requireNonNull(MainViewerGUI.getComponent(SearchBoxPane.class)).search.setEnabled(true);

View file

@ -1,5 +1,6 @@
package the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer;
import the.bytecode.club.bytecodeviewer.api.ASMUtil;
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.ResourceViewPanel;
import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor;
@ -66,8 +67,6 @@ public class ClassViewer extends ResourceViewer
public ResourceViewPanel resourceViewPanel2 = new ResourceViewPanel(1, this);
public ResourceViewPanel resourceViewPanel3 = new ResourceViewPanel(2, this);
public File[] tempFiles;
public ClassViewer THIS = this;
public List<MethodParser> methods = Arrays.asList(new MethodParser(), new MethodParser(), new MethodParser());
public final String workingName;
@ -93,68 +92,31 @@ public class ClassViewer extends ResourceViewer
});
}
public void resetDivider()
{
SwingUtilities.invokeLater(() ->
{
sp.setResizeWeight(0.5);
if (resourceViewPanel2.decompiler != Decompiler.NONE && resourceViewPanel1.decompiler != Decompiler.NONE) {
setDividerLocation(sp, 0.5);
} else if (resourceViewPanel1.decompiler != Decompiler.NONE) {
setDividerLocation(sp, 1);
} else if (resourceViewPanel2.decompiler != Decompiler.NONE) {
sp.setResizeWeight(1);
setDividerLocation(sp, 0);
} else {
setDividerLocation(sp, 0);
}
if (resourceViewPanel3.decompiler != Decompiler.NONE) {
sp2.setResizeWeight(0.7);
setDividerLocation(sp2, 0.7);
if ((resourceViewPanel2.decompiler == Decompiler.NONE && resourceViewPanel1.decompiler != Decompiler.NONE)
|| (resourceViewPanel1.decompiler == Decompiler.NONE && resourceViewPanel2.decompiler != Decompiler.NONE)) {
setDividerLocation(sp2, 0.5);
} else if (resourceViewPanel1.decompiler == Decompiler.NONE) {
setDividerLocation(sp2, 0);
}
} else {
sp.setResizeWeight(1);
sp2.setResizeWeight(0);
setDividerLocation(sp2, 1);
}
});
}
public void startPaneUpdater(final JButton button)
{
this.cn = BytecodeViewer.getClassNode(container, cn.name); //update the classnode
setPanes();
this.cn = container.getClassNode(cn.name); //update the classnode
setPanes();
refreshTitle();
resourceViewPanel1.createPane(this);
resourceViewPanel2.createPane(this);
resourceViewPanel3.createPane(this);
final ClassWriter cw = new ClassWriter(0);
try {
cn.accept(cw);
} catch (Exception e) {
e.printStackTrace();
try {
Thread.sleep(200);
cn.accept(cw);
} catch (InterruptedException ignored) { }
byte[] classBytes = getBytes();
//TODO remove this once all of the importers have been properly updated to use a FileContainerImporter
if(classBytes == null || classBytes.length == 0)
{
System.err.println("WARNING: Imported using the old importer!");
classBytes = ASMUtil.nodeToBytes(cn);
}
final byte[] b = cw.toByteArray();
resourceViewPanel1.updatePane(this, b, button, isPanel1Editable());
resourceViewPanel2.updatePane(this, b, button, isPanel2Editable());
resourceViewPanel3.updatePane(this, b, button, isPanel3Editable());
resourceViewPanel1.updatePane(this, classBytes, button, isPanel1Editable());
resourceViewPanel2.updatePane(this, classBytes, button, isPanel2Editable());
resourceViewPanel3.updatePane(this, classBytes, button, isPanel3Editable());
Thread t = new Thread(() ->
Thread dumpBuild = new Thread(() ->
{
BytecodeViewer.updateBusyStatus(true);
@ -168,8 +130,6 @@ public class ClassViewer extends ResourceViewer
}
}
tempFiles = BCVResourceUtils.dumpTempFile(container);
BytecodeViewer.updateBusyStatus(false);
if (resourceViewPanel1.decompiler != Decompiler.NONE)
@ -179,7 +139,7 @@ public class ClassViewer extends ResourceViewer
if (resourceViewPanel3.decompiler != Decompiler.NONE)
resourceViewPanel3.updateThread.startNewThread();
}, "ClassViewer Temp Dump");
t.start();
dumpBuild.start();
if (isPanel1Editable() || isPanel2Editable() || isPanel3Editable())
{
@ -227,42 +187,6 @@ public class ClassViewer extends ResourceViewer
return BytecodeViewer.viewer.viewPane3.isPaneEditable();
}
/**
* Whoever wrote this function, THANK YOU!
*
* @param splitter
* @param proportion
* @return
*/
public static JSplitPane setDividerLocation(final JSplitPane splitter,
final double proportion) {
if (splitter.isShowing()) {
if (splitter.getWidth() > 0 && splitter.getHeight() > 0) {
splitter.setDividerLocation(proportion);
} else {
splitter.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent ce) {
splitter.removeComponentListener(this);
setDividerLocation(splitter, proportion);
}
});
}
} else {
splitter.addHierarchyListener(new HierarchyListener() {
@Override
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0
&& splitter.isShowing()) {
splitter.removeHierarchyListener(this);
setDividerLocation(splitter, proportion);
}
}
});
}
return splitter;
}
public static void selectMethod(RSyntaxTextArea area, int methodLine) {
if (methodLine != area.getCaretLineNumber()) {
@ -343,5 +267,72 @@ public class ClassViewer extends ResourceViewer
} catch (BadLocationException ignored) { }
}
public void resetDivider()
{
SwingUtilities.invokeLater(() ->
{
sp.setResizeWeight(0.5);
if (resourceViewPanel2.decompiler != Decompiler.NONE && resourceViewPanel1.decompiler != Decompiler.NONE) {
setDividerLocation(sp, 0.5);
} else if (resourceViewPanel1.decompiler != Decompiler.NONE) {
setDividerLocation(sp, 1);
} else if (resourceViewPanel2.decompiler != Decompiler.NONE) {
sp.setResizeWeight(1);
setDividerLocation(sp, 0);
} else {
setDividerLocation(sp, 0);
}
if (resourceViewPanel3.decompiler != Decompiler.NONE) {
sp2.setResizeWeight(0.7);
setDividerLocation(sp2, 0.7);
if ((resourceViewPanel2.decompiler == Decompiler.NONE && resourceViewPanel1.decompiler != Decompiler.NONE)
|| (resourceViewPanel1.decompiler == Decompiler.NONE && resourceViewPanel2.decompiler != Decompiler.NONE)) {
setDividerLocation(sp2, 0.5);
} else if (resourceViewPanel1.decompiler == Decompiler.NONE) {
setDividerLocation(sp2, 0);
}
} else {
sp.setResizeWeight(1);
sp2.setResizeWeight(0);
setDividerLocation(sp2, 1);
}
});
}
/**
* Whoever wrote this function, THANK YOU!
*/
public static JSplitPane setDividerLocation(final JSplitPane splitter,
final double proportion)
{
if (splitter.isShowing()) {
if (splitter.getWidth() > 0 && splitter.getHeight() > 0) {
splitter.setDividerLocation(proportion);
} else {
splitter.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent ce) {
splitter.removeComponentListener(this);
setDividerLocation(splitter, proportion);
}
});
}
} else {
splitter.addHierarchyListener(new HierarchyListener() {
@Override
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0
&& splitter.isShowing()) {
splitter.removeHierarchyListener(this);
setDividerLocation(splitter, proportion);
}
}
});
}
return splitter;
}
private static final long serialVersionUID = -8650495368920680024L;
}

View file

@ -53,5 +53,13 @@ public abstract class ResourceViewer extends JPanel
return tabName;
}
public byte[] getBytes()
{
if(container.resourceClassBytes.containsKey(name))
return container.resourceClassBytes.get(name);
else
return container.resourceFiles.get(name);
}
private static final long serialVersionUID = -2965538493489119191L;
}

View file

@ -147,7 +147,7 @@ public class AllatoriStringDecrypter extends Plugin
// We have to create new node for editing
// Also, one decrypter method could be used for multiple methods in code, what gives us only part of string decrypted
ClassNode decrypterClassNode = ASMUtil.getClassNode(decrypterFileContents);
ClassNode decrypterClassNode = ASMUtil.bytesToNode(decrypterFileContents);
MethodNode decryptermethodnode = ASMUtil.getMethodByName(decrypterClassNode, decrypterMethodName);
if (decryptermethodnode != null)

View file

@ -87,7 +87,7 @@ public class CompiledJavaPluginLaunchStrategy implements PluginLaunchStrategy {
String name = entry.getName();
if (name.endsWith(".class"))
{
byte[] bytes = JarUtils.getBytes(jis);
byte[] bytes = MiscUtils.getBytes(jis);
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
{
try {

View file

@ -191,10 +191,7 @@ public class ResourceDecompiling
if (BytecodeViewer.autoCompileSuccessful())
return;
final String s = BytecodeViewer.getCurrentlyOpenedClassNode().name;
if (s == null)
return;
final ClassNode cn = BytecodeViewer.getCurrentlyOpenedClassNode();
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
"Select Java Files",
@ -230,7 +227,6 @@ public class ResourceDecompiling
if (result == 0) {
Thread t1 = new Thread(() -> {
try {
ClassNode cn = BytecodeViewer.getClassNode(s);
final ClassWriter cw = new ClassWriter(0);
try {
Objects.requireNonNull(cn).accept(cw);
@ -282,7 +278,6 @@ public class ResourceDecompiling
if (result == 1) {
Thread t1 = new Thread(() -> {
try {
ClassNode cn = BytecodeViewer.getClassNode(s);
final ClassWriter cw = new ClassWriter(0);
try {
Objects.requireNonNull(cn).accept(cw);
@ -308,7 +303,6 @@ public class ResourceDecompiling
if (result == 2) {
Thread t1 = new Thread(() -> {
try {
ClassNode cn = BytecodeViewer.getClassNode(s);
final ClassWriter cw = new ClassWriter(0);
try {
Objects.requireNonNull(cn).accept(cw);
@ -334,7 +328,6 @@ public class ResourceDecompiling
if (result == 3) {
Thread t1 = new Thread(() -> {
try {
ClassNode cn = BytecodeViewer.getClassNode(s);
final ClassWriter cw = new ClassWriter(0);
try {
Objects.requireNonNull(cn).accept(cw);
@ -362,7 +355,6 @@ public class ResourceDecompiling
if (result == 4) {
Thread t1 = new Thread(() -> {
try {
ClassNode cn = BytecodeViewer.getClassNode(s);
final ClassWriter cw = new ClassWriter(0);
try {
Objects.requireNonNull(cn).accept(cw);
@ -371,18 +363,16 @@ public class ResourceDecompiling
try {
Thread.sleep(200);
Objects.requireNonNull(cn).accept(cw);
} catch (InterruptedException ignored) {
}
} catch (InterruptedException ignored) { }
}
String contents = Decompiler.KRAKATAU_DECOMPILER.getDecompiler().decompileClassNode(cn,
cw.toByteArray());
String contents = Decompiler.KRAKATAU_DECOMPILER.getDecompiler().
decompileClassNode(cn, cw.toByteArray());
DiskWriter.replaceFile(path, contents, false);
BytecodeViewer.updateBusyStatus(false);
} catch (Exception e) {
BytecodeViewer.updateBusyStatus(false);
BytecodeViewer.handleException(
e);
BytecodeViewer.handleException(e);
}
});
t1.start();

View file

@ -32,7 +32,6 @@ import java.util.Objects;
*/
public class ImportResource implements Runnable
{
private boolean update = true;
private final File[] files;
public ImportResource(File[] files) {this.files = files;}
@ -46,53 +45,46 @@ public class ImportResource implements Runnable
{
final String fn = file.getName();
//check if file exists
if (!file.exists())
{
update = false;
BytecodeViewer.showMessage("The file " + file.getAbsolutePath() + " could not be found.");
Settings.removeRecentFile(file);
continue;
}
else
{
//check if file is directory
if (file.isDirectory())
{
Import.DIRECTORY.getImporter().open(file);
continue;
}
else
{
//check for zip archives
if (fn.endsWith(".jar") || fn.endsWith(".zip") || fn.endsWith(".war") || fn.endsWith(".ear"))
{
if(!Import.ZIP.getImporter().open(file))
update = false;
}
Import.ZIP.getImporter().open(file);
//check for classes
else if (fn.endsWith(".class"))
{
if(!Import.CLASS.getImporter().open(file))
update = false;
}
Import.CLASS.getImporter().open(file);
//check for XAPKs
else if (fn.endsWith(".xapk"))
{
Import.XAPK.getImporter().open(file);
return;
}
//check for APKs
else if (fn.endsWith(".apk"))
{
Import.APK.getImporter().open(file);
return;
}
//check for DEX
else if (fn.endsWith(".dex"))
{
Import.DEX.getImporter().open(file);
return;
}
//everything else import as a resource
else
{
Import.FILE.getImporter().open(file);
}
}
}
}
}
catch (final Exception e)
{
BytecodeViewer.handleException(e);
@ -100,8 +92,6 @@ public class ImportResource implements Runnable
finally
{
BytecodeViewer.updateBusyStatus(false);
if (update)
try {
Objects.requireNonNull(MainViewerGUI.getComponent(ResourceListPane.class)).updateTree();
} catch (NullPointerException ignored) { }

View file

@ -26,5 +26,5 @@ import java.io.File;
*/
public interface Importer
{
boolean open(File file) throws Exception;
void open(File file) throws Exception;
}

View file

@ -1,12 +1,13 @@
package the.bytecode.club.bytecodeviewer.resources.importing.impl;
import org.apache.commons.io.FileUtils;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
import the.bytecode.club.bytecodeviewer.util.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Objects;
import static the.bytecode.club.bytecodeviewer.Constants.fs;
@ -19,9 +20,8 @@ import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
public class APKResourceImporter implements Importer
{
@Override
public boolean open(File file) throws Exception
public void open(File file) throws Exception
{
try {
BytecodeViewer.updateBusyStatus(true);
File tempCopy = new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk");
@ -34,10 +34,10 @@ public class APKResourceImporter implements Importer
File decodedResources =
new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk");
APKTool.decodeResources(tempCopy, decodedResources, container);
container.files = JarUtils.loadResources(decodedResources);
container.resourceFiles = JarUtils.loadResources(decodedResources);
}
Objects.requireNonNull(container.files).putAll(JarUtils.loadResources(tempCopy)); //copy and rename
Objects.requireNonNull(container.resourceFiles).putAll(JarUtils.loadResources(tempCopy)); //copy and rename
// to prevent unicode filenames
String name = MiscUtils.getRandomizedName() + ".jar";
@ -48,14 +48,12 @@ public class APKResourceImporter implements Importer
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
Enjarify.apk2Jar(tempCopy, output);
container.classes = JarUtils.loadClasses(output);
//TODO update to FileContainerImporter
ArrayList<ClassNode> nodeList = JarUtils.loadClasses(output);
for(ClassNode cn : nodeList)
container.resourceClasses.put(cn.name, cn);
BytecodeViewer.updateBusyStatus(false);
BytecodeViewer.files.add(container);
} catch (final Exception e) {
BytecodeViewer.handleException(e);
}
return true;
}
}

View file

@ -1,8 +1,8 @@
package the.bytecode.club.bytecodeviewer.resources.importing.impl;
import org.apache.commons.io.FilenameUtils;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
import the.bytecode.club.bytecodeviewer.util.FileContainer;
import the.bytecode.club.bytecodeviewer.util.JarUtils;
@ -18,32 +18,26 @@ import java.io.FileInputStream;
public class ClassResourceImporter implements Importer
{
@Override
public boolean open(File file) throws Exception
public void open(File file) throws Exception
{
final String fn = file.getName();
try
{
byte[] bytes = JarUtils.getBytes(new FileInputStream(file));
final String name = file.getName();
byte[] bytes = MiscUtils.getBytes(new FileInputStream(file));
FileContainer container = new FileContainer(file);
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
{
final ClassNode cn = JarUtils.getNode(bytes);
FileContainer container = new FileContainer(file);
container.classes.add(cn);
BytecodeViewer.files.add(container);
container.resourceClasses.put(FilenameUtils.removeExtension(name), cn);
container.resourceClassBytes.put(name, bytes);
}
else
{
BytecodeViewer.showMessage(fn + ": Header does not start with CAFEBABE, ignoring.");
return false;
}
}
catch (final Exception e)
{
BytecodeViewer.handleException(e);
return false;
}
BytecodeViewer.showMessage(name + "\nHeader does not start with CAFEBABE\nimporting as resource instead.");
return true;
//TODO double check this
container.resourceFiles.put(name, bytes);
}
BytecodeViewer.files.add(container);
}
}

View file

@ -1,12 +1,13 @@
package the.bytecode.club.bytecodeviewer.resources.importing.impl;
import org.apache.commons.io.FileUtils;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
import the.bytecode.club.bytecodeviewer.util.*;
import java.io.File;
import java.util.ArrayList;
import static the.bytecode.club.bytecodeviewer.Constants.fs;
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
@ -18,9 +19,8 @@ import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
public class DEXResourceImporter implements Importer
{
@Override
public boolean open(File file) throws Exception
public void open(File file) throws Exception
{
try {
BytecodeViewer.updateBusyStatus(true);
File tempCopy = new File(tempDirectory + fs + MiscUtils.randomString(32) + ".dex");
@ -37,14 +37,12 @@ public class DEXResourceImporter implements Importer
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
Enjarify.apk2Jar(tempCopy, output);
container.classes = JarUtils.loadClasses(output);
//TODO update to FileContainerImporter
ArrayList<ClassNode> nodeList = JarUtils.loadClasses(output);
for(ClassNode cn : nodeList)
container.resourceClasses.put(cn.name, cn);
BytecodeViewer.updateBusyStatus(false);
BytecodeViewer.files.add(container);
} catch (final Exception e) {
BytecodeViewer.handleException(e);
}
return true;
}
}

View file

@ -1,5 +1,6 @@
package the.bytecode.club.bytecodeviewer.resources.importing.impl;
import org.apache.commons.io.FilenameUtils;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.resources.importing.Import;
@ -22,7 +23,7 @@ import java.util.Objects;
public class DirectoryResourceImporter implements Importer
{
@Override
public boolean open(File file) throws Exception
public void open(File file) throws Exception
{
FileContainer container = new FileContainer(file);
HashMap<String, byte[]> allDirectoryFiles = new HashMap<>();
@ -61,29 +62,22 @@ public class DirectoryResourceImporter implements Importer
//attempt to import archives automatically
if (fileName.endsWith(".jar") || fileName.endsWith(".zip") || fileName.endsWith(".war") || fileName.endsWith(".ear"))
{
Import.ZIP.getImporter().open(child);
}
else if (fileName.endsWith(".apk"))
{
Import.APK.getImporter().open(child);
}
else if (fileName.endsWith(".dex"))
{
Import.DEX.getImporter().open(child);
}
else if (fileName.endsWith(".class"))
{
byte[] bytes = Files.readAllBytes(Paths.get(child.getAbsolutePath()));
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
{
final ClassNode cn = JarUtils.getNode(bytes);
allDirectoryClasses.put(trimmedPath, cn);
allDirectoryClasses.put(FilenameUtils.removeExtension(trimmedPath), cn);
}
}
else
else //pack files into a single container
{
//pack files into a single container
allDirectoryFiles.put(trimmedPath, Files.readAllBytes(Paths.get(child.getAbsolutePath())));
}
}
@ -92,9 +86,8 @@ public class DirectoryResourceImporter implements Importer
}
}
container.classes.addAll(allDirectoryClasses.values());
container.files = allDirectoryFiles;
container.resourceClasses.putAll(allDirectoryClasses);
container.resourceFiles = allDirectoryFiles;
BytecodeViewer.files.add(container);
return true;
}
}

View file

@ -3,7 +3,9 @@ package the.bytecode.club.bytecodeviewer.resources.importing.impl;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
import the.bytecode.club.bytecodeviewer.util.FileContainer;
import the.bytecode.club.bytecodeviewer.util.FileContainerImporter;
import the.bytecode.club.bytecodeviewer.util.JarUtils;
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
import java.io.File;
import java.io.FileInputStream;
@ -16,16 +18,15 @@ import java.util.HashMap;
public class FileResourceImporter implements Importer
{
@Override
public boolean open(File file) throws Exception
public void open(File file) throws Exception
{
HashMap<String, byte[]> files1 = new HashMap<>();
byte[] bytes = JarUtils.getBytes(new FileInputStream(file));
files1.put(file.getName(), bytes);
//create the new file container
FileContainer container = new FileContainer(file);
container.files = files1;
//create the new file importer
FileContainerImporter importer = new FileContainerImporter(container);
//import the file into the file container
importer.importAsFile();
//add the file container to BCV's total loaded files
BytecodeViewer.files.add(container);
return true;
}
}

View file

@ -2,7 +2,6 @@ package the.bytecode.club.bytecodeviewer.resources.importing.impl;
import me.konloch.kontainer.io.DiskWriter;
import org.apache.commons.io.IOUtils;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Configuration;
import the.bytecode.club.bytecodeviewer.resources.importing.Import;
@ -14,6 +13,7 @@ import java.io.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import static the.bytecode.club.bytecodeviewer.Constants.fs;
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
@ -27,14 +27,13 @@ import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
public class XAPKResourceImporter implements Importer
{
@Override
public boolean open(File file) throws Exception
public void open(File file) throws Exception
{
FileContainer container = new FileContainer(file);
HashMap<String, byte[]> allDirectoryFiles = new HashMap<>();
HashMap<String, ClassNode> allDirectoryClasses = new HashMap<>();
Configuration.silenceExceptionGUI++; //turn exceptions off
try (java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile(file))
try (ZipFile zipFile = new ZipFile(file))
{
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements())
@ -69,13 +68,11 @@ public class XAPKResourceImporter implements Importer
}
}
}
Configuration.silenceExceptionGUI--; //turn exceptions back on
BytecodeViewer.viewer.clearBusyStatus(); //clear errant busy signals from failed APK imports
container.classes.addAll(allDirectoryClasses.values());
container.files = allDirectoryFiles;
BytecodeViewer.files.add(container);
return true;
container.resourceFiles = allDirectoryFiles; //store the file resource
BytecodeViewer.files.add(container); //add the file container to BCV's total loaded files
}
public File exportTo(File original, String extension, byte[] bytes)

View file

@ -3,6 +3,8 @@ package the.bytecode.club.bytecodeviewer.resources.importing.impl;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
import the.bytecode.club.bytecodeviewer.util.FileContainer;
import the.bytecode.club.bytecodeviewer.util.FileContainerImporter;
import the.bytecode.club.bytecodeviewer.util.JarUtils;
import java.io.File;
@ -15,32 +17,15 @@ import java.io.IOException;
public class ZipResourceImporter implements Importer
{
@Override
public boolean open(File file) throws Exception
public void open(File file) throws Exception
{
//attempt to load archives using the first method
try
{
JarUtils.importArchiveA(file);
}
catch (IOException z)
{
//attempt to load archives using the fallback method on fail
try
{
JarUtils.importArchiveB(file);
}
catch (final Exception e)
{
BytecodeViewer.handleException(e);
return false;
}
}
catch (final Exception e)
{
BytecodeViewer.handleException(e);
return false;
}
return true;
//create the new file container
FileContainer container = new FileContainer(file);
//create the new file importer
FileContainerImporter importer = new FileContainerImporter(container);
//import the file as zip into the file container
importer.importAsZip();
//add the file container to BCV's total loaded files
BytecodeViewer.files.add(container);
}
}

View file

@ -33,75 +33,6 @@ import static the.bytecode.club.bytecodeviewer.Constants.RT_JAR_DUMPED;
*/
public class BCVResourceUtils
{
public static void resetWorkspace()
{
BytecodeViewer.files.clear();
LazyNameUtil.reset();
BytecodeViewer.viewer.resourcePane.resetWorkspace();
BytecodeViewer.viewer.workPane.resetWorkspace();
BytecodeViewer.viewer.searchBoxPane.resetWorkspace();
BCV.getClassNodeLoader().clear();
}
/**
* Dumps the loaded classes as a library to be used for Krakatau
*/
public static File[] dumpTempFile(FileContainer container)
{
File[] files = new File[2];
//currently won't optimize if you've got two containers with the same name, will need to add this later
if (!LazyNameUtil.SAME_NAME_JAR_WORKSPACE)
{
if (Configuration.krakatauTempJar != null && !Configuration.krakatauTempJar.exists())
Configuration.needsReDump = true;
if (Configuration.needsReDump && Configuration.krakatauTempJar != null)
{
Configuration.krakatauTempDir = null;
Configuration.krakatauTempJar = null;
}
boolean passes = false;
if (BytecodeViewer.viewer.viewPane1.getGroup().isSelected(BytecodeViewer.viewer.viewPane1.getKrakatau().getJava().getModel()))
passes = true;
else if (BytecodeViewer.viewer.viewPane1.getGroup().isSelected(BytecodeViewer.viewer.viewPane1.getKrakatau().getBytecode().getModel()))
passes = true;
else if (BytecodeViewer.viewer.viewPane2.getGroup().isSelected(BytecodeViewer.viewer.viewPane2.getKrakatau().getJava().getModel()))
passes = true;
else if (BytecodeViewer.viewer.viewPane2.getGroup().isSelected(BytecodeViewer.viewer.viewPane2.getKrakatau().getBytecode().getModel()))
passes = true;
else if (BytecodeViewer.viewer.viewPane3.getGroup().isSelected(BytecodeViewer.viewer.viewPane3.getKrakatau().getJava().getModel()))
passes = true;
else if (BytecodeViewer.viewer.viewPane3.getGroup().isSelected(BytecodeViewer.viewer.viewPane3.getKrakatau().getBytecode().getModel()))
passes = true;
if (Configuration.krakatauTempJar != null || !passes)
{
files[0] = Configuration.krakatauTempJar;
files[1] = Configuration.krakatauTempDir;
return files;
}
}
Configuration.currentlyDumping = true;
Configuration.needsReDump = false;
Configuration.krakatauTempDir = new File(tempDirectory + fs + MiscUtils.randomString(32) + fs);
Configuration.krakatauTempDir.mkdir();
Configuration.krakatauTempJar = new File(tempDirectory + fs + "temp" + MiscUtils.randomString(32) + ".jar");
//krakatauTempJar = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp" + MiscUtils
// .randomString(32) + ".jar."+container.name);
JarUtils.saveAsJarClassesOnly(container.classes, Configuration.krakatauTempJar.getAbsolutePath());
Configuration.currentlyDumping = false;
files[0] = Configuration.krakatauTempJar;
files[1] = Configuration.krakatauTempDir;
return files;
}
//rt.jar check
public synchronized static void rtCheck()
{

View file

@ -4,7 +4,6 @@ import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.Configuration;
/***************************************************************************
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
@ -46,16 +45,13 @@ public class FileContainer {
public String name;
public File APKToolContents = null;
public HashMap<String, byte[]> files = new HashMap<>();
public ArrayList<ClassNode> classes = new ArrayList<>();
public HashMap<String, byte[]> resourceFiles = new HashMap<>();
public HashMap<String, byte[]> resourceClassBytes = new HashMap<>();
public HashMap<String, ClassNode> resourceClasses = new HashMap<>();
public ClassNode getClassNode(String name)
{
for (ClassNode c : classes)
if (c.name.equals(name))
return c;
return null;
return resourceClasses.get(name);
}
public String generateWorkName(String name)

View file

@ -0,0 +1,138 @@
package the.bytecode.club.bytecodeviewer.util;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.io.FilenameUtils;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.api.ASMUtil;
import java.io.*;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* @author Konloch
* @since 7/10/2021
*/
public class FileContainerImporter
{
private final FileContainer container;
public FileContainerImporter(FileContainer container)
{
this.container = container;
}
public void importAsFile() throws IOException
{
addUnknownFile(container.file.getName(), new FileInputStream(container.file), false);
}
public void importAsZip() throws IOException
{
container.resourceClasses.clear();
container.resourceClassBytes.clear();
container.resourceFiles.clear();
try
{
//attempt to import using Java ZipInputStream
importZipInputStream(false);
}
catch (IOException e)
{
e.printStackTrace();
//fallback to apache commons ZipFile
importApacheZipFile(false);
}
}
//sorts the file type from classes or resources
public void addUnknownFile(String name, InputStream stream, boolean classesOnly) throws IOException
{
//TODO remove this .class check and just look for cafebabe
if (name.endsWith(".class"))
addClassResource(name, stream);
else if(!classesOnly)
addResource(name, stream);
}
public void addClassResource(String name, InputStream stream) throws IOException
{
byte[] bytes = MiscUtils.getBytes(stream);
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
{
try
{
final ClassNode cn = ASMUtil.bytesToNode(bytes);
//classes are copied into memory twice
ClassNode existingNode = container.resourceClasses.put(FilenameUtils.removeExtension(name), cn);
container.resourceClassBytes.put(name, bytes);
if( existingNode != null)
{
//TODO prompt to ask the user if they would like to overwrite the resource conflict
// or solve it automatically by creating a new file container for each conflict
System.err.println("WARNING: Resource Conflict: " + name);
System.err.println("Suggested Fix: Contact Konloch to add support for resource conflicts");
}
}
catch (Exception e)
{
e.printStackTrace();
}
} else {
System.err.println(container.file + ">" + name + ": Header does not start with CAFEBABE, ignoring.");
}
}
public void addResource(String name, InputStream stream) throws IOException
{
byte[] bytes = MiscUtils.getBytes(stream);
container.resourceFiles.put(name, bytes);
}
public void importZipInputStream(boolean classesOnly) throws IOException
{
ZipInputStream jis = new ZipInputStream(new FileInputStream(container.file));
ZipEntry entry;
while ((entry = jis.getNextEntry()) != null)
{
final String name = entry.getName();
//skip directories
if(entry.isDirectory())
continue;
addUnknownFile(name, jis, classesOnly);
jis.closeEntry();
}
jis.close();
}
//TODO if this ever fails: import Sun's jarsigner code from JDK 7, re-sign the jar to rebuild the CRC,
// should also rebuild the archive byte offsets
public void importApacheZipFile(boolean classesOnly) throws IOException
{
try (ZipFile zipFile = new ZipFile(container.file))
{
Enumeration<? extends ZipArchiveEntry> entries = zipFile.getEntries();
while (entries.hasMoreElements())
{
ZipArchiveEntry entry = entries.nextElement();
String name = entry.getName();
if(entry.isDirectory())
continue;
try (InputStream in = zipFile.getInputStream(entry))
{
addUnknownFile(name, in, classesOnly);
}
}
}
}
}

View file

@ -7,6 +7,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map.Entry;
@ -17,6 +18,7 @@ import java.util.zip.ZipInputStream;
import me.konloch.kontainer.io.DiskWriter;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.io.FilenameUtils;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
@ -45,11 +47,14 @@ import static the.bytecode.club.bytecodeviewer.Constants.*;
/**
* Loading and saving jars
*
* NOTE: This is in the process of being replaced with the Import & Export API
*
* @author Konloch
* @author WaterWolf
* @since 09/26/2011
*/
@Deprecated
public class JarUtils
{
public static Object LOCK = new Object();
@ -70,7 +75,7 @@ public class JarUtils
while ((entry = jis.getNextEntry()) != null) {
try {
final String name = entry.getName();
final byte[] bytes = getBytes(jis);
final byte[] bytes = MiscUtils.getBytes(jis);
if (!name.endsWith(".class")) {
if (!entry.isDirectory())
files.put(name, bytes);
@ -79,7 +84,7 @@ public class JarUtils
{
try {
final ClassNode cn = getNode(bytes);
container.classes.add(cn);
container.resourceClasses.put(FilenameUtils.removeExtension(name), cn);
} catch (Exception e) {
System.err.println("Skipping: " + name);
e.printStackTrace();
@ -100,7 +105,7 @@ public class JarUtils
}
}
jis.close();
container.files = files;
container.resourceFiles = files;
BytecodeViewer.files.add(container);
}
@ -126,7 +131,7 @@ public class JarUtils
String name = entry.getName();
if (!entry.isDirectory()) {
try (InputStream in = zipFile.getInputStream(entry)) {
final byte[] bytes = getBytes(in);
final byte[] bytes = MiscUtils.getBytes(in);
if (!name.endsWith(".class")) {
files.put(name, bytes);
@ -135,7 +140,7 @@ public class JarUtils
{
try {
final ClassNode cn = getNode(bytes);
container.classes.add(cn);
container.resourceClasses.put(FilenameUtils.removeExtension(name), cn);
} catch (Exception e) {
e.printStackTrace();
}
@ -149,7 +154,7 @@ public class JarUtils
}
}
container.files = files;
container.resourceFiles = files;
BytecodeViewer.files.add(container);
}
@ -162,7 +167,7 @@ public class JarUtils
try {
final String name = entry.getName();
if (name.endsWith(".class")) {
byte[] bytes = getBytes(jis);
byte[] bytes = MiscUtils.getBytes(jis);
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
{
try {
@ -205,7 +210,7 @@ public class JarUtils
final String name = entry.getName();
if (!name.endsWith(".class") && !name.endsWith(".dex")) {
if (!entry.isDirectory())
files.put(name, getBytes(jis));
files.put(name, MiscUtils.getBytes(jis));
jis.closeEntry();
}
@ -218,25 +223,6 @@ public class JarUtils
jis.close();
return files;
}
/**
* Reads an InputStream and returns the read byte[]
*
* @param is InputStream
* @return the read byte[]
* @throws IOException
*/
public static byte[] getBytes(final InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int a;
while ((a = is.read(buffer)) != -1) {
baos.write(buffer, 0, a);
}
baos.close();
return baos.toByteArray();
}
/**
@ -248,7 +234,7 @@ public class JarUtils
public static ClassNode getNode(final byte[] bytez) {
synchronized (LOCK)
{
return ASMUtil.getClassNode(bytez);
return ASMUtil.bytesToNode(bytez);
}
}
@ -278,7 +264,7 @@ public class JarUtils
out.closeEntry();
for (FileContainer container : BytecodeViewer.files)
for (Entry<String, byte[]> entry : container.files.entrySet()) {
for (Entry<String, byte[]> entry : container.resourceFiles.entrySet()) {
String filename = entry.getKey();
if (!filename.startsWith("META-INF")) {
out.putNextEntry(new ZipEntry(filename));
@ -299,7 +285,8 @@ public class JarUtils
* @param nodeList The loaded ClassNodes
* @param path the exact jar output path
*/
public static void saveAsJarClassesOnly(ArrayList<ClassNode> nodeList, String path) {
public static void saveAsJarClassesOnly(Collection<ClassNode> nodeList, String path)
{
synchronized (LOCK)
{
try
@ -380,7 +367,7 @@ public class JarUtils
}
for (FileContainer container : BytecodeViewer.files)
for (Entry<String, byte[]> entry : container.files.entrySet()) {
for (Entry<String, byte[]> entry : container.resourceFiles.entrySet()) {
String filename = entry.getKey();
if (!filename.startsWith("META-INF")) {
if (!noDupe.contains(filename)) {

View file

@ -8,7 +8,6 @@ import the.bytecode.club.bytecodeviewer.translation.Language;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.Field;
@ -181,7 +180,7 @@ public class MiscUtils
StringBuilder block = new StringBuilder();
for (FileContainer container : fileContainers) {
block.append(container.name);
for (ClassNode node : container.classes) {
for (ClassNode node : container.resourceClasses.values()) {
block.append(node.name);
}
}
@ -273,4 +272,26 @@ public class MiscUtils
return path;
}
/**
* Reads an InputStream and returns the read byte[]
*
* @param is InputStream
* @return the read byte[]
* @throws IOException
*/
public static byte[] getBytes(final InputStream is) throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int a;
while ((a = is.read(buffer)) != -1)
baos.write(buffer, 0, a);
baos.close();
return baos.toByteArray();
}
}

View file

@ -90,6 +90,7 @@ public class SecurityMan extends SecurityManager
if (allow && !blocking) {
System.out.println("Allowing exec: " + cmd);
} else throw new SecurityException("BCV is awesome, blocking(" + blocking + ") exec " + cmd);
}