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.apache.commons.io.FileUtils;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bootloader.Boot;
|
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.api.ExceptionUI;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.*;
|
import the.bytecode.club.bytecodeviewer.gui.components.*;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.TabbedPane;
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.TabbedPane;
|
||||||
|
@ -168,11 +169,6 @@ public class BytecodeViewer
|
||||||
//setup look and feel
|
//setup look and feel
|
||||||
Configuration.lafTheme.setLAF();
|
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
|
//set swing specific system properties
|
||||||
System.setProperty("swing.aatext", "true");
|
System.setProperty("swing.aatext", "true");
|
||||||
|
|
||||||
|
@ -189,7 +185,6 @@ public class BytecodeViewer
|
||||||
|
|
||||||
//handle CLI
|
//handle CLI
|
||||||
int CLI = CommandLineInput.parseCommandLine(args);
|
int CLI = CommandLineInput.parseCommandLine(args);
|
||||||
|
|
||||||
if (CLI == CommandLineInput.STOP)
|
if (CLI == CommandLineInput.STOP)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -200,10 +195,14 @@ public class BytecodeViewer
|
||||||
Boot.boot(args, CLI != CommandLineInput.GUI);
|
Boot.boot(args, CLI != CommandLineInput.GUI);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
installFatJar.start();
|
installFatJar.start();
|
||||||
|
}
|
||||||
|
|
||||||
if (CLI == CommandLineInput.GUI)
|
if (CLI == CommandLineInput.GUI)
|
||||||
|
{
|
||||||
BytecodeViewer.boot(false);
|
BytecodeViewer.boot(false);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BytecodeViewer.boot(true);
|
BytecodeViewer.boot(true);
|
||||||
|
@ -350,15 +349,20 @@ public class BytecodeViewer
|
||||||
/**
|
/**
|
||||||
* Returns the ClassNode by the specified name
|
* 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
|
* @param name the class name
|
||||||
* @return the ClassNode instance
|
* @return the ClassNode instance
|
||||||
*/
|
*/
|
||||||
public static ClassNode getClassNode(String name)
|
@Deprecated
|
||||||
|
public static ClassNode blindlySearchForClassNode(String name)
|
||||||
{
|
{
|
||||||
for (FileContainer container : files)
|
for (FileContainer container : files)
|
||||||
for (ClassNode c : container.classes)
|
{
|
||||||
if (c.name.equals(name))
|
ClassNode node = container.getClassNode(name);
|
||||||
return c;
|
if(node != null)
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -382,18 +386,6 @@ public class BytecodeViewer
|
||||||
return files;
|
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.
|
* Grabs the file contents of the loaded resources.
|
||||||
*
|
*
|
||||||
|
@ -403,8 +395,8 @@ public class BytecodeViewer
|
||||||
public static byte[] getFileContents(String name)
|
public static byte[] getFileContents(String name)
|
||||||
{
|
{
|
||||||
for (FileContainer container : files)
|
for (FileContainer container : files)
|
||||||
if (container.files.containsKey(name))
|
if (container.resourceFiles.containsKey(name))
|
||||||
return container.files.get(name);
|
return container.resourceFiles.get(name);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -426,8 +418,13 @@ public class BytecodeViewer
|
||||||
public static void updateNode(ClassNode oldNode, ClassNode newNode)
|
public static void updateNode(ClassNode oldNode, ClassNode newNode)
|
||||||
{
|
{
|
||||||
for (FileContainer container : files)
|
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<>();
|
ArrayList<ClassNode> a = new ArrayList<>();
|
||||||
|
|
||||||
for (FileContainer container : files)
|
for (FileContainer container : files)
|
||||||
for (ClassNode c : container.classes)
|
for (ClassNode c : container.resourceClasses.values())
|
||||||
if (!a.contains(c))
|
if (!a.contains(c))
|
||||||
a.add(c);
|
a.add(c);
|
||||||
|
|
||||||
|
@ -648,7 +645,20 @@ public class BytecodeViewer
|
||||||
return;
|
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());
|
Decompiler.PROCYON_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(target);
|
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||||
final ClassWriter cw = accept(cn);
|
final ClassWriter cw = accept(cn);
|
||||||
String contents = Decompiler.PROCYON_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
String contents = Decompiler.PROCYON_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||||
|
@ -233,7 +233,7 @@ public class CommandLineInput {
|
||||||
Decompiler.CFR_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
|
Decompiler.CFR_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(target);
|
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||||
final ClassWriter cw = accept(cn);
|
final ClassWriter cw = accept(cn);
|
||||||
String contents = Decompiler.CFR_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
String contents = Decompiler.CFR_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||||
|
@ -251,7 +251,7 @@ public class CommandLineInput {
|
||||||
Decompiler.FERNFLOWER_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
|
Decompiler.FERNFLOWER_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(target);
|
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||||
final ClassWriter cw = accept(cn);
|
final ClassWriter cw = accept(cn);
|
||||||
String contents = Decompiler.FERNFLOWER_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
String contents = Decompiler.FERNFLOWER_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||||
|
@ -269,7 +269,7 @@ public class CommandLineInput {
|
||||||
Decompiler.KRAKATAU_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
|
Decompiler.KRAKATAU_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(target);
|
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||||
final ClassWriter cw = accept(cn);
|
final ClassWriter cw = accept(cn);
|
||||||
String contents = Decompiler.KRAKATAU_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
String contents = Decompiler.KRAKATAU_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||||
|
@ -288,7 +288,7 @@ public class CommandLineInput {
|
||||||
//Decompiler.krakatauDA.decompileToZip(output.getAbsolutePath());
|
//Decompiler.krakatauDA.decompileToZip(output.getAbsolutePath());
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(target);
|
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||||
final ClassWriter cw = accept(cn);
|
final ClassWriter cw = accept(cn);
|
||||||
String contents = Decompiler.KRAKATAU_DISASSEMBLER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
String contents = Decompiler.KRAKATAU_DISASSEMBLER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||||
|
@ -307,7 +307,7 @@ public class CommandLineInput {
|
||||||
//Decompiler.jdgui.decompileToZip(output.getAbsolutePath());
|
//Decompiler.jdgui.decompileToZip(output.getAbsolutePath());
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(target);
|
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||||
final ClassWriter cw = accept(cn);
|
final ClassWriter cw = accept(cn);
|
||||||
String contents = Decompiler.JD_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
String contents = Decompiler.JD_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||||
|
@ -326,7 +326,7 @@ public class CommandLineInput {
|
||||||
//Decompiler.smali.decompileToZip(output.getAbsolutePath());
|
//Decompiler.smali.decompileToZip(output.getAbsolutePath());
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(target);
|
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||||
final ClassWriter cw = accept(cn);
|
final ClassWriter cw = accept(cn);
|
||||||
String contents = Decompiler.SMALI_DISASSEMBLER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
String contents = Decompiler.SMALI_DISASSEMBLER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||||
|
@ -345,7 +345,7 @@ public class CommandLineInput {
|
||||||
//Decompiler.smali.decompileToZip(output.getAbsolutePath());
|
//Decompiler.smali.decompileToZip(output.getAbsolutePath());
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(target);
|
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||||
final ClassWriter cw = accept(cn);
|
final ClassWriter cw = accept(cn);
|
||||||
String contents = Decompiler.JADX_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
String contents = Decompiler.JADX_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||||
|
|
|
@ -11,6 +11,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.BytecodeViewer.gson;
|
import static the.bytecode.club.bytecodeviewer.BytecodeViewer.gson;
|
||||||
|
import static the.bytecode.club.bytecodeviewer.Configuration.maxRecentFiles;
|
||||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,8 +39,8 @@ public class Settings
|
||||||
else
|
else
|
||||||
recentPlugins = DiskReader.loadArrayList(getBCVDirectory() + fs + "recentplugins.bcv", false);
|
recentPlugins = DiskReader.loadArrayList(getBCVDirectory() + fs + "recentplugins.bcv", false);
|
||||||
|
|
||||||
MiscUtils.deduplicateAndTrim(recentFiles, 25);
|
MiscUtils.deduplicateAndTrim(recentFiles, maxRecentFiles);
|
||||||
MiscUtils.deduplicateAndTrim(recentPlugins, 25);
|
MiscUtils.deduplicateAndTrim(recentPlugins, maxRecentFiles);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -56,7 +57,7 @@ public class Settings
|
||||||
{
|
{
|
||||||
recentFiles.remove(f.getAbsolutePath()); // already added on the list
|
recentFiles.remove(f.getAbsolutePath()); // already added on the list
|
||||||
recentFiles.add(0, f.getAbsolutePath());
|
recentFiles.add(0, f.getAbsolutePath());
|
||||||
MiscUtils.deduplicateAndTrim(recentFiles, 25);
|
MiscUtils.deduplicateAndTrim(recentFiles, maxRecentFiles);
|
||||||
DiskWriter.replaceFile(filesName, MiscUtils.listToString(recentFiles), false);
|
DiskWriter.replaceFile(filesName, MiscUtils.listToString(recentFiles), false);
|
||||||
resetRecentFilesMenu();
|
resetRecentFilesMenu();
|
||||||
}
|
}
|
||||||
|
@ -87,7 +88,7 @@ public class Settings
|
||||||
{
|
{
|
||||||
recentPlugins.remove(f.getAbsolutePath()); // already added on the list
|
recentPlugins.remove(f.getAbsolutePath()); // already added on the list
|
||||||
recentPlugins.add(0, f.getAbsolutePath());
|
recentPlugins.add(0, f.getAbsolutePath());
|
||||||
MiscUtils.deduplicateAndTrim(recentPlugins, 25);
|
MiscUtils.deduplicateAndTrim(recentPlugins, maxRecentFiles);
|
||||||
DiskWriter.replaceFile(pluginsName, MiscUtils.listToString(recentPlugins), false);
|
DiskWriter.replaceFile(pluginsName, MiscUtils.listToString(recentPlugins), false);
|
||||||
resetRecentFilesMenu();
|
resetRecentFilesMenu();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package the.bytecode.club.bytecodeviewer.api;
|
package the.bytecode.club.bytecodeviewer.api;
|
||||||
|
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import org.objectweb.asm.tree.MethodNode;
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
|
||||||
|
@ -12,11 +13,8 @@ public class ASMUtil
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Creates a new ClassNode instances from the provided byte[]
|
* 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);
|
ClassReader cr = new ClassReader(b);
|
||||||
ClassNode cn = new ClassNode();
|
ClassNode cn = new ClassNode();
|
||||||
|
@ -28,6 +26,26 @@ public class ASMUtil
|
||||||
return cn;
|
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)
|
public static MethodNode getMethodByName(ClassNode cn, String name)
|
||||||
{
|
{
|
||||||
for(MethodNode m : cn.methods)
|
for(MethodNode m : cn.methods)
|
||||||
|
|
|
@ -174,7 +174,7 @@ public class BCV
|
||||||
*/
|
*/
|
||||||
public static ClassNode getClassNode(String name) {
|
public static ClassNode getClassNode(String name) {
|
||||||
return the.bytecode.club.bytecodeviewer.BytecodeViewer
|
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.InnerClassNode;
|
||||||
import org.objectweb.asm.tree.MethodNode;
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||||
|
|
||||||
|
@ -101,7 +100,7 @@ public class ClassNodeDecompiler
|
||||||
if ((innerClassName != null)
|
if ((innerClassName != null)
|
||||||
&& !decompiledClasses.contains(innerClassName)) {
|
&& !decompiledClasses.contains(innerClassName)) {
|
||||||
decompiledClasses.add(innerClassName);
|
decompiledClasses.add(innerClassName);
|
||||||
ClassNode cn1 = BytecodeViewer.getClassNode(innerClassName);
|
ClassNode cn1 = BytecodeViewer.blindlySearchForClassNode(innerClassName);
|
||||||
if (cn1 != null) {
|
if (cn1 != null) {
|
||||||
sb.appendPrefix(" ");
|
sb.appendPrefix(" ");
|
||||||
sb.append(nl + nl);
|
sb.append(nl + nl);
|
||||||
|
|
|
@ -30,7 +30,6 @@ public class HTMLPane extends JEditorPane
|
||||||
{
|
{
|
||||||
HTMLPane pane = new HTMLPane();
|
HTMLPane pane = new HTMLPane();
|
||||||
|
|
||||||
text = text.replace("{previewCopy}", String.valueOf(PREVIEW_COPY));
|
|
||||||
text = text.replace("{fatJar}", String.valueOf(FAT_JAR));
|
text = text.replace("{fatJar}", String.valueOf(FAT_JAR));
|
||||||
text = text.replace("{java}", Configuration.java);
|
text = text.replace("{java}", Configuration.java);
|
||||||
text = text.replace("{javac}", Configuration.javac);
|
text = text.replace("{javac}", Configuration.javac);
|
||||||
|
|
|
@ -29,7 +29,6 @@ import javax.swing.tree.TreeNode;
|
||||||
import javax.swing.tree.TreePath;
|
import javax.swing.tree.TreePath;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
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.TranslatedStrings;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckBox;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckBox;
|
||||||
|
@ -169,9 +168,9 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
|
||||||
ImageRenderer renderer = new ImageRenderer();
|
ImageRenderer renderer = new ImageRenderer();
|
||||||
tree.setCellRenderer(renderer);
|
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;
|
String name = c.name;
|
||||||
final String[] spl = name.split("/");
|
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();
|
String name = entry.getKey();
|
||||||
final String[] spl = name.split("/");
|
final String[] spl = name.split("/");
|
||||||
|
@ -311,7 +310,7 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
|
||||||
String name = nameBuffer.toString();
|
String name = nameBuffer.toString();
|
||||||
if (name.endsWith(".class"))
|
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()));
|
name.substring(0, name.length() - ".class".length()));
|
||||||
|
|
||||||
if (cn != null)
|
if (cn != null)
|
||||||
|
|
|
@ -43,7 +43,7 @@ class PerformSearch extends BackgroundSearchThread
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FileContainer container : BytecodeViewer.files)
|
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());
|
searchBoxPane.searchType.details.search(container, c, srn, searchBoxPane.exact.isSelected());
|
||||||
|
|
||||||
Objects.requireNonNull(MainViewerGUI.getComponent(SearchBoxPane.class)).search.setEnabled(true);
|
Objects.requireNonNull(MainViewerGUI.getComponent(SearchBoxPane.class)).search.setEnabled(true);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer;
|
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.decompilers.Decompiler;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.ResourceViewPanel;
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.ResourceViewPanel;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor;
|
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 resourceViewPanel2 = new ResourceViewPanel(1, this);
|
||||||
public ResourceViewPanel resourceViewPanel3 = new ResourceViewPanel(2, 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 List<MethodParser> methods = Arrays.asList(new MethodParser(), new MethodParser(), new MethodParser());
|
||||||
public final String workingName;
|
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)
|
public void startPaneUpdater(final JButton button)
|
||||||
{
|
{
|
||||||
this.cn = BytecodeViewer.getClassNode(container, cn.name); //update the classnode
|
this.cn = container.getClassNode(cn.name); //update the classnode
|
||||||
setPanes();
|
|
||||||
|
|
||||||
|
setPanes();
|
||||||
refreshTitle();
|
refreshTitle();
|
||||||
|
|
||||||
resourceViewPanel1.createPane(this);
|
resourceViewPanel1.createPane(this);
|
||||||
resourceViewPanel2.createPane(this);
|
resourceViewPanel2.createPane(this);
|
||||||
resourceViewPanel3.createPane(this);
|
resourceViewPanel3.createPane(this);
|
||||||
|
|
||||||
final ClassWriter cw = new ClassWriter(0);
|
byte[] classBytes = getBytes();
|
||||||
try {
|
|
||||||
cn.accept(cw);
|
//TODO remove this once all of the importers have been properly updated to use a FileContainerImporter
|
||||||
} catch (Exception e) {
|
if(classBytes == null || classBytes.length == 0)
|
||||||
e.printStackTrace();
|
{
|
||||||
try {
|
System.err.println("WARNING: Imported using the old importer!");
|
||||||
Thread.sleep(200);
|
classBytes = ASMUtil.nodeToBytes(cn);
|
||||||
cn.accept(cw);
|
|
||||||
} catch (InterruptedException ignored) { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final byte[] b = cw.toByteArray();
|
resourceViewPanel1.updatePane(this, classBytes, button, isPanel1Editable());
|
||||||
resourceViewPanel1.updatePane(this, b, button, isPanel1Editable());
|
resourceViewPanel2.updatePane(this, classBytes, button, isPanel2Editable());
|
||||||
resourceViewPanel2.updatePane(this, b, button, isPanel2Editable());
|
resourceViewPanel3.updatePane(this, classBytes, button, isPanel3Editable());
|
||||||
resourceViewPanel3.updatePane(this, b, button, isPanel3Editable());
|
|
||||||
|
|
||||||
Thread t = new Thread(() ->
|
Thread dumpBuild = new Thread(() ->
|
||||||
{
|
{
|
||||||
BytecodeViewer.updateBusyStatus(true);
|
BytecodeViewer.updateBusyStatus(true);
|
||||||
|
|
||||||
|
@ -168,8 +130,6 @@ public class ClassViewer extends ResourceViewer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tempFiles = BCVResourceUtils.dumpTempFile(container);
|
|
||||||
|
|
||||||
BytecodeViewer.updateBusyStatus(false);
|
BytecodeViewer.updateBusyStatus(false);
|
||||||
|
|
||||||
if (resourceViewPanel1.decompiler != Decompiler.NONE)
|
if (resourceViewPanel1.decompiler != Decompiler.NONE)
|
||||||
|
@ -179,7 +139,7 @@ public class ClassViewer extends ResourceViewer
|
||||||
if (resourceViewPanel3.decompiler != Decompiler.NONE)
|
if (resourceViewPanel3.decompiler != Decompiler.NONE)
|
||||||
resourceViewPanel3.updateThread.startNewThread();
|
resourceViewPanel3.updateThread.startNewThread();
|
||||||
}, "ClassViewer Temp Dump");
|
}, "ClassViewer Temp Dump");
|
||||||
t.start();
|
dumpBuild.start();
|
||||||
|
|
||||||
if (isPanel1Editable() || isPanel2Editable() || isPanel3Editable())
|
if (isPanel1Editable() || isPanel2Editable() || isPanel3Editable())
|
||||||
{
|
{
|
||||||
|
@ -227,42 +187,6 @@ public class ClassViewer extends ResourceViewer
|
||||||
return BytecodeViewer.viewer.viewPane3.isPaneEditable();
|
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) {
|
public static void selectMethod(RSyntaxTextArea area, int methodLine) {
|
||||||
if (methodLine != area.getCaretLineNumber()) {
|
if (methodLine != area.getCaretLineNumber()) {
|
||||||
|
@ -343,5 +267,72 @@ public class ClassViewer extends ResourceViewer
|
||||||
} catch (BadLocationException ignored) { }
|
} 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;
|
private static final long serialVersionUID = -8650495368920680024L;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,5 +53,13 @@ public abstract class ResourceViewer extends JPanel
|
||||||
return tabName;
|
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;
|
private static final long serialVersionUID = -2965538493489119191L;
|
||||||
}
|
}
|
|
@ -147,7 +147,7 @@ public class AllatoriStringDecrypter extends Plugin
|
||||||
|
|
||||||
// We have to create new node for editing
|
// 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
|
// 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);
|
MethodNode decryptermethodnode = ASMUtil.getMethodByName(decrypterClassNode, decrypterMethodName);
|
||||||
|
|
||||||
if (decryptermethodnode != null)
|
if (decryptermethodnode != null)
|
||||||
|
|
|
@ -87,7 +87,7 @@ public class CompiledJavaPluginLaunchStrategy implements PluginLaunchStrategy {
|
||||||
String name = entry.getName();
|
String name = entry.getName();
|
||||||
if (name.endsWith(".class"))
|
if (name.endsWith(".class"))
|
||||||
{
|
{
|
||||||
byte[] bytes = JarUtils.getBytes(jis);
|
byte[] bytes = MiscUtils.getBytes(jis);
|
||||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -191,10 +191,7 @@ public class ResourceDecompiling
|
||||||
if (BytecodeViewer.autoCompileSuccessful())
|
if (BytecodeViewer.autoCompileSuccessful())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
final String s = BytecodeViewer.getCurrentlyOpenedClassNode().name;
|
final ClassNode cn = BytecodeViewer.getCurrentlyOpenedClassNode();
|
||||||
|
|
||||||
if (s == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Java Files",
|
"Select Java Files",
|
||||||
|
@ -230,7 +227,6 @@ public class ResourceDecompiling
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
Thread t1 = new Thread(() -> {
|
Thread t1 = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(s);
|
|
||||||
final ClassWriter cw = new ClassWriter(0);
|
final ClassWriter cw = new ClassWriter(0);
|
||||||
try {
|
try {
|
||||||
Objects.requireNonNull(cn).accept(cw);
|
Objects.requireNonNull(cn).accept(cw);
|
||||||
|
@ -282,7 +278,6 @@ public class ResourceDecompiling
|
||||||
if (result == 1) {
|
if (result == 1) {
|
||||||
Thread t1 = new Thread(() -> {
|
Thread t1 = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(s);
|
|
||||||
final ClassWriter cw = new ClassWriter(0);
|
final ClassWriter cw = new ClassWriter(0);
|
||||||
try {
|
try {
|
||||||
Objects.requireNonNull(cn).accept(cw);
|
Objects.requireNonNull(cn).accept(cw);
|
||||||
|
@ -308,7 +303,6 @@ public class ResourceDecompiling
|
||||||
if (result == 2) {
|
if (result == 2) {
|
||||||
Thread t1 = new Thread(() -> {
|
Thread t1 = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(s);
|
|
||||||
final ClassWriter cw = new ClassWriter(0);
|
final ClassWriter cw = new ClassWriter(0);
|
||||||
try {
|
try {
|
||||||
Objects.requireNonNull(cn).accept(cw);
|
Objects.requireNonNull(cn).accept(cw);
|
||||||
|
@ -334,7 +328,6 @@ public class ResourceDecompiling
|
||||||
if (result == 3) {
|
if (result == 3) {
|
||||||
Thread t1 = new Thread(() -> {
|
Thread t1 = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(s);
|
|
||||||
final ClassWriter cw = new ClassWriter(0);
|
final ClassWriter cw = new ClassWriter(0);
|
||||||
try {
|
try {
|
||||||
Objects.requireNonNull(cn).accept(cw);
|
Objects.requireNonNull(cn).accept(cw);
|
||||||
|
@ -362,7 +355,6 @@ public class ResourceDecompiling
|
||||||
if (result == 4) {
|
if (result == 4) {
|
||||||
Thread t1 = new Thread(() -> {
|
Thread t1 = new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
ClassNode cn = BytecodeViewer.getClassNode(s);
|
|
||||||
final ClassWriter cw = new ClassWriter(0);
|
final ClassWriter cw = new ClassWriter(0);
|
||||||
try {
|
try {
|
||||||
Objects.requireNonNull(cn).accept(cw);
|
Objects.requireNonNull(cn).accept(cw);
|
||||||
|
@ -371,18 +363,16 @@ public class ResourceDecompiling
|
||||||
try {
|
try {
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
Objects.requireNonNull(cn).accept(cw);
|
Objects.requireNonNull(cn).accept(cw);
|
||||||
} catch (InterruptedException ignored) {
|
} catch (InterruptedException ignored) { }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String contents = Decompiler.KRAKATAU_DECOMPILER.getDecompiler().decompileClassNode(cn,
|
String contents = Decompiler.KRAKATAU_DECOMPILER.getDecompiler().
|
||||||
cw.toByteArray());
|
decompileClassNode(cn, cw.toByteArray());
|
||||||
DiskWriter.replaceFile(path, contents, false);
|
DiskWriter.replaceFile(path, contents, false);
|
||||||
BytecodeViewer.updateBusyStatus(false);
|
BytecodeViewer.updateBusyStatus(false);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
BytecodeViewer.updateBusyStatus(false);
|
BytecodeViewer.updateBusyStatus(false);
|
||||||
BytecodeViewer.handleException(
|
BytecodeViewer.handleException(e);
|
||||||
e);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
t1.start();
|
t1.start();
|
||||||
|
|
|
@ -32,7 +32,6 @@ import java.util.Objects;
|
||||||
*/
|
*/
|
||||||
public class ImportResource implements Runnable
|
public class ImportResource implements Runnable
|
||||||
{
|
{
|
||||||
private boolean update = true;
|
|
||||||
private final File[] files;
|
private final File[] files;
|
||||||
|
|
||||||
public ImportResource(File[] files) {this.files = files;}
|
public ImportResource(File[] files) {this.files = files;}
|
||||||
|
@ -46,51 +45,44 @@ public class ImportResource implements Runnable
|
||||||
{
|
{
|
||||||
final String fn = file.getName();
|
final String fn = file.getName();
|
||||||
|
|
||||||
|
//check if file exists
|
||||||
if (!file.exists())
|
if (!file.exists())
|
||||||
{
|
{
|
||||||
update = false;
|
|
||||||
BytecodeViewer.showMessage("The file " + file.getAbsolutePath() + " could not be found.");
|
BytecodeViewer.showMessage("The file " + file.getAbsolutePath() + " could not be found.");
|
||||||
Settings.removeRecentFile(file);
|
Settings.removeRecentFile(file);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
//check if file is directory
|
||||||
|
if (file.isDirectory())
|
||||||
{
|
{
|
||||||
if (file.isDirectory())
|
Import.DIRECTORY.getImporter().open(file);
|
||||||
{
|
continue;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//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)
|
catch (final Exception e)
|
||||||
|
@ -100,11 +92,9 @@ public class ImportResource implements Runnable
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
BytecodeViewer.updateBusyStatus(false);
|
BytecodeViewer.updateBusyStatus(false);
|
||||||
|
try {
|
||||||
if (update)
|
Objects.requireNonNull(MainViewerGUI.getComponent(ResourceListPane.class)).updateTree();
|
||||||
try {
|
} catch (NullPointerException ignored) { }
|
||||||
Objects.requireNonNull(MainViewerGUI.getComponent(ResourceListPane.class)).updateTree();
|
|
||||||
} catch (NullPointerException ignored) { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,5 +26,5 @@ import java.io.File;
|
||||||
*/
|
*/
|
||||||
public interface Importer
|
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;
|
package the.bytecode.club.bytecodeviewer.resources.importing.impl;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
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.resources.importing.Importer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.*;
|
import the.bytecode.club.bytecodeviewer.util.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
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
|
public class APKResourceImporter implements Importer
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean open(File file) throws Exception
|
public void open(File file) throws Exception
|
||||||
{
|
{
|
||||||
try {
|
BytecodeViewer.updateBusyStatus(true);
|
||||||
BytecodeViewer.updateBusyStatus(true);
|
|
||||||
|
|
||||||
File tempCopy = new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk");
|
File tempCopy = new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk");
|
||||||
|
|
||||||
FileUtils.copyFile(file, tempCopy);
|
FileUtils.copyFile(file, tempCopy);
|
||||||
|
|
||||||
FileContainer container = new FileContainer(tempCopy, file.getName());
|
FileContainer container = new FileContainer(tempCopy, file.getName());
|
||||||
|
|
||||||
if (BytecodeViewer.viewer.decodeAPKResources.isSelected()) {
|
if (BytecodeViewer.viewer.decodeAPKResources.isSelected()) {
|
||||||
File decodedResources =
|
File decodedResources =
|
||||||
new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk");
|
new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk");
|
||||||
APKTool.decodeResources(tempCopy, decodedResources, container);
|
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
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
package the.bytecode.club.bytecodeviewer.resources.importing.impl;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
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.resources.importing.Importer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||||
|
@ -18,32 +18,26 @@ import java.io.FileInputStream;
|
||||||
public class ClassResourceImporter implements Importer
|
public class ClassResourceImporter implements Importer
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean open(File file) throws Exception
|
public void open(File file) throws Exception
|
||||||
{
|
{
|
||||||
final String fn = file.getName();
|
final String name = file.getName();
|
||||||
try
|
byte[] bytes = MiscUtils.getBytes(new FileInputStream(file));
|
||||||
{
|
FileContainer container = new FileContainer(file);
|
||||||
byte[] bytes = JarUtils.getBytes(new FileInputStream(file));
|
|
||||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
|
||||||
{
|
|
||||||
final ClassNode cn = JarUtils.getNode(bytes);
|
|
||||||
|
|
||||||
FileContainer container = new FileContainer(file);
|
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||||
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);
|
final ClassNode cn = JarUtils.getNode(bytes);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
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;
|
package the.bytecode.club.bytecodeviewer.resources.importing.impl;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
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.resources.importing.Importer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.*;
|
import the.bytecode.club.bytecodeviewer.util.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
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
|
public class DEXResourceImporter implements Importer
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean open(File file) throws Exception
|
public void open(File file) throws Exception
|
||||||
{
|
{
|
||||||
try {
|
BytecodeViewer.updateBusyStatus(true);
|
||||||
BytecodeViewer.updateBusyStatus(true);
|
|
||||||
|
|
||||||
File tempCopy = new File(tempDirectory + fs + MiscUtils.randomString(32) + ".dex");
|
File tempCopy = new File(tempDirectory + fs + MiscUtils.randomString(32) + ".dex");
|
||||||
|
|
||||||
FileUtils.copyFile(file, tempCopy); //copy and rename to prevent unicode filenames
|
FileUtils.copyFile(file, tempCopy); //copy and rename to prevent unicode filenames
|
||||||
|
|
||||||
FileContainer container = new FileContainer(tempCopy, file.getName());
|
FileContainer container = new FileContainer(tempCopy, file.getName());
|
||||||
|
|
||||||
String name = MiscUtils.getRandomizedName() + ".jar";
|
String name = MiscUtils.getRandomizedName() + ".jar";
|
||||||
File output = new File(tempDirectory + fs + name);
|
File output = new File(tempDirectory + fs + name);
|
||||||
|
|
||||||
if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionDex.getModel()))
|
if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionDex.getModel()))
|
||||||
Dex2Jar.dex2Jar(tempCopy, output);
|
Dex2Jar.dex2Jar(tempCopy, output);
|
||||||
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
|
else if (BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
|
||||||
Enjarify.apk2Jar(tempCopy, output);
|
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.updateBusyStatus(false);
|
||||||
BytecodeViewer.files.add(container);
|
BytecodeViewer.files.add(container);
|
||||||
} catch (final Exception e) {
|
|
||||||
BytecodeViewer.handleException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package the.bytecode.club.bytecodeviewer.resources.importing.impl;
|
package the.bytecode.club.bytecodeviewer.resources.importing.impl;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.importing.Import;
|
import the.bytecode.club.bytecodeviewer.resources.importing.Import;
|
||||||
|
@ -22,7 +23,7 @@ import java.util.Objects;
|
||||||
public class DirectoryResourceImporter implements Importer
|
public class DirectoryResourceImporter implements Importer
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean open(File file) throws Exception
|
public void open(File file) throws Exception
|
||||||
{
|
{
|
||||||
FileContainer container = new FileContainer(file);
|
FileContainer container = new FileContainer(file);
|
||||||
HashMap<String, byte[]> allDirectoryFiles = new HashMap<>();
|
HashMap<String, byte[]> allDirectoryFiles = new HashMap<>();
|
||||||
|
@ -61,29 +62,22 @@ public class DirectoryResourceImporter implements Importer
|
||||||
|
|
||||||
//attempt to import archives automatically
|
//attempt to import archives automatically
|
||||||
if (fileName.endsWith(".jar") || fileName.endsWith(".zip") || fileName.endsWith(".war") || fileName.endsWith(".ear"))
|
if (fileName.endsWith(".jar") || fileName.endsWith(".zip") || fileName.endsWith(".war") || fileName.endsWith(".ear"))
|
||||||
{
|
|
||||||
Import.ZIP.getImporter().open(child);
|
Import.ZIP.getImporter().open(child);
|
||||||
}
|
|
||||||
else if (fileName.endsWith(".apk"))
|
else if (fileName.endsWith(".apk"))
|
||||||
{
|
|
||||||
Import.APK.getImporter().open(child);
|
Import.APK.getImporter().open(child);
|
||||||
}
|
|
||||||
else if (fileName.endsWith(".dex"))
|
else if (fileName.endsWith(".dex"))
|
||||||
{
|
|
||||||
Import.DEX.getImporter().open(child);
|
Import.DEX.getImporter().open(child);
|
||||||
}
|
|
||||||
else if (fileName.endsWith(".class"))
|
else if (fileName.endsWith(".class"))
|
||||||
{
|
{
|
||||||
byte[] bytes = Files.readAllBytes(Paths.get(child.getAbsolutePath()));
|
byte[] bytes = Files.readAllBytes(Paths.get(child.getAbsolutePath()));
|
||||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||||
{
|
{
|
||||||
final ClassNode cn = JarUtils.getNode(bytes);
|
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())));
|
allDirectoryFiles.put(trimmedPath, Files.readAllBytes(Paths.get(child.getAbsolutePath())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,9 +86,8 @@ public class DirectoryResourceImporter implements Importer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
container.classes.addAll(allDirectoryClasses.values());
|
container.resourceClasses.putAll(allDirectoryClasses);
|
||||||
container.files = allDirectoryFiles;
|
container.resourceFiles = allDirectoryFiles;
|
||||||
BytecodeViewer.files.add(container);
|
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.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
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.JarUtils;
|
||||||
|
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -16,16 +18,15 @@ import java.util.HashMap;
|
||||||
public class FileResourceImporter implements Importer
|
public class FileResourceImporter implements Importer
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean open(File file) throws Exception
|
public void open(File file) throws Exception
|
||||||
{
|
{
|
||||||
HashMap<String, byte[]> files1 = new HashMap<>();
|
//create the new file container
|
||||||
byte[] bytes = JarUtils.getBytes(new FileInputStream(file));
|
|
||||||
files1.put(file.getName(), bytes);
|
|
||||||
|
|
||||||
|
|
||||||
FileContainer container = new FileContainer(file);
|
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);
|
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 me.konloch.kontainer.io.DiskWriter;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.importing.Import;
|
import the.bytecode.club.bytecodeviewer.resources.importing.Import;
|
||||||
|
@ -14,6 +13,7 @@ import java.io.*;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.zip.ZipEntry;
|
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.fs;
|
||||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
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
|
public class XAPKResourceImporter implements Importer
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean open(File file) throws Exception
|
public void open(File file) throws Exception
|
||||||
{
|
{
|
||||||
FileContainer container = new FileContainer(file);
|
FileContainer container = new FileContainer(file);
|
||||||
HashMap<String, byte[]> allDirectoryFiles = new HashMap<>();
|
HashMap<String, byte[]> allDirectoryFiles = new HashMap<>();
|
||||||
HashMap<String, ClassNode> allDirectoryClasses = new HashMap<>();
|
|
||||||
|
|
||||||
Configuration.silenceExceptionGUI++; //turn exceptions off
|
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();
|
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||||
while (entries.hasMoreElements())
|
while (entries.hasMoreElements())
|
||||||
|
@ -69,13 +68,11 @@ public class XAPKResourceImporter implements Importer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Configuration.silenceExceptionGUI--; //turn exceptions back on
|
Configuration.silenceExceptionGUI--; //turn exceptions back on
|
||||||
BytecodeViewer.viewer.clearBusyStatus(); //clear errant busy signals from failed APK imports
|
BytecodeViewer.viewer.clearBusyStatus(); //clear errant busy signals from failed APK imports
|
||||||
|
container.resourceFiles = allDirectoryFiles; //store the file resource
|
||||||
container.classes.addAll(allDirectoryClasses.values());
|
BytecodeViewer.files.add(container); //add the file container to BCV's total loaded files
|
||||||
container.files = allDirectoryFiles;
|
|
||||||
BytecodeViewer.files.add(container);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public File exportTo(File original, String extension, byte[] bytes)
|
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.BytecodeViewer;
|
||||||
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
|
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.importing.Importer;
|
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.JarUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -15,32 +17,15 @@ import java.io.IOException;
|
||||||
public class ZipResourceImporter implements Importer
|
public class ZipResourceImporter implements Importer
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean open(File file) throws Exception
|
public void open(File file) throws Exception
|
||||||
{
|
{
|
||||||
//attempt to load archives using the first method
|
//create the new file container
|
||||||
try
|
FileContainer container = new FileContainer(file);
|
||||||
{
|
//create the new file importer
|
||||||
JarUtils.importArchiveA(file);
|
FileContainerImporter importer = new FileContainerImporter(container);
|
||||||
}
|
//import the file as zip into the file container
|
||||||
catch (IOException z)
|
importer.importAsZip();
|
||||||
{
|
//add the file container to BCV's total loaded files
|
||||||
//attempt to load archives using the fallback method on fail
|
BytecodeViewer.files.add(container);
|
||||||
try
|
|
||||||
{
|
|
||||||
JarUtils.importArchiveB(file);
|
|
||||||
}
|
|
||||||
catch (final Exception e)
|
|
||||||
{
|
|
||||||
BytecodeViewer.handleException(e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (final Exception e)
|
|
||||||
{
|
|
||||||
BytecodeViewer.handleException(e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,75 +33,6 @@ import static the.bytecode.club.bytecodeviewer.Constants.RT_JAR_DUMPED;
|
||||||
*/
|
*/
|
||||||
public class BCVResourceUtils
|
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
|
//rt.jar check
|
||||||
public synchronized static void rtCheck()
|
public synchronized static void rtCheck()
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,6 @@ import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
|
||||||
|
@ -46,16 +45,13 @@ public class FileContainer {
|
||||||
public String name;
|
public String name;
|
||||||
public File APKToolContents = null;
|
public File APKToolContents = null;
|
||||||
|
|
||||||
public HashMap<String, byte[]> files = new HashMap<>();
|
public HashMap<String, byte[]> resourceFiles = new HashMap<>();
|
||||||
public ArrayList<ClassNode> classes = new ArrayList<>();
|
public HashMap<String, byte[]> resourceClassBytes = new HashMap<>();
|
||||||
|
public HashMap<String, ClassNode> resourceClasses = new HashMap<>();
|
||||||
|
|
||||||
public ClassNode getClassNode(String name)
|
public ClassNode getClassNode(String name)
|
||||||
{
|
{
|
||||||
for (ClassNode c : classes)
|
return resourceClasses.get(name);
|
||||||
if (c.name.equals(name))
|
|
||||||
return c;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateWorkName(String 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.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
@ -17,6 +18,7 @@ import java.util.zip.ZipInputStream;
|
||||||
import me.konloch.kontainer.io.DiskWriter;
|
import me.konloch.kontainer.io.DiskWriter;
|
||||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
|
@ -45,11 +47,14 @@ import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||||
/**
|
/**
|
||||||
* Loading and saving jars
|
* Loading and saving jars
|
||||||
*
|
*
|
||||||
|
* NOTE: This is in the process of being replaced with the Import & Export API
|
||||||
|
*
|
||||||
* @author Konloch
|
* @author Konloch
|
||||||
* @author WaterWolf
|
* @author WaterWolf
|
||||||
* @since 09/26/2011
|
* @since 09/26/2011
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public class JarUtils
|
public class JarUtils
|
||||||
{
|
{
|
||||||
public static Object LOCK = new Object();
|
public static Object LOCK = new Object();
|
||||||
|
@ -70,7 +75,7 @@ public class JarUtils
|
||||||
while ((entry = jis.getNextEntry()) != null) {
|
while ((entry = jis.getNextEntry()) != null) {
|
||||||
try {
|
try {
|
||||||
final String name = entry.getName();
|
final String name = entry.getName();
|
||||||
final byte[] bytes = getBytes(jis);
|
final byte[] bytes = MiscUtils.getBytes(jis);
|
||||||
if (!name.endsWith(".class")) {
|
if (!name.endsWith(".class")) {
|
||||||
if (!entry.isDirectory())
|
if (!entry.isDirectory())
|
||||||
files.put(name, bytes);
|
files.put(name, bytes);
|
||||||
|
@ -79,7 +84,7 @@ public class JarUtils
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
final ClassNode cn = getNode(bytes);
|
final ClassNode cn = getNode(bytes);
|
||||||
container.classes.add(cn);
|
container.resourceClasses.put(FilenameUtils.removeExtension(name), cn);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("Skipping: " + name);
|
System.err.println("Skipping: " + name);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -100,7 +105,7 @@ public class JarUtils
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jis.close();
|
jis.close();
|
||||||
container.files = files;
|
container.resourceFiles = files;
|
||||||
BytecodeViewer.files.add(container);
|
BytecodeViewer.files.add(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +131,7 @@ public class JarUtils
|
||||||
String name = entry.getName();
|
String name = entry.getName();
|
||||||
if (!entry.isDirectory()) {
|
if (!entry.isDirectory()) {
|
||||||
try (InputStream in = zipFile.getInputStream(entry)) {
|
try (InputStream in = zipFile.getInputStream(entry)) {
|
||||||
final byte[] bytes = getBytes(in);
|
final byte[] bytes = MiscUtils.getBytes(in);
|
||||||
|
|
||||||
if (!name.endsWith(".class")) {
|
if (!name.endsWith(".class")) {
|
||||||
files.put(name, bytes);
|
files.put(name, bytes);
|
||||||
|
@ -135,7 +140,7 @@ public class JarUtils
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
final ClassNode cn = getNode(bytes);
|
final ClassNode cn = getNode(bytes);
|
||||||
container.classes.add(cn);
|
container.resourceClasses.put(FilenameUtils.removeExtension(name), cn);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -149,7 +154,7 @@ public class JarUtils
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
container.files = files;
|
container.resourceFiles = files;
|
||||||
BytecodeViewer.files.add(container);
|
BytecodeViewer.files.add(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +167,7 @@ public class JarUtils
|
||||||
try {
|
try {
|
||||||
final String name = entry.getName();
|
final String name = entry.getName();
|
||||||
if (name.endsWith(".class")) {
|
if (name.endsWith(".class")) {
|
||||||
byte[] bytes = getBytes(jis);
|
byte[] bytes = MiscUtils.getBytes(jis);
|
||||||
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
if (MiscUtils.getFileHeader(bytes).equalsIgnoreCase("cafebabe"))
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
@ -205,7 +210,7 @@ public class JarUtils
|
||||||
final String name = entry.getName();
|
final String name = entry.getName();
|
||||||
if (!name.endsWith(".class") && !name.endsWith(".dex")) {
|
if (!name.endsWith(".class") && !name.endsWith(".dex")) {
|
||||||
if (!entry.isDirectory())
|
if (!entry.isDirectory())
|
||||||
files.put(name, getBytes(jis));
|
files.put(name, MiscUtils.getBytes(jis));
|
||||||
|
|
||||||
jis.closeEntry();
|
jis.closeEntry();
|
||||||
}
|
}
|
||||||
|
@ -218,25 +223,6 @@ public class JarUtils
|
||||||
jis.close();
|
jis.close();
|
||||||
|
|
||||||
return files;
|
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) {
|
public static ClassNode getNode(final byte[] bytez) {
|
||||||
synchronized (LOCK)
|
synchronized (LOCK)
|
||||||
{
|
{
|
||||||
return ASMUtil.getClassNode(bytez);
|
return ASMUtil.bytesToNode(bytez);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +264,7 @@ public class JarUtils
|
||||||
out.closeEntry();
|
out.closeEntry();
|
||||||
|
|
||||||
for (FileContainer container : BytecodeViewer.files)
|
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();
|
String filename = entry.getKey();
|
||||||
if (!filename.startsWith("META-INF")) {
|
if (!filename.startsWith("META-INF")) {
|
||||||
out.putNextEntry(new ZipEntry(filename));
|
out.putNextEntry(new ZipEntry(filename));
|
||||||
|
@ -299,7 +285,8 @@ public class JarUtils
|
||||||
* @param nodeList The loaded ClassNodes
|
* @param nodeList The loaded ClassNodes
|
||||||
* @param path the exact jar output path
|
* @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)
|
synchronized (LOCK)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -380,7 +367,7 @@ public class JarUtils
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FileContainer container : BytecodeViewer.files)
|
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();
|
String filename = entry.getKey();
|
||||||
if (!filename.startsWith("META-INF")) {
|
if (!filename.startsWith("META-INF")) {
|
||||||
if (!noDupe.contains(filename)) {
|
if (!noDupe.contains(filename)) {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import the.bytecode.club.bytecodeviewer.translation.Language;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
@ -181,7 +180,7 @@ public class MiscUtils
|
||||||
StringBuilder block = new StringBuilder();
|
StringBuilder block = new StringBuilder();
|
||||||
for (FileContainer container : fileContainers) {
|
for (FileContainer container : fileContainers) {
|
||||||
block.append(container.name);
|
block.append(container.name);
|
||||||
for (ClassNode node : container.classes) {
|
for (ClassNode node : container.resourceClasses.values()) {
|
||||||
block.append(node.name);
|
block.append(node.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,4 +272,26 @@ public class MiscUtils
|
||||||
|
|
||||||
return path;
|
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) {
|
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);
|
} else throw new SecurityException("BCV is awesome, blocking(" + blocking + ") exec " + cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue