Improved Importing
This commit is contained in:
parent
a7e399add9
commit
d98f3d3e31
29 changed files with 510 additions and 465 deletions
|
@ -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;
|
||||
}
|
||||
|
@ -381,18 +385,6 @@ public class BytecodeViewer
|
|||
public static List<FileContainer> getFiles() {
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -174,7 +174,7 @@ public class BCV
|
|||
*/
|
||||
public static ClassNode getClassNode(String name) {
|
||||
return the.bytecode.club.bytecodeviewer.BytecodeViewer
|
||||
.getClassNode(name);
|
||||
.blindlySearchForClassNode(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
resourceViewPanel1.updatePane(this, classBytes, button, isPanel1Editable());
|
||||
resourceViewPanel2.updatePane(this, classBytes, button, isPanel2Editable());
|
||||
resourceViewPanel3.updatePane(this, classBytes, button, isPanel3Editable());
|
||||
|
||||
final byte[] b = cw.toByteArray();
|
||||
resourceViewPanel1.updatePane(this, b, button, isPanel1Editable());
|
||||
resourceViewPanel2.updatePane(this, b, button, isPanel2Editable());
|
||||
resourceViewPanel3.updatePane(this, b, button, isPanel3Editable());
|
||||
|
||||
Thread t = new Thread(() ->
|
||||
Thread dumpBuild = new Thread(() ->
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
|
||||
|
@ -167,8 +129,6 @@ public class ClassViewer extends ResourceViewer
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
tempFiles = BCVResourceUtils.dumpTempFile(container);
|
||||
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,14 @@ 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;
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,51 +45,44 @@ 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())
|
||||
{
|
||||
if (file.isDirectory())
|
||||
{
|
||||
Import.DIRECTORY.getImporter().open(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fn.endsWith(".jar") || fn.endsWith(".zip") || fn.endsWith(".war") || fn.endsWith(".ear"))
|
||||
{
|
||||
if(!Import.ZIP.getImporter().open(file))
|
||||
update = false;
|
||||
}
|
||||
else if (fn.endsWith(".class"))
|
||||
{
|
||||
if(!Import.CLASS.getImporter().open(file))
|
||||
update = false;
|
||||
}
|
||||
else if (fn.endsWith(".xapk"))
|
||||
{
|
||||
Import.XAPK.getImporter().open(file);
|
||||
return;
|
||||
}
|
||||
else if (fn.endsWith(".apk"))
|
||||
{
|
||||
Import.APK.getImporter().open(file);
|
||||
return;
|
||||
}
|
||||
else if (fn.endsWith(".dex"))
|
||||
{
|
||||
Import.DEX.getImporter().open(file);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Import.FILE.getImporter().open(file);
|
||||
}
|
||||
}
|
||||
Import.DIRECTORY.getImporter().open(file);
|
||||
continue;
|
||||
}
|
||||
|
||||
//check for zip archives
|
||||
if (fn.endsWith(".jar") || fn.endsWith(".zip") || fn.endsWith(".war") || fn.endsWith(".ear"))
|
||||
Import.ZIP.getImporter().open(file);
|
||||
|
||||
//check for classes
|
||||
else if (fn.endsWith(".class"))
|
||||
Import.CLASS.getImporter().open(file);
|
||||
|
||||
//check for XAPKs
|
||||
else if (fn.endsWith(".xapk"))
|
||||
Import.XAPK.getImporter().open(file);
|
||||
|
||||
//check for APKs
|
||||
else if (fn.endsWith(".apk"))
|
||||
Import.APK.getImporter().open(file);
|
||||
|
||||
//check for DEX
|
||||
else if (fn.endsWith(".dex"))
|
||||
Import.DEX.getImporter().open(file);
|
||||
|
||||
//everything else import as a resource
|
||||
else
|
||||
Import.FILE.getImporter().open(file);
|
||||
}
|
||||
}
|
||||
catch (final Exception e)
|
||||
|
@ -100,11 +92,9 @@ public class ImportResource implements Runnable
|
|||
finally
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
|
||||
if (update)
|
||||
try {
|
||||
Objects.requireNonNull(MainViewerGUI.getComponent(ResourceListPane.class)).updateTree();
|
||||
} catch (NullPointerException ignored) { }
|
||||
try {
|
||||
Objects.requireNonNull(MainViewerGUI.getComponent(ResourceListPane.class)).updateTree();
|
||||
} catch (NullPointerException ignored) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,5 +26,5 @@ import java.io.File;
|
|||
*/
|
||||
public interface Importer
|
||||
{
|
||||
boolean open(File file) throws Exception;
|
||||
void open(File file) throws Exception;
|
||||
}
|
||||
|
|
|
@ -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,43 +20,40 @@ 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");
|
||||
|
||||
FileUtils.copyFile(file, tempCopy);
|
||||
|
||||
FileContainer container = new FileContainer(tempCopy, file.getName());
|
||||
|
||||
if (BytecodeViewer.viewer.decodeAPKResources.isSelected()) {
|
||||
File decodedResources =
|
||||
new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk");
|
||||
APKTool.decodeResources(tempCopy, decodedResources, container);
|
||||
container.files = JarUtils.loadResources(decodedResources);
|
||||
}
|
||||
|
||||
Objects.requireNonNull(container.files).putAll(JarUtils.loadResources(tempCopy)); //copy and rename
|
||||
// to prevent unicode filenames
|
||||
|
||||
String name = MiscUtils.getRandomizedName() + ".jar";
|
||||
File output = new File(tempDirectory + fs + name);
|
||||
|
||||
if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionDex.getModel()))
|
||||
Dex2Jar.dex2Jar(tempCopy, output);
|
||||
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
|
||||
Enjarify.apk2Jar(tempCopy, output);
|
||||
|
||||
container.classes = JarUtils.loadClasses(output);
|
||||
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
BytecodeViewer.files.add(container);
|
||||
} catch (final Exception e) {
|
||||
BytecodeViewer.handleException(e);
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
|
||||
File tempCopy = new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk");
|
||||
|
||||
FileUtils.copyFile(file, tempCopy);
|
||||
|
||||
FileContainer container = new FileContainer(tempCopy, file.getName());
|
||||
|
||||
if (BytecodeViewer.viewer.decodeAPKResources.isSelected()) {
|
||||
File decodedResources =
|
||||
new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk");
|
||||
APKTool.decodeResources(tempCopy, decodedResources, container);
|
||||
container.resourceFiles = JarUtils.loadResources(decodedResources);
|
||||
}
|
||||
|
||||
return true;
|
||||
Objects.requireNonNull(container.resourceFiles).putAll(JarUtils.loadResources(tempCopy)); //copy and rename
|
||||
// to prevent unicode filenames
|
||||
|
||||
String name = MiscUtils.getRandomizedName() + ".jar";
|
||||
File output = new File(tempDirectory + fs + name);
|
||||
|
||||
if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionDex.getModel()))
|
||||
Dex2Jar.dex2Jar(tempCopy, output);
|
||||
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
|
||||
Enjarify.apk2Jar(tempCopy, 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
BytecodeViewer.showMessage(fn + ": Header does not start with CAFEBABE, ignoring.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (final Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
return false;
|
||||
}
|
||||
final String name = file.getName();
|
||||
byte[] bytes = MiscUtils.getBytes(new FileInputStream(file));
|
||||
FileContainer container = new FileContainer(file);
|
||||
|
||||
return true;
|
||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||
{
|
||||
final ClassNode cn = JarUtils.getNode(bytes);
|
||||
|
||||
container.resourceClasses.put(FilenameUtils.removeExtension(name), cn);
|
||||
container.resourceClassBytes.put(name, bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
BytecodeViewer.showMessage(name + "\nHeader does not start with CAFEBABE\nimporting as resource instead.");
|
||||
|
||||
//TODO double check this
|
||||
container.resourceFiles.put(name, bytes);
|
||||
}
|
||||
BytecodeViewer.files.add(container);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,33 +19,30 @@ 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");
|
||||
|
||||
FileUtils.copyFile(file, tempCopy); //copy and rename to prevent unicode filenames
|
||||
|
||||
FileContainer container = new FileContainer(tempCopy, file.getName());
|
||||
|
||||
String name = MiscUtils.getRandomizedName() + ".jar";
|
||||
File output = new File(tempDirectory + fs + name);
|
||||
|
||||
if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionDex.getModel()))
|
||||
Dex2Jar.dex2Jar(tempCopy, output);
|
||||
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
|
||||
Enjarify.apk2Jar(tempCopy, output);
|
||||
|
||||
container.classes = JarUtils.loadClasses(output);
|
||||
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
BytecodeViewer.files.add(container);
|
||||
} catch (final Exception e) {
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
|
||||
return true;
|
||||
File tempCopy = new File(tempDirectory + fs + MiscUtils.randomString(32) + ".dex");
|
||||
|
||||
FileUtils.copyFile(file, tempCopy); //copy and rename to prevent unicode filenames
|
||||
|
||||
FileContainer container = new FileContainer(tempCopy, file.getName());
|
||||
|
||||
String name = MiscUtils.getRandomizedName() + ".jar";
|
||||
File output = new File(tempDirectory + fs + name);
|
||||
|
||||
if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionDex.getModel()))
|
||||
Dex2Jar.dex2Jar(tempCopy, output);
|
||||
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
|
||||
Enjarify.apk2Jar(tempCopy, 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,8 @@ public class SecurityMan extends SecurityManager
|
|||
}
|
||||
|
||||
if (allow && !blocking) {
|
||||
System.out.println("Allowing exec:" + cmd);
|
||||
System.out.println("Allowing exec: " + cmd);
|
||||
|
||||
} else throw new SecurityException("BCV is awesome, blocking(" + blocking + ") exec " + cmd);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue