diff --git a/libs/android-5.1.jar b/libs/android-5.1.jar new file mode 100644 index 00000000..873cf828 Binary files /dev/null and b/libs/android-5.1.jar differ diff --git a/libs/annotations-17.0.0.jar b/libs/annotations-17.0.0.jar new file mode 100644 index 00000000..477f7d02 Binary files /dev/null and b/libs/annotations-17.0.0.jar differ diff --git a/libs/cloning-1.9.12.jar b/libs/cloning-1.9.12.jar new file mode 100644 index 00000000..162bf38b Binary files /dev/null and b/libs/cloning-1.9.12.jar differ diff --git a/libs/dx-1.16.jar b/libs/dx-1.16.jar new file mode 100644 index 00000000..6e468ce7 Binary files /dev/null and b/libs/dx-1.16.jar differ diff --git a/libs/gson-2.8.5.jar b/libs/gson-2.8.5.jar new file mode 100644 index 00000000..0d5baf3f Binary files /dev/null and b/libs/gson-2.8.5.jar differ diff --git a/libs/jadx-core.jar b/libs/jadx-core.jar new file mode 100644 index 00000000..b50c56c8 Binary files /dev/null and b/libs/jadx-core.jar differ diff --git a/libs/objenesis-3.0.1.jar b/libs/objenesis-3.0.1.jar new file mode 100644 index 00000000..8521c847 Binary files /dev/null and b/libs/objenesis-3.0.1.jar differ diff --git a/libs/slf4j-api-1.7.26.jar b/libs/slf4j-api-1.7.26.jar new file mode 100644 index 00000000..d2f27ace Binary files /dev/null and b/libs/slf4j-api-1.7.26.jar differ diff --git a/src/the/bytecode/club/bootloader/InitialBootScreen.java b/src/the/bytecode/club/bootloader/InitialBootScreen.java index 5010fd8d..6053b490 100644 --- a/src/the/bytecode/club/bootloader/InitialBootScreen.java +++ b/src/the/bytecode/club/bootloader/InitialBootScreen.java @@ -5,6 +5,9 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Toolkit; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowStateListener; import java.io.IOException; import javax.swing.JEditorPane; @@ -13,6 +16,7 @@ import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.text.html.HTMLEditorKit; +import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.Resources; /*************************************************************************** @@ -44,7 +48,14 @@ public class InitialBootScreen extends JFrame { private JProgressBar progressBar = new JProgressBar(); public InitialBootScreen() throws IOException { - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + BytecodeViewer.canExit = true; + System.exit(0); + } + }); this.setIconImages(Resources.iconList); int i = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight(); diff --git a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java index a87246d1..c8a0a50b 100644 --- a/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/BytecodeViewer.java @@ -16,8 +16,12 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Enumeration; import java.util.HashMap; import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; import javax.swing.JDialog; import javax.swing.JFileChooser; @@ -26,12 +30,14 @@ import javax.swing.JOptionPane; import javax.swing.UIManager; import javax.swing.filechooser.FileFilter; +import com.google.gson.reflect.TypeToken; import me.konloch.kontainer.io.DiskReader; import me.konloch.kontainer.io.DiskWriter; import me.konloch.kontainer.io.HTTPRequest; import org.apache.commons.io.FileUtils; import org.objectweb.asm.tree.ClassNode; +import com.google.gson.*; import the.bytecode.club.bootloader.Boot; import the.bytecode.club.bootloader.ILoader; @@ -68,6 +74,10 @@ import the.bytecode.club.bytecodeviewer.util.*; ***************************************************************************/ /** + * TODO: + * open as folder doesn't actually work + * smali compile + * * A lightweight Java Reverse Engineering suite, developed by Konloch - http://konloch.me * * All you have to do is add a jar or class file into the workspace, @@ -109,7 +119,7 @@ import the.bytecode.club.bytecodeviewer.util.*; public class BytecodeViewer { /*per version*/ - public static final String VERSION = "2.9.17"; + public static final String VERSION = "2.9.18"; public static String krakatauVersion = "12"; public static String enjarifyVersion = "4"; public static final boolean BLOCK_TAB_MENU = true; @@ -142,22 +152,46 @@ public class BytecodeViewer public static String nl = System.getProperty("line.separator"); private static File BCVDir = new File(System.getProperty("user.home") + fs + ".Bytecode-Viewer"); public static File RJ_JAR = new File(System.getProperty("java.home") + fs + "lib" + fs + "rt.jar"); - private static String filesName = getBCVDirectory() + fs + "recentfiles.bcv"; - private static String pluginsName = getBCVDirectory() + fs + "recentplugins.bcv"; + private static String filesName = getBCVDirectory() + fs + "recentfiles.json"; + private static String pluginsName = getBCVDirectory() + fs + "recentplugins.json"; public static String settingsName = getBCVDirectory() + fs + "settings.bcv"; public static String tempDirectory = getBCVDirectory() + fs + "bcv_temp" + fs; public static String libsDirectory = getBCVDirectory() + fs + "libs" + fs; public static String krakatauWorkingDirectory = getBCVDirectory() + fs + "krakatau_" + krakatauVersion; public static String enjarifyWorkingDirectory = getBCVDirectory() + fs + "enjarify_" + enjarifyVersion; - private static ArrayList recentFiles = DiskReader.loadArrayList(filesName, false); - private static ArrayList recentPlugins = DiskReader.loadArrayList(pluginsName, false); public static boolean runningObfuscation = false; private static long start = System.currentTimeMillis(); - public static String lastDirectory = ""; + public static String lastDirectory = "."; public static ArrayList createdProcesses = new ArrayList(); public static Refactorer refactorer = new Refactorer(); public static boolean pingback = false; public static boolean deleteForeignLibraries = true; + public static boolean canExit = false; + public static Gson gson; + + private static ArrayList recentPlugins; + private static ArrayList recentFiles; + + static + { + try + { + gson = new GsonBuilder().setPrettyPrinting().create(); + if(new File(filesName).exists()) + recentFiles = gson.fromJson(DiskReader.loadAsString(filesName), new TypeToken>() {}.getType()); + else + recentFiles = DiskReader.loadArrayList(getBCVDirectory() + fs + "recentfiles.bcv", false); + + if(new File(pluginsName).exists()) + recentPlugins = gson.fromJson(DiskReader.loadAsString(pluginsName), new TypeToken>() {}.getType()); + else + recentPlugins = DiskReader.loadArrayList(getBCVDirectory() + fs + "recentplugins.bcv", false); + } + catch (Exception e) + { + e.printStackTrace(); + } + } /** * The version checker thread @@ -812,7 +846,7 @@ public class BytecodeViewer } else { if (f.isDirectory()) { FileContainer container = new FileContainer(f); - HashMap files = new HashMap(); + HashMap files = new HashMap<>(); boolean finished = false; ArrayList totalFiles = new ArrayList(); totalFiles.add(f); @@ -844,10 +878,10 @@ public class BytecodeViewer container.files = files; BytecodeViewer.files.add(container); } else { - if (fn.endsWith(".jar") || fn.endsWith(".zip")) { + if (fn.endsWith(".jar") || fn.endsWith(".zip") || fn.endsWith(".war")) { try { JarUtils.put(f); - } catch (final java.util.zip.ZipException z) { + } catch (java.io.IOException z) { try { JarUtils.put2(f); } catch (final Exception e) { @@ -938,7 +972,7 @@ public class BytecodeViewer } return; } else { - HashMap files = new HashMap(); + HashMap files = new HashMap<>(); byte[] bytes = JarUtils.getBytes(new FileInputStream(f)); files.put(f.getName(), bytes); @@ -1201,10 +1235,7 @@ public class BytecodeViewer * @return string with newline per array object */ private static String quickConvert(ArrayList a) { - String s = ""; - for (String r : a) - s += r + nl; - return s; + return gson.toJson(a); } private static long last = System.currentTimeMillis(); diff --git a/src/the/bytecode/club/bytecodeviewer/CommandLineInput.java b/src/the/bytecode/club/bytecodeviewer/CommandLineInput.java index 68f2b4e9..459996e6 100644 --- a/src/the/bytecode/club/bytecodeviewer/CommandLineInput.java +++ b/src/the/bytecode/club/bytecodeviewer/CommandLineInput.java @@ -322,6 +322,7 @@ public class CommandLineInput { System.out.println("Finished."); System.out.println("Bytecode Viewer CLI v" + BytecodeViewer.VERSION + " by @Konloch - http://bytecodeviewer.com"); + BytecodeViewer.canExit = true; System.exit(0); } catch (Exception e) { new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); diff --git a/src/the/bytecode/club/bytecodeviewer/SecurityMan.java b/src/the/bytecode/club/bytecodeviewer/SecurityMan.java index f4095657..dbb8c82f 100644 --- a/src/the/bytecode/club/bytecodeviewer/SecurityMan.java +++ b/src/the/bytecode/club/bytecodeviewer/SecurityMan.java @@ -121,6 +121,10 @@ public class SecurityMan extends SecurityManager { @Override public void checkExit(int status) { + if(!BytecodeViewer.canExit) + { + throw new SecurityException("BCV is awesome, blocking System.exit("+status+");"); + } } @Override diff --git a/src/the/bytecode/club/bytecodeviewer/Settings.java b/src/the/bytecode/club/bytecodeviewer/Settings.java index 18e60f02..2eb7f44d 100644 --- a/src/the/bytecode/club/bytecodeviewer/Settings.java +++ b/src/the/bytecode/club/bytecodeviewer/Settings.java @@ -329,6 +329,8 @@ public class Settings { BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1KrakatauBytecode.getModel(), true); else if (decompiler == 9) BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.panel1JDGUI.getModel(), true); + else if (decompiler == 10) + BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.jadxJ1.getModel(), true); decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 82, false)); if (decompiler == 0) @@ -351,6 +353,8 @@ public class Settings { BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2KrakatauBytecode.getModel(), true); else if (decompiler == 9) BytecodeViewer.viewer.panelGroup2.setSelected(BytecodeViewer.viewer.panel2JDGUI.getModel(), true); + else if (decompiler == 10) + BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.jadxJ2.getModel(), true); decompiler = Integer.parseInt(DiskReader.loadString(BytecodeViewer.settingsName, 83, false)); if (decompiler == 0) @@ -373,6 +377,8 @@ public class Settings { BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3KrakatauBytecode.getModel(), true); else if (decompiler == 9) BytecodeViewer.viewer.panelGroup3.setSelected(BytecodeViewer.viewer.panel3JDGUI.getModel(), true); + else if (decompiler == 10) + BytecodeViewer.viewer.panelGroup1.setSelected(BytecodeViewer.viewer.jadxJ3.getModel(), true); BytecodeViewer.viewer.refreshOnChange.setSelected(Boolean.parseBoolean(DiskReader.loadString(BytecodeViewer.settingsName, 84, false))); diff --git a/src/the/bytecode/club/bytecodeviewer/compilers/SmaliAssembler.java b/src/the/bytecode/club/bytecodeviewer/compilers/SmaliAssembler.java index fb028cca..e420b868 100644 --- a/src/the/bytecode/club/bytecodeviewer/compilers/SmaliAssembler.java +++ b/src/the/bytecode/club/bytecodeviewer/compilers/SmaliAssembler.java @@ -55,8 +55,9 @@ public class SmaliAssembler extends Compiler { } try { - com.googlecode.d2j.smali.SmaliCmd.main(new String[]{tempSmaliFolder.getAbsolutePath(), "-o", tempDex.getAbsolutePath()}); + com.googlecode.d2j.smali.SmaliCmd.main(new String[]{tempSmaliFolder.getAbsolutePath()});//, "-o", tempDex.getAbsolutePath()}); } catch (Exception e) { + e.printStackTrace(); new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); } diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/CFRDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/CFRDecompiler.java index 75dd25e3..f2573514 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/CFRDecompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/CFRDecompiler.java @@ -48,11 +48,51 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils; public class CFRDecompiler extends Decompiler { + private static final String[] WINDOWS_IS_GREAT = new String[] + { + "CON", + "PRN", + "AUX", + "NUL", + "COM1", + "COM2", + "COM3", + "COM4", + "COM5", + "COM6", + "COM7", + "COM8", + "COM9", + "LPT1", + "LPT2", + "LPT3", + "LPT4", + "LPT5", + "LPT6", + "LPT7", + "LPT8", + "LPT9" + }; + + public static String windowsFun(String base) + { + for(String s : WINDOWS_IS_GREAT) + { + if(base.contains(s.toLowerCase())) + { + base = base.replace(s.toLowerCase(), "BCV"); + } + } + + return base; + } + @Override public String decompileClassNode(ClassNode cn, byte[] b) { - String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs; + String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs.toLowerCase(); String exception = ""; + //final File tempClass = new File(windowsFun(MiscUtils.getUniqueName(fileStart, ".class") + ".class")); final File tempClass = new File(MiscUtils.getUniqueName(fileStart, ".class") + ".class"); try { @@ -66,6 +106,7 @@ public class CFRDecompiler extends Decompiler { } String fuckery = fuckery(fileStart); + /*if (!BytecodeViewer.fatJar) { try { ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll( @@ -84,6 +125,7 @@ public class CFRDecompiler extends Decompiler { } else { org.benf.cfr.reader.Main.main(generateMainMethod(tempClass.getAbsolutePath(), fuckery)); }*/ + try { org.benf.cfr.reader.Main.main(generateMainMethod(tempClass.getAbsolutePath(), fuckery)); @@ -104,8 +146,6 @@ public class CFRDecompiler extends Decompiler { return findFile(file.listFiles()); return "CFR error! Send the stacktrace to Konloch at http://the.bytecode.club or konloch@gmail.com" + BytecodeViewer.nl + BytecodeViewer.nl + "Suggested Fix: Click refresh class, if it fails again try another decompiler." + BytecodeViewer.nl + BytecodeViewer.nl + exception; - - } Random r = new Random(); diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/Decompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/Decompiler.java index 287ffb8b..b2c00841 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/Decompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/Decompiler.java @@ -36,8 +36,9 @@ public abstract class Decompiler { public final static Decompiler cfr = new CFRDecompiler(); public final static KrakatauDecompiler krakatau = new KrakatauDecompiler(); public final static KrakatauDisassembler krakatauDA = new KrakatauDisassembler(); - public final static Decompiler smali = new SmaliDisassembler(); + public final static SmaliDisassembler smali = new SmaliDisassembler(); public final static Decompiler jdgui = new JDGUIDecompiler(); + public final static Decompiler jadx = new JADXDecompiler(); public abstract String decompileClassNode(ClassNode cn, byte[] b); diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/JADXDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/JADXDecompiler.java new file mode 100644 index 00000000..5e7b699d --- /dev/null +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/JADXDecompiler.java @@ -0,0 +1,131 @@ +package the.bytecode.club.bytecodeviewer.decompilers; + +import jadx.api.JadxArgs; +import jadx.api.JadxDecompiler; +import me.konloch.kontainer.io.DiskReader; +import org.objectweb.asm.tree.ClassNode; +import the.bytecode.club.bytecodeviewer.BytecodeViewer; +import the.bytecode.club.bytecodeviewer.util.MiscUtils; + +import java.io.*; +import java.util.Deque; +import java.util.LinkedList; +import java.util.Random; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/*************************************************************************** + * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite * + * Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +/** + * JADX Java Wrapper + * + * @author Konloch + */ + +public class JADXDecompiler extends Decompiler +{ + @Override + public String decompileClassNode(ClassNode cn, byte[] b) { + String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs; + + String exception = ""; + final File tempClass = new File(MiscUtils.getUniqueName(fileStart, ".class") + ".class"); + + try { + final FileOutputStream fos = new FileOutputStream(tempClass); + + fos.write(b); + + fos.close(); + } catch (final IOException e) { + new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + } + + File fuckery = new File(fuckery(fileStart)); + try + { + JadxArgs args = new JadxArgs(); + args.getInputFiles().add(tempClass); + args.setOutDir(fuckery); + + JadxDecompiler jadx = new JadxDecompiler(args); + jadx.load(); + jadx.save(); + } + catch(StackOverflowError | Exception e) + { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + e.printStackTrace(); + + exception = "Bytecode Viewer Version: " + BytecodeViewer.VERSION + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString(); + } + + tempClass.delete(); + + if(fuckery.exists()) + return findFile(fuckery.listFiles()); + + return "JADX error! Send the stacktrace to Konloch at http://the.bytecode.club or konloch@gmail.com" + BytecodeViewer.nl + BytecodeViewer.nl + "Suggested Fix: Click refresh class, if it fails again try another decompiler." + BytecodeViewer.nl + BytecodeViewer.nl + exception; + + + } + + Random r = new Random(); + File f; + + public String fuckery(String start) { + boolean b = false; + while (!b) { + f = new File(start + r.nextInt(Integer.MAX_VALUE)); + if (!f.exists()) + return f.toString(); + } + + return null; + } + + public String findFile(File[] fA) { + for (File f : fA) { + if (f.isDirectory()) + return findFile(f.listFiles()); + else { + String s = ""; + try { + s = DiskReader.loadAsString(f.getAbsolutePath()); + } catch (Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + e.printStackTrace(); + + String exception = "Bytecode Viewer Version: " + BytecodeViewer.VERSION + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString(); + return "JADX error! Send the stacktrace to Konloch at http://the.bytecode.club or konloch@gmail.com" + BytecodeViewer.nl + BytecodeViewer.nl + "Suggested Fix: Click refresh class, if it fails again try another decompiler." + BytecodeViewer.nl + BytecodeViewer.nl + exception; + } + return s; + } + } + return "CFR error!" + BytecodeViewer.nl + BytecodeViewer.nl + "Suggested Fix: Click refresh class, if it fails again try another decompiler."; + } + + @Override + public void decompileToZip(String sourceJar, String zipName) + { + } + +} diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/ProcyonDecompiler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/ProcyonDecompiler.java index ce9136d2..57be6136 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/ProcyonDecompiler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/ProcyonDecompiler.java @@ -125,7 +125,7 @@ public class ProcyonDecompiler extends Decompiler { .getCanonicalPath()); DecompilationOptions decompilationOptions = new DecompilationOptions(); - decompilationOptions.setSettings(DecompilerSettings.javaDefaults()); + decompilationOptions.setSettings(settings); decompilationOptions.setFullDecompilation(true); TypeDefinition resolvedType = null; diff --git a/src/the/bytecode/club/bytecodeviewer/decompilers/SmaliDisassembler.java b/src/the/bytecode/club/bytecodeviewer/decompilers/SmaliDisassembler.java index 96136837..16c088ce 100644 --- a/src/the/bytecode/club/bytecodeviewer/decompilers/SmaliDisassembler.java +++ b/src/the/bytecode/club/bytecodeviewer/decompilers/SmaliDisassembler.java @@ -1,15 +1,15 @@ package the.bytecode.club.bytecodeviewer.decompilers; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; +import java.io.*; import me.konloch.kontainer.io.DiskReader; +import org.apache.commons.io.FileUtils; import org.objectweb.asm.tree.ClassNode; import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.util.Dex2Jar; +import the.bytecode.club.bytecodeviewer.util.FileContainer; import the.bytecode.club.bytecodeviewer.util.MiscUtils; import the.bytecode.club.bytecodeviewer.util.ZipUtils; @@ -39,14 +39,14 @@ import the.bytecode.club.bytecodeviewer.util.ZipUtils; public class SmaliDisassembler extends Decompiler { - public String decompileClassNode(ClassNode cn, byte[] b) { + public String decompileClassNode(FileContainer container, ClassNode cn, byte[] b) { + String exception = ""; String fileStart = BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp"; - String start = BytecodeViewer.tempDirectory + BytecodeViewer.fs+MiscUtils.getUniqueName(fileStart, ".class"); + String start = MiscUtils.getUniqueName(fileStart, ".class"); final File tempClass = new File(start + ".class"); - final File tempZip = new File(start + ".jar"); final File tempDex = new File(start + ".dex"); final File tempSmali = new File(start + "-smali"); //output directory @@ -60,15 +60,42 @@ public class SmaliDisassembler extends Decompiler { new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); } - ZipUtils.zipFile(tempClass, tempZip); + //ZipUtils.zipFile(tempClass, tempZip); - Dex2Jar.saveAsDex(tempZip, tempDex); + Dex2Jar.saveAsDex(container.file, tempDex, false); - try { - com.googlecode.d2j.smali.SmaliCmd.main(new String[]{"-o", tempSmali.getAbsolutePath(), "-x", tempDex.getAbsolutePath()}); - } catch (Exception e) { - new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + System.out.println("FOR SHOW: " + tempDex.getName().replaceFirst("\\.dex", "-out")); //tempSmali.getAbsolutePath() + + try + { + com.googlecode.d2j.smali.BaksmaliCmd.main(new String[]{tempDex.getAbsolutePath()}); } + catch(Exception e) + { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + e.printStackTrace(); + + exception += "Bytecode Viewer Version: " + BytecodeViewer.VERSION + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString(); + } + + File rename = new File(tempDex.getName().replaceFirst("\\.dex", "-out")); + + try + { + FileUtils.moveDirectory(rename, tempSmali); + } + catch (IOException e) + { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + e.printStackTrace(); + + exception += "Bytecode Viewer Version: " + BytecodeViewer.VERSION + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString(); + } + + System.out.println("FOR SHOW1: " + rename.getAbsolutePath()); + System.out.println("FOR SHOW2: " + tempSmali.getAbsolutePath()); File outputSmali = null; @@ -87,9 +114,19 @@ public class SmaliDisassembler extends Decompiler { try { return DiskReader.loadAsString(outputSmali.getAbsolutePath()); } catch (Exception e) { - new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + e.printStackTrace(); + + exception += "Bytecode Viewer Version: " + BytecodeViewer.VERSION + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString(); } + return "Smali Disassembler error! Send the stacktrace to Konloch at http://the.bytecode.club or konloch@gmail.com" + BytecodeViewer.nl + BytecodeViewer.nl + "Suggested Fix: Click refresh class, if it fails again try another decompiler." + BytecodeViewer.nl + BytecodeViewer.nl + exception; + } + + @Override + public String decompileClassNode(ClassNode cn, byte[] b) + { return null; } diff --git a/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java b/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java index ac9edd01..a601867a 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/ClassViewer.java @@ -13,7 +13,6 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.regex.Matcher; import javax.swing.*; import javax.swing.text.*; @@ -685,7 +684,7 @@ public class ClassViewer extends Viewer panelArea.setCodeFoldingEnabled(true); panelArea.setAntiAliasingEnabled(true); scrollPane = new RTextScrollPane(panelArea); - panelArea.setText(Decompiler.smali.decompileClassNode(cn, b)); + panelArea.setText(Decompiler.smali.decompileClassNode(container, cn, b)); panelArea.setCaretPosition(0); panelArea.setEditable(isPanel1Editable()); smali1 = panelArea; @@ -857,6 +856,51 @@ public class ClassViewer extends Viewer java1 = panelArea; } + + if (pane1 == 10) {// JADX + panelArea = new RSyntaxTextArea(); + panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + panelArea.setCodeFoldingEnabled(true); + panelArea.setAntiAliasingEnabled(true); + scrollPane = new RTextScrollPane(panelArea); + panelArea.setText(Decompiler.jadx.decompileClassNode(cn, b)); + panelArea.setCaretPosition(0); + panelArea.setEditable(isPanel1Editable()); + panelArea.addKeyListener(new KeyListener() + { + public void keyPressed(KeyEvent e) + { + if ((e.getKeyCode() == KeyEvent.VK_F) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) + { + field1.requestFocus(); + } + + BytecodeViewer.checkHotKey(e); + } + + @Override + public void keyReleased(KeyEvent arg0) + { + } + + @Override + public void keyTyped(KeyEvent arg0) + { + } + }); + scrollPane.setColumnHeaderView(new JLabel("JADX Decompiler - Editable: " + panelArea.isEditable())); + panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue())); + + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + panel1.add(scrollPane); + } + }); + + java1 = panelArea; + } } catch (java.lang.IndexOutOfBoundsException | java.lang.NullPointerException e) { //ignore } catch (Exception e) { @@ -1050,7 +1094,7 @@ public class ClassViewer extends Viewer panelArea.setCodeFoldingEnabled(true); panelArea.setAntiAliasingEnabled(true); scrollPane = new RTextScrollPane(panelArea); - panelArea.setText(Decompiler.smali.decompileClassNode(cn, b)); + panelArea.setText(Decompiler.smali.decompileClassNode(container, cn, b)); panelArea.setCaretPosition(0); panelArea.setEditable(isPanel2Editable()); smali2 = panelArea; @@ -1195,6 +1239,51 @@ public class ClassViewer extends Viewer java2 = panelArea; } + + if (pane2 == 10) {// JADX + panelArea = new RSyntaxTextArea(); + panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + panelArea.setCodeFoldingEnabled(true); + panelArea.setAntiAliasingEnabled(true); + scrollPane = new RTextScrollPane(panelArea); + panelArea.setText(Decompiler.jadx.decompileClassNode(cn, b)); + panelArea.setCaretPosition(0); + panelArea.setEditable(isPanel2Editable()); + panelArea.addKeyListener(new KeyListener() + { + public void keyPressed(KeyEvent e) + { + if ((e.getKeyCode() == KeyEvent.VK_F) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) + { + field1.requestFocus(); + } + + BytecodeViewer.checkHotKey(e); + } + + @Override + public void keyReleased(KeyEvent arg0) + { + } + + @Override + public void keyTyped(KeyEvent arg0) + { + } + }); + scrollPane.setColumnHeaderView(new JLabel("JADX Decompiler - Editable: " + panelArea.isEditable())); + panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue())); + + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + panel2.add(scrollPane); + } + }); + + java2 = panelArea; + } } catch (java.lang.IndexOutOfBoundsException | java.lang.NullPointerException e) { //ignore } catch (Exception e) { @@ -1390,7 +1479,7 @@ public class ClassViewer extends Viewer panelArea.setCodeFoldingEnabled(true); panelArea.setAntiAliasingEnabled(true); scrollPane = new RTextScrollPane(panelArea); - panelArea.setText(Decompiler.smali.decompileClassNode(cn, b)); + panelArea.setText(Decompiler.smali.decompileClassNode(container, cn, b)); panelArea.setCaretPosition(0); panelArea.setEditable(isPanel3Editable()); smali3 = panelArea; @@ -1533,6 +1622,51 @@ public class ClassViewer extends Viewer } }); } + + if (pane3 == 10) {// JADX + panelArea = new RSyntaxTextArea(); + panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + panelArea.setCodeFoldingEnabled(true); + panelArea.setAntiAliasingEnabled(true); + scrollPane = new RTextScrollPane(panelArea); + panelArea.setText(Decompiler.jadx.decompileClassNode(cn, b)); + panelArea.setCaretPosition(0); + panelArea.setEditable(isPanel3Editable()); + panelArea.addKeyListener(new KeyListener() + { + public void keyPressed(KeyEvent e) + { + if ((e.getKeyCode() == KeyEvent.VK_F) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) + { + field1.requestFocus(); + } + + BytecodeViewer.checkHotKey(e); + } + + @Override + public void keyReleased(KeyEvent arg0) + { + } + + @Override + public void keyTyped(KeyEvent arg0) + { + } + }); + scrollPane.setColumnHeaderView(new JLabel("JADX Decompiler - Editable: " + panelArea.isEditable())); + panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue())); + + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + panel3.add(scrollPane); + } + }); + + java3 = panelArea; + } } catch (java.lang.IndexOutOfBoundsException | java.lang.NullPointerException e) { //ignore } catch (Exception e) { @@ -1721,6 +1855,8 @@ public class ClassViewer extends Viewer pane1 = 8; else if (BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.panel1JDGUI.getModel())) pane1 = 9; + else if (BytecodeViewer.viewer.panelGroup1.isSelected(BytecodeViewer.viewer.jadxJ1.getModel())) + pane1 = 10; if (BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2None.getModel())) pane2 = 0; @@ -1742,6 +1878,8 @@ public class ClassViewer extends Viewer pane2 = 8; else if (BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.panel2JDGUI.getModel())) pane2 = 9; + else if (BytecodeViewer.viewer.panelGroup2.isSelected(BytecodeViewer.viewer.jadxJ2.getModel())) + pane2 = 10; if (BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3None.getModel())) pane3 = 0; @@ -1763,6 +1901,8 @@ public class ClassViewer extends Viewer pane3 = 8; else if (BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.panel3JDGUI.getModel())) pane3 = 9; + else if (BytecodeViewer.viewer.panelGroup3.isSelected(BytecodeViewer.viewer.jadxJ3.getModel())) + pane3 = 10; } public boolean isPanel1Editable() diff --git a/src/the/bytecode/club/bytecodeviewer/gui/FileNavigationPane.java b/src/the/bytecode/club/bytecodeviewer/gui/FileNavigationPane.java index 73663e90..1af1cead 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/FileNavigationPane.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/FileNavigationPane.java @@ -250,6 +250,7 @@ public class FileNavigationPane extends VisibleComponent implements @Override public void keyPressed(KeyEvent e) { + System.out.println((int)e.getKeyChar()); if (e.getKeyCode() == KeyEvent.VK_ENTER) { if (e.getSource() instanceof MyTree) @@ -258,7 +259,7 @@ public class FileNavigationPane extends VisibleComponent implements openPath(tree.getSelectionPath()); } } - else if((int)e.getKeyChar() != 0 && (int)e.getKeyChar() != 65535 && !e.isControlDown() && !e.isAltDown()) + else if((int)e.getKeyChar() != 0 &&(int)e.getKeyChar() != 8 &&(int)e.getKeyChar() != 127 && (int)e.getKeyChar() != 65535 && !e.isControlDown() && !e.isAltDown()) { quickSearch.grabFocus(); quickSearch.setText("" + e.getKeyChar()); @@ -614,7 +615,7 @@ public class FileNavigationPane extends VisibleComponent implements the.bytecode.club.bytecodeviewer.gui.FileNavigationPane.MyTreeNode node = (the.bytecode.club.bytecodeviewer.gui.FileNavigationPane.MyTreeNode) value; String name = node.toString().toLowerCase(); - if (name.endsWith(".jar")) { + if (name.endsWith(".jar") || name.endsWith(".war")) { setIcon(Resources.jarIcon); } else if (name.endsWith(".zip")) { setIcon(Resources.zipIcon); diff --git a/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java b/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java index a031b5dc..bc1d7fe3 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java @@ -413,6 +413,17 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier public final JRadioButtonMenuItem panel1JDGUI = new JRadioButtonMenuItem("Java"); private final JSeparator separator_35 = new JSeparator(); public final JCheckBoxMenuItem panel1JDGUI_E = new JCheckBoxMenuItem("Editable"); + + private final JMenu jadx1 = new JMenu("JADX"); + public final JRadioButtonMenuItem jadxJ1 = new JRadioButtonMenuItem("Java"); + public final JCheckBoxMenuItem jadxE1 = new JCheckBoxMenuItem("Editable"); + private final JMenu jadx2 = new JMenu("JADX"); + public final JRadioButtonMenuItem jadxJ2 = new JRadioButtonMenuItem("Java"); + public final JCheckBoxMenuItem jadxE2 = new JCheckBoxMenuItem("Editable"); + private final JMenu jadx3 = new JMenu("JADX"); + public final JRadioButtonMenuItem jadxJ3 = new JRadioButtonMenuItem("Java"); + public final JCheckBoxMenuItem jadxE3 = new JCheckBoxMenuItem("Editable"); + private final JMenu mnFontSize = new JMenu("Font Size"); private final JMenu visualSettings = new JMenu("Visual Settings"); public final JSpinner fontSpinner = new JSpinner(); @@ -488,7 +499,14 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier obfuscatorGroup.add(strongObf); obfuscatorGroup.add(lightObf); obfuscatorGroup.setSelected(strongObf.getModel(), true); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + BytecodeViewer.canExit = true; + System.exit(0); + } + }); // procyon /* none */ @@ -512,7 +530,9 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier @Override public void actionPerformed(ActionEvent e) { - JFileChooser fc = new JFileChooser(); + + final JFileChooser fc = new JFileChooser(); + try { File f = new File(BytecodeViewer.lastDirectory); @@ -523,6 +543,10 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier { } + + fc.setDialogTitle("Select File or Folder to open in BCV"); + fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + fc.setAcceptAllFileFilterUsed(true); fc.setFileFilter(new FileFilter() { @Override @@ -535,7 +559,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier if (extension != null) if (extension.equals("jar") || extension.equals("zip") || extension.equals("class") || extension.equals("apk") - || extension.equals("dex")) + || extension.equals("dex") || extension.equals("war") || extension.equals("jsp")) return true; return false; @@ -544,11 +568,10 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier @Override public String getDescription() { - return "APKs, DEX, Class Files or Zip/Jar Archives"; + return "APKs, DEX, Class Files or Zip/Jar/War Archives"; } }); - fc.setFileHidingEnabled(false); - fc.setAcceptAllFileFilterUsed(false); + int returnVal = fc.showOpenDialog(BytecodeViewer.viewer); if (returnVal == JFileChooser.APPROVE_OPTION) @@ -557,8 +580,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier try { BytecodeViewer.viewer.setIcon(true); - BytecodeViewer.openFiles(new File[]{fc - .getSelectedFile()}, true); + BytecodeViewer.openFiles(new File[]{fc.getSelectedFile()}, true); BytecodeViewer.viewer.setIcon(false); } catch (Exception e1) @@ -568,6 +590,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier } } }); + mnNewMenu.add(mntmLoadJar); mnNewMenu.add(separator_40); @@ -1566,6 +1589,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier if (result == 0) { + BytecodeViewer.canExit = true; System.exit(0); } } @@ -1590,6 +1614,22 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier panel1Proc.addActionListener(listener); mnNewMenu_7.add(mnCfr); + + jadx1.add(jadxJ1); + jadx1.add(separator_19); + jadx1.add(jadxE1); + + jadx2.add(jadxJ2); + jadx2.add(separator_19); + jadx2.add(jadxE2); + + jadx3.add(jadxJ3); + jadx3.add(separator_19); + jadx3.add(jadxE3); + + mnNewMenu_7.add(jadx1); + + mnCfr.add(panel1CFR); panel1CFR.addActionListener(listener); @@ -1656,6 +1696,8 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier mnPane.add(menu_2); + mnPane.add(jadx2); + menu_2.add(panel2CFR); menu_2.add(separator_11); @@ -1719,6 +1761,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier menu_7.add(panel3Proc_E); mnPane_1.add(menu_8); + mnPane_1.add(jadx3); menu_8.add(panel3CFR); @@ -1889,6 +1932,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier mnNewMenu_4.add(chckbxmntmNewCheckItem_4); + chckbxmntmNewCheckItem_7.setSelected(true); mnNewMenu_4.add(chckbxmntmNewCheckItem_7); mnNewMenu_4.add(chckbxmntmSimplifyMemberReferences); @@ -2338,6 +2382,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier panelGroup1.add(panel1None); panelGroup1.add(panel1Proc); panelGroup1.add(panel1CFR); + panelGroup1.add(jadxJ1); panelGroup1.add(panel1JDGUI); panelGroup1.add(panel1Fern); panelGroup1.add(panel1Krakatau); @@ -2349,6 +2394,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier panelGroup2.add(panel2None); panelGroup2.add(panel2Proc); panelGroup2.add(panel2CFR); + panelGroup2.add(jadxJ2); panelGroup2.add(panel2JDGUI); panelGroup2.add(panel2Fern); panelGroup2.add(panel2Krakatau); @@ -2360,6 +2406,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier panelGroup3.add(panel3None); panelGroup3.add(panel3Proc); panelGroup3.add(panel3CFR); + panelGroup3.add(jadxJ3); panelGroup3.add(panel3JDGUI); panelGroup3.add(panel3Fern); panelGroup3.add(panel3Krakatau); diff --git a/src/the/bytecode/club/bytecodeviewer/gui/PaneUpdaterThread.java b/src/the/bytecode/club/bytecodeviewer/gui/PaneUpdaterThread.java index a5461fb0..2f3bc9f2 100644 --- a/src/the/bytecode/club/bytecodeviewer/gui/PaneUpdaterThread.java +++ b/src/the/bytecode/club/bytecodeviewer/gui/PaneUpdaterThread.java @@ -29,8 +29,7 @@ import javax.swing.event.CaretListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import java.awt.event.*; import java.util.regex.Matcher; import static the.bytecode.club.bytecodeviewer.gui.TabbedPane.BLANK; @@ -57,6 +56,38 @@ public abstract class PaneUpdaterThread extends Thread public void run() { doShit(); synchronizePane(); + //attachCtrlMouseWheelZoom(scrollPane, panelArea); //freezes the UI for some reason, probably cause BCV is doing dumb shit with the swing thread + } + + public void attachCtrlMouseWheelZoom(RTextScrollPane scrollPane, RSyntaxTextArea panelArea) + { + if(scrollPane == null) + return; + + scrollPane.addMouseWheelListener(new MouseWheelListener() + { + @Override + public void mouseWheelMoved(MouseWheelEvent e) + { + if(panelArea == null || panelArea.getText().isEmpty()) + return; + + if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) + { + Font font = panelArea.getFont(); + int size = font.getSize(); + if(e.getWheelRotation() > 0) + { //Up + panelArea.setFont(new Font(font.getName(), font.getStyle(), --size >= 2 ? --size : 2)); + } + else + { //Down + panelArea.setFont(new Font(font.getName(), font.getStyle(), ++size)); + } + } + e.consume(); + } + }); } public final CaretListener caretListener = new CaretListener() diff --git a/src/the/bytecode/club/bytecodeviewer/util/Dex2Jar.java b/src/the/bytecode/club/bytecodeviewer/util/Dex2Jar.java index a0cac83c..8b2af821 100644 --- a/src/the/bytecode/club/bytecodeviewer/util/Dex2Jar.java +++ b/src/the/bytecode/club/bytecodeviewer/util/Dex2Jar.java @@ -1,5 +1,7 @@ package the.bytecode.club.bytecodeviewer.util; +import the.bytecode.club.bytecodeviewer.BytecodeViewer; + import java.io.File; /*************************************************************************** @@ -55,14 +57,35 @@ public class Dex2Jar { * @param output the output .dex file */ public static synchronized void saveAsDex(File input, File output) { + saveAsDex(input, output, true); + } + + public static synchronized void saveAsDex(File input, File output, boolean delete) { try { - com.googlecode.dex2jar.tools.Dex2jarCmd.main(new String[]{input.getAbsolutePath()}); - String realOutput = input.getName().replaceAll("\\.jar", "-jar2dex.dex"); - File realOutputF = new File(realOutput); - realOutputF.renameTo(output); - File realOutputF2 = new File(realOutput); - while (realOutputF2.exists()) - realOutputF2.delete(); + com.googlecode.dex2jar.tools.Jar2Dex.main(new String[]{input.getAbsolutePath()}); + File currentDexLocation = new File("./"+input.getName()); + + if(currentDexLocation.getAbsolutePath().toLowerCase().endsWith(".jar")) + { + currentDexLocation = new File(currentDexLocation.getAbsolutePath().replaceFirst("\\.jar", "-jar2dex.dex")); + } + else if(currentDexLocation.getAbsolutePath().toLowerCase().endsWith(".apk")) + { + currentDexLocation = new File(currentDexLocation.getAbsolutePath().replaceFirst("\\.apk", "-jar2dex.dex")); + } + else if(currentDexLocation.getAbsolutePath().toLowerCase().endsWith(".dex")) + { + currentDexLocation = new File(currentDexLocation.getAbsolutePath().replaceFirst("\\.dex", "-jar2dex.dex")); + } + else if(currentDexLocation.getAbsolutePath().toLowerCase().endsWith(".zip")) + { + currentDexLocation = new File(currentDexLocation.getAbsolutePath().replaceFirst("\\.zip", "-jar2dex.dex")); + } + + currentDexLocation.renameTo(output); + + if(delete) + input.delete(); } catch (Exception e) { new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); } diff --git a/src/the/bytecode/club/bytecodeviewer/util/FileContainer.java b/src/the/bytecode/club/bytecodeviewer/util/FileContainer.java index b7f76a4f..023228cf 100644 --- a/src/the/bytecode/club/bytecodeviewer/util/FileContainer.java +++ b/src/the/bytecode/club/bytecodeviewer/util/FileContainer.java @@ -45,8 +45,8 @@ public class FileContainer { public File file; public String name; - public HashMap files = new HashMap(); - public ArrayList classes = new ArrayList(); + public HashMap files = new HashMap<>(); + public ArrayList classes = new ArrayList<>(); public ClassNode getClassNode(String name) { for (ClassNode c : classes) diff --git a/src/the/bytecode/club/bytecodeviewer/util/JarUtils.java b/src/the/bytecode/club/bytecodeviewer/util/JarUtils.java index 9918d676..da44f80f 100644 --- a/src/the/bytecode/club/bytecodeviewer/util/JarUtils.java +++ b/src/the/bytecode/club/bytecodeviewer/util/JarUtils.java @@ -1,7 +1,6 @@ package the.bytecode.club.bytecodeviewer.util; import java.io.*; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -17,7 +16,6 @@ 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.compress.utils.IOUtils; import org.apache.commons.io.FilenameUtils; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; @@ -59,7 +57,7 @@ public class JarUtils { */ public static void put(final File jarFile) throws IOException { FileContainer container = new FileContainer(jarFile); - HashMap files = new HashMap(); + HashMap files = new HashMap<>(); ZipInputStream jis = new ZipInputStream(new FileInputStream(jarFile)); ZipEntry entry; @@ -86,7 +84,7 @@ public class JarUtils { } } - } catch (ZipException e) { + } catch (java.io.EOFException | ZipException e) { //ignore cause apache unzip } catch (Exception e) { new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e); @@ -99,12 +97,12 @@ public class JarUtils { BytecodeViewer.files.add(container); } - public static void put2(final File jarFile) throws IOException { - //TODO try zip libraries till one works, worst case import Sun's jarsigner code from JDK 7 re-sign the jar to rebuilt the CRC, should also rebuild the archive byte offsets + public static void put2(final File jarFile) throws IOException + { + //if this ever fails, worst case import Sun's jarsigner code from JDK 7 re-sign the jar to rebuild the CRC, should also rebuild the archive byte offsets FileContainer container = new FileContainer(jarFile); - HashMap files = new HashMap(); - + HashMap files = new HashMap<>(); Path path = jarFile.toPath(); @@ -114,29 +112,42 @@ public class JarUtils { try (ZipFile zipFile = new ZipFile(jarFile)) { Enumeration entries = zipFile.getEntries(); - while (entries.hasMoreElements()) { + while (entries.hasMoreElements()) + { ZipArchiveEntry entry = entries.nextElement(); Path entryPath = destFolderPath.resolve(entry.getName()); String name = entry.getName(); - if (entry.isDirectory()) { + if (entry.isDirectory()) + { //directory - } else { + } + else + { try (InputStream in = zipFile.getInputStream(entry)) { - final byte[] bytes = getBytes(in); - if (!name.endsWith(".class")) { + + if(!name.endsWith(".class")) + { files.put(name, bytes); - } else { + } + else + { String cafebabe = String.format("%02X", bytes[0]) + String.format("%02X", bytes[1]) + String.format("%02X", bytes[2]) + String.format("%02X", bytes[3]); - if (cafebabe.toLowerCase().equals("cafebabe")) { - try { + if (cafebabe.toLowerCase().equals("cafebabe")) + { + try + { final ClassNode cn = getNode(bytes); container.classes.add(cn); - } catch (Exception e) { + } + catch (Exception e) + { e.printStackTrace(); } - } else { + } + else + { files.put(name, bytes); } } @@ -193,7 +204,7 @@ public class JarUtils { if (!zipFile.exists()) return null; //just ignore - HashMap files = new HashMap(); + HashMap files = new HashMap<>(); ZipInputStream jis = new ZipInputStream(new FileInputStream(zipFile)); ZipEntry entry;