This commit is contained in:
Konloch 2015-07-22 03:17:01 -06:00
parent 89bad45283
commit f7d0233df2
13 changed files with 646 additions and 252 deletions

View file

@ -1,5 +1,16 @@
<html>Bytecode Viewer (BCV) was designed to be extremely user and beginner friendly, because of this almost everything is accessible through an interface, settings, tools, etc. This means if you give BCV a try you should get the gist of it can do, however for those who don't want to run BCV until they're convinced they should use it, below is a complete list of features BCV has, and what they do.
<h2>Command Line Interface (CLI):</h2>
<ul>
<li> -help Displays the help menu</li>
<li> -list Displays the available decompilers</li>
<li> -decompiler [decompiler] Selects the decompiler, procyon by default</li>
<li> -i [input file] Selects the input file (Jar, Class, APK, ZIP, DEX all work automatically)</li>
<li> -o [output file] Selects the output file (Java or Java-Bytecode)</li>
<li> -t [target classname] Must either be the fully qualified classname or "all" to decompile all as zip</li>
<li> -nowait Doesn't wait for the user to read the CLI messages</li>
</ul>
<h2>File:</h2>
<ul>
<li>Add (Ctrl + O) - If you add a jar/zip BCV will unzip it, if you add an APK or DEX file, BCV will run dex2jar then run the jar input process.</li>

View file

@ -16,8 +16,8 @@ import me.konloch.kontainer.io.HTTPRequest;
import the.bytecode.club.bootloader.resource.EmptyExternalResource;
import the.bytecode.club.bootloader.resource.ExternalResource;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.CommandLineInput;
import the.bytecode.club.bytecodeviewer.ZipUtils;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
/**
* @author Konloch
@ -26,18 +26,28 @@ import the.bytecode.club.bytecodeviewer.ZipUtils;
*/
public class Boot {
private static InitialBootScreen screen;
public static boolean globalstop = false;
public static boolean completedboot = false;
public static boolean downloading = false;
private static InitialBootScreen screen;
private static List<String> libsList = new ArrayList<String>();
private static List<String> libsFileList = new ArrayList<String>();
private static List<String> urlList = new ArrayList<String>();
static {
try {
screen = new InitialBootScreen();
} catch(Exception e) {
new ExceptionUI(e);
}
}
public static void boot(String[] args, int CLI) throws Exception {
if(CLI == CommandLineInput.STOP)
return;
public static void boot(String[] args, boolean CLI) throws Exception {
bootstrap();
ILoader<?> loader = findLoader();
screen = new InitialBootScreen();
if(CLI == CommandLineInput.OPEN_FILE)
if(!CLI)
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
@ -53,37 +63,32 @@ public class Boot {
screen.setVisible(false);
}
});
/*Class<?> klass = loader.loadClass("the.bytecode.club.bytecodeviewer.BytecodeViewer");
klass.getDeclaredMethod("BOOT", new Class<?>[] { String[].class }).invoke(null, new Object[] { args });*/
if(CLI == CommandLineInput.OPEN_FILE)
BytecodeViewer.BOOT(args, false);
else {
BytecodeViewer.BOOT(args, true);
CommandLineInput.executeCommandLine(args);
}
}
public static void hide() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
screen.setVisible(false);
}
});
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private static void create(ILoader<?> loader, boolean clean) throws Exception {
setState("Bytecode Viewer Boot Screen - Checking Libraries...");
final File libsDirectory = libsDir();
List<String> urlList = new ArrayList<String>();
HTTPRequest req = new HTTPRequest(new URL("https://github.com/Konloch/bytecode-viewer/tree/master/libs"));
for (String s : req.read())
if (s.contains("href=\"/Konloch/bytecode-viewer/blob/master/libs/")) {
urlList.add("https://github.com" + s.split("<a href=")[1].split("\"")[1]);
}
populateUrlList();
if(globalstop) {
while(true) {
Thread.sleep(100);//just keep this thread halted.
}
}
if (urlList.isEmpty()) {
JOptionPane
.showMessageDialog(
null,
"Bytecode Viewer ran into an issue, for some reason github is not returning what we're expecting. Please try rebooting, if this issue persists please contact @Konloch.",
"Error", JOptionPane.ERROR_MESSAGE);
JOptionPane.showMessageDialog(null, "Bytecode Viewer ran into an issue, for some reason github is not returning what we're expecting. Please try rebooting, if this issue persists please contact @Konloch.", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
@ -92,13 +97,8 @@ public class Boot {
if (!libsDirectory.exists())
libsDirectory.mkdir();
List<String> libsList = new ArrayList<String>();
List<String> libsFileList = new ArrayList<String>();
for (File f : libsDirectory.listFiles()) {
libsList.add(f.getName());
libsFileList.add(f.getAbsolutePath());
}
populateLibsDirectory();
screen.getProgressBar().setMaximum(urlList.size() * 2);
@ -106,16 +106,20 @@ public class Boot {
for (String s : urlList) {
String fileName = s.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length(), s.length());
if (!libsList.contains(fileName)) {
setState("Bytecode Viewer Boot Screen - Downloading " + fileName);
System.out.println("Downloading " + fileName);
boolean passed = false;
while (!passed) {
File file = new File(libsDirectory, fileName);
boolean passed = false;
while (!passed) {
if (!libsList.contains(fileName)) {
downloading = true;
setState("Bytecode Viewer Boot Screen - Downloading " + fileName + "...");
System.out.println("Downloading " + fileName);
InputStream is = null;
FileOutputStream fos = null;
try {
is = new URL("https://github.com/Konloch/bytecode-viewer/raw/master/libs/" + fileName).openConnection().getInputStream();
fos = new FileOutputStream(new File(libsDirectory, fileName));
fos = new FileOutputStream(file);
System.out.println("Downloading from " + s);
byte[] buffer = new byte[8192];
int len;
@ -133,7 +137,6 @@ public class Boot {
} else
flag = false;
}
libsFileList.add(new File(libsDirectory, fileName).getAbsolutePath());
} finally {
try {
if (is != null) {
@ -148,7 +151,40 @@ public class Boot {
}
}
}
System.out.println("Download finished!");
try {
setState("Bytecode Viewer Boot Screen - Verifying " + fileName + "...");
System.out.println("Verifying " + fileName + "...");
File f = new File(BytecodeViewer.tempDirectory, "temp");
ZipUtils.zipFile(file, f);
f.delete();
libsFileList.add(file.getAbsolutePath());
System.out.println("Download finished!");
passed = true;
} catch(Exception e) {
e.printStackTrace();
System.out.println("Jar or Zip" + file.getAbsolutePath() + " is corrupt, redownloading.");
file.delete();
}
} else if(BytecodeViewer.verify) { //verify its not corrupt each boot (adds 3 seconds boot time)
try {
setState("Bytecode Viewer Boot Screen - Verifying " + fileName + "...");
System.out.println("Verifying " + fileName + "...");
File f = new File(BytecodeViewer.tempDirectory, "temp");
ZipUtils.zipFile(file, f);
f.delete();
passed = true;
} catch(Exception e) {
e.printStackTrace();
System.out.println("Jar or Zip" + file.getAbsolutePath() + " is corrupt, redownloading.");
libsFileList.remove(file.getAbsolutePath());
file.delete();
}
} else {
passed = true;
}
}
@ -200,6 +236,178 @@ public class Boot {
}
}
checkKrakatau();
completedCheck++;
screen.getProgressBar().setValue(completedCheck);
checkEnjarify();
completedCheck++;
screen.getProgressBar().setValue(completedCheck);
setState("Bytecode Viewer Boot Screen - Booting!");
completedboot = true;
}
public static File libsDir() {
File dir = new File(System.getProperty("user.home"), ".Bytecode-Viewer");
while (!dir.exists())
dir.mkdirs();
return new File(dir, "libs");
}
public static void setState(String s) {
screen.setTitle(s);
}
public static ILoader<?> findLoader() {
// TODO: Find from providers
// return new LibraryClassLoader();
// TODO: Catch
return AbstractLoaderFactory.find().spawnLoader();
}
private static void bootstrap() {
AbstractLoaderFactory.register(new LoaderFactory<Object>() {
@Override
public ILoader<Object> spawnLoader() {
return new ClassPathLoader();
}
});
}
public static void populateUrlList() throws Exception {
HTTPRequest req = new HTTPRequest(new URL("https://github.com/Konloch/bytecode-viewer/tree/master/libs"));
req.setTimeout(30000);
for (String s : req.read())
if (s.contains("href=\"/Konloch/bytecode-viewer/blob/master/libs/")) {
urlList.add("https://github.com" + s.split("<a href=")[1].split("\"")[1]);
}
}
public static void populateLibsDirectory() {
if(libsDir() != null)
for (File f : libsDir().listFiles()) {
libsList.add(f.getName());
libsFileList.add(f.getAbsolutePath());
}
}
public static void downloadZipsOnly() throws Exception{
for (String s : urlList) {
String fileName = s.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length(), s.length());
File file = new File(libsDir(), fileName);
boolean passed = false;
while (!passed) {
if (!libsList.contains(fileName) && fileName.endsWith(".zip")) {
downloading = true;
setState("Bytecode Viewer Boot Screen - Downloading " + fileName + "...");
System.out.println("Downloading " + fileName);
InputStream is = null;
FileOutputStream fos = null;
try {
is = new URL("https://github.com/Konloch/bytecode-viewer/raw/master/libs/" + fileName).openConnection().getInputStream();
fos = new FileOutputStream(file);
System.out.println("Downloading from " + s);
byte[] buffer = new byte[8192];
int len;
int downloaded = 0;
boolean flag = false;
while ((len = is.read(buffer)) > 0) {
fos.write(buffer, 0, len);
fos.flush();
downloaded += 8192;
int mbs = downloaded / 1048576;
if (mbs % 5 == 0 && mbs != 0) {
if (!flag)
System.out.println("Downloaded " + mbs + "MBs so far");
flag = true;
} else
flag = false;
}
} catch(Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
} finally {
if (fos != null) {
fos.flush();
}
if (fos != null) {
fos.close();
}
}
}
try {
setState("Bytecode Viewer Boot Screen - Verifying " + fileName + "...");
System.out.println("Verifying " + fileName + "...");
File f = new File(BytecodeViewer.tempDirectory, "temp");
ZipUtils.zipFile(file, f);
f.delete();
libsFileList.add(file.getAbsolutePath());
System.out.println("Download finished!");
passed = true;
} catch(Exception e) {
e.printStackTrace();
System.out.println("Jar or Zip" + file.getAbsolutePath() + " is corrupt, redownloading.");
file.delete();
}
} else
passed = true;
}
}
}
public static void checkEnjarify() {
setState("Bytecode Viewer Boot Screen - Checking Enjarify...");
System.out.println("Checking enjarify");
File enjarifyZip = null;
for(File f : new File(BytecodeViewer.libsDirectory).listFiles()) {
if(f.getName().toLowerCase().startsWith("enjarify-")) {
BytecodeViewer.enjarifyVersion = f.getName().split("-")[1].split("\\.")[0];
enjarifyZip = f;
}
}
for(File f : new File(BytecodeViewer.getBCVDirectory()).listFiles()) {
if(f.getName().toLowerCase().startsWith("enjarify_") && !f.getName().split("_")[1].split("\\.")[0].equals(BytecodeViewer.enjarifyVersion)) {
setState("Bytecode Viewer Boot Screen - Removing Outdated " + f.getName() + "...");
System.out.println("Removing oudated " + f.getName());
try {
FileUtils.deleteDirectory(f);
} catch (Exception e) {
e.printStackTrace();
}
}
}
BytecodeViewer.enjarifyWorkingDirectory = BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion + BytecodeViewer.fs + "enjarify-master";
File enjarifyDirectory = new File(BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion);
if(!enjarifyDirectory.exists()) {
try {
setState("Bytecode Viewer Boot Screen - Updating to "+enjarifyDirectory.getName()+"...");
ZipUtils.unzipFilesToPath(enjarifyZip.getAbsolutePath(), enjarifyDirectory.getAbsolutePath());
System.out.println("Updated to enjarify v" + BytecodeViewer.enjarifyVersion);
} catch(Exception e) {
BytecodeViewer.showMessage("ERROR: There was an issue unzipping enjarify (possibly corrupt). Restart BCV."+BytecodeViewer.nl+
"If the error persists contact @Konloch.");
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
enjarifyZip.delete();
}
}
}
public static void checkKrakatau() {
setState("Bytecode Viewer Boot Screen - Checking Krakatau...");
System.out.println("Checking krakatau");
@ -237,80 +445,5 @@ public class Boot {
krakatauZip.delete();
}
}
completedCheck++;
screen.getProgressBar().setValue(completedCheck);
setState("Bytecode Viewer Boot Screen - Checking Enjarify...");
System.out.println("Checking enjarify");
File enjarifyZip = null;
for(File f : new File(BytecodeViewer.libsDirectory).listFiles()) {
if(f.getName().toLowerCase().startsWith("enjarify-")) {
BytecodeViewer.enjarifyVersion = f.getName().split("-")[1].split("\\.")[0];
enjarifyZip = f;
}
}
for(File f : new File(BytecodeViewer.getBCVDirectory()).listFiles()) {
if(f.getName().toLowerCase().startsWith("enjarify_") && !f.getName().split("_")[1].split("\\.")[0].equals(BytecodeViewer.enjarifyVersion)) {
setState("Bytecode Viewer Boot Screen - Removing Outdated " + f.getName() + "...");
System.out.println("Removing oudated " + f.getName());
try {
FileUtils.deleteDirectory(f);
} catch (Exception e) {
e.printStackTrace();
}
}
}
BytecodeViewer.enjarifyWorkingDirectory = BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion + BytecodeViewer.fs + "enjarify-master";
File enjarifyDirectory = new File(BytecodeViewer.getBCVDirectory() + BytecodeViewer.fs + "enjarify_" + BytecodeViewer.enjarifyVersion);
if(!enjarifyDirectory.exists()) {
try {
setState("Bytecode Viewer Boot Screen - Updating to "+enjarifyDirectory.getName()+"...");
ZipUtils.unzipFilesToPath(enjarifyZip.getAbsolutePath(), enjarifyDirectory.getAbsolutePath());
System.out.println("Updated to enjarify v" + BytecodeViewer.enjarifyVersion);
} catch(Exception e) {
BytecodeViewer.showMessage("ERROR: There was an issue unzipping enjarify (possibly corrupt). Restart BCV."+BytecodeViewer.nl+
"If the error persists contact @Konloch.");
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
enjarifyZip.delete();
}
}
completedCheck++;
screen.getProgressBar().setValue(completedCheck);
setState("Bytecode Viewer Boot Screen - Booting!");
}
private static File libsDir() {
File dir = new File(System.getProperty("user.home"), ".Bytecode-Viewer");
while (!dir.exists())
dir.mkdirs();
return new File(dir, "libs");
}
private static void setState(String s) {
screen.setTitle(s);
}
private static ILoader<?> findLoader() {
// TODO: Find from providers
// return new LibraryClassLoader();
// TODO: Catch
return AbstractLoaderFactory.find().spawnLoader();
}
private static void bootstrap() {
AbstractLoaderFactory.register(new LoaderFactory<Object>() {
@Override
public ILoader<Object> spawnLoader() {
return new ClassPathLoader();
}
});
}
}

View file

@ -15,7 +15,7 @@ import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.List;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
@ -32,6 +32,9 @@ import org.apache.commons.io.FileUtils;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bootloader.Boot;
import the.bytecode.club.bootloader.ILoader;
import the.bytecode.club.bootloader.resource.EmptyExternalResource;
import the.bytecode.club.bootloader.resource.ExternalResource;
import the.bytecode.club.bytecodeviewer.api.ClassNodeLoader;
import the.bytecode.club.bytecodeviewer.gui.ClassViewer;
import the.bytecode.club.bytecodeviewer.gui.FileNavigationPane;
@ -96,6 +99,11 @@ import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
* 07/20/2015 - Bibl sexified the boot loading time.
* 07/20/2015 - Decode APK Resources is selected by default.
* 07/20/2015 - Made the security manager slightly safer, can still be targeted but not as obvious now.
* 07/20/2015 - Added CLI to the boot page.
* 07/21/2015 - Added support for offline mode incase you cannot connect to github for some reason. (kicks in after 7 seconds)
* 07/21/2015 - Added fatjar option back, incase anyone wants a 100% portable version.
* 07/21/2015 - Made it so it now shows the decompiler it's using - http://i.imgur.com/yMEzXwv.png.
* 07/21/2015 - Rewrote the file system, it now shows the path of the jar it's got loaded.
*
* @author Konloch
*
@ -106,7 +114,10 @@ public class BytecodeViewer {
/*per version*/
public static String version = "2.9.8";
public static boolean previewCopy = true;
public static boolean fatJar = false;
/*the rest*/
public static boolean verify = false; //eventually may be a setting
public static String[] args;
public static MainViewerGUI viewer = null;
public static ClassNodeLoader loader = new ClassNodeLoader(); //might be insecure due to assholes targeting BCV, however that's highly unlikely.
public static SecurityMan sm = new SecurityMan(); //might be insecure due to assholes targeting BCV, however that's highly unlikely.
@ -114,8 +125,7 @@ public class BytecodeViewer {
public static String python3 = "";
public static String rt = "";
public static String library = "";
public static HashMap<String, ClassNode> loadedClasses = new HashMap<String, ClassNode>();
public static HashMap<String, byte[]> loadedResources = new HashMap<String, byte[]>();
public static ArrayList<FileContainer> files = new ArrayList<FileContainer>(); //all of BCV's loaded files/classes/etc
private static int maxRecentFiles = 25;
public static String fs = System.getProperty("file.separator");
public static String nl = System.getProperty("line.separator");
@ -142,7 +152,7 @@ public class BytecodeViewer {
/**
* The version checker thread
*/
public static Thread versionChecker = new Thread() {
private static Thread versionChecker = new Thread() {
@Override
public void run() {
try {
@ -310,7 +320,10 @@ public class BytecodeViewer {
}
};
public static Thread PingBack = new Thread() {
/**
* Pings back to bytecodeviewer.com to be added into the total running statistics
*/
private static Thread PingBack = new Thread() {
@Override
public void run() {
try {
@ -321,6 +334,98 @@ public class BytecodeViewer {
}
};
/**
* Downloads & installs the krakatau & enjarify zips
*/
private static Thread InstallFatJar = new Thread() {
@Override
public void run() {
try {
Boot.populateUrlList();
Boot.populateLibsDirectory();
Boot.downloadZipsOnly();
Boot.checkKrakatau();
Boot.checkEnjarify();
} catch(Exception e) {
e.printStackTrace();
}
}
};
/**
* Used to check incase booting failed for some reason, this kicks in as a fail safe
*/
private static Thread bootCheck = new Thread() {
boolean finished = false;
@SuppressWarnings({ "rawtypes", "unchecked" })
public void run() {
long start = System.currentTimeMillis();
while(!finished) {
if(System.currentTimeMillis() - start >= 7000) { //7 second failsafe
if(!Boot.completedboot && !Boot.downloading) {
if(Boot.libsDir() == null || Boot.libsDir().listFiles() == null || Boot.libsDir().listFiles().length <= 0) {
BytecodeViewer.showMessage(
"Github is loading extremely slow, BCV needs to download libraries from github in order"+nl+
"to work, please try ajusting your network settings or manually downloading these libraries"+nl+
"if this error persists.");
finished = true;
return;
}
Boot.setState("Bytecode Viewer Boot Screen (OFFLINE MODE) - Unable to connect to github, force booting...");
System.out.println("Unable to connect to github, force booting...");
List<String> libsList = new ArrayList<String>();
List<String> libsFileList = new ArrayList<String>();
if(Boot.libsDir() != null)
for (File f : Boot.libsDir().listFiles()) {
libsList.add(f.getName());
libsFileList.add(f.getAbsolutePath());
}
ILoader<?> loader = Boot.findLoader();
for (String s : libsFileList) {
if (s.endsWith(".jar")) {
File f = new File(s);
if (f.exists()) {
Boot.setState("Bytecode Viewer Boot Screen (OFFLINE MODE) - Force Loading Library " + f.getName());
System.out.println("Force loading library " + f.getName());
try {
ExternalResource res = new EmptyExternalResource<Object>(f.toURI().toURL());
loader.bind(res);
System.out.println("Succesfully loaded " + f.getName());
} catch (Exception e) {
e.printStackTrace();
f.delete();
JOptionPane.showMessageDialog(null, "Error, Library " + f.getName() + " is corrupt, please restart to redownload it.",
"Error", JOptionPane.ERROR_MESSAGE);
}
}
}
}
Boot.globalstop = false;
Boot.hide();
if(CommandLineInput.parseCommandLine(args) == CommandLineInput.OPEN_FILE)
BytecodeViewer.BOOT(false);
else {
BytecodeViewer.BOOT(true);
CommandLineInput.executeCommandLine(args);
}
}
finished = true;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}
};
public static void pingback() {
JOptionPane pane = new JOptionPane(
"Would you like to 'pingback' to https://bytecodeviewer.com to be counted in the global users for BCV?");
@ -366,6 +471,7 @@ public class BytecodeViewer {
* @param args files you want to open
*/
public static void main(String[] args) {
BytecodeViewer.args = args;
System.out.println("https://the.bytecode.club - Created by @Konloch - Bytecode Viewer " + version);
System.setSecurityManager(sm);
try {
@ -377,15 +483,37 @@ public class BytecodeViewer {
viewer = new MainViewerGUI();
Settings.loadGUI();
int CLI = CommandLineInput.parseCommandLine(args);
Boot.boot(args, CommandLineInput.parseCommandLine(args));
//new BootScreen().DO_FIRST_BOOT(args, CommandLineInput.parseCommandLine(args));
if(CLI == CommandLineInput.STOP)
return;
if(!fatJar) {
bootCheck.start();
if(CLI == CommandLineInput.OPEN_FILE)
Boot.boot(args, false);
else
Boot.boot(args, true);
} else
InstallFatJar.start();
if(CLI == CommandLineInput.OPEN_FILE)
BytecodeViewer.BOOT(false);
else {
BytecodeViewer.BOOT(true);
CommandLineInput.executeCommandLine(args);
}
} catch (Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
}
public static void BOOT(String[] args, boolean cli) {
/**
* Boot after all of the libraries have been loaded
* @param cli is it running CLI mode or not
*/
public static void BOOT(boolean cli) {
cleanup();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
@ -409,7 +537,7 @@ public class BytecodeViewer {
versionChecker.start();
if(!cli)
viewer.setVisible(true);
viewer.setVisible(true);
System.out.println("Start up took " + ((System.currentTimeMillis() - start) / 1000) + " seconds");
@ -442,8 +570,11 @@ public class BytecodeViewer {
* @return the ClassNode instance
*/
public static ClassNode getClassNode(String name) {
if (loadedClasses.containsKey(name))
return loadedClasses.get(name);
for(FileContainer container : files)
for(ClassNode c : container.classes)
if(c.name.equals(name))
return c;
return null;
}
@ -453,8 +584,12 @@ public class BytecodeViewer {
* @return the file contents as a byte[]
*/
public static byte[] getFileContents(String name) {
if (loadedResources.containsKey(name))
return loadedResources.get(name);
for(FileContainer container : files) {
HashMap<String, byte[]> files = container.files;
if(files.containsKey(name))
return files.get(name);
}
return null;
}
@ -464,8 +599,10 @@ public class BytecodeViewer {
* @param newNode the new instance
*/
public static void updateNode(ClassNode oldNode, ClassNode newNode) {
BytecodeViewer.loadedClasses.remove(oldNode.name);
BytecodeViewer.loadedClasses.put(oldNode.name, newNode);
for(FileContainer container : files) {
if(container.classes.remove(oldNode))
container.classes.add(newNode);
}
}
/**
@ -474,12 +611,11 @@ public class BytecodeViewer {
*/
public static ArrayList<ClassNode> getLoadedClasses() {
ArrayList<ClassNode> a = new ArrayList<ClassNode>();
if (loadedClasses != null)
for (Entry<String, ClassNode> entry : loadedClasses.entrySet()) {
Object value = entry.getValue();
ClassNode cln = (ClassNode) value;
a.add(cln);
}
for(FileContainer container : files)
for(ClassNode c : container.classes)
a.add(c);
return a;
}
@ -604,7 +740,7 @@ public class BytecodeViewer {
} else {
if (fn.endsWith(".jar") || fn.endsWith(".zip")) {
try {
JarUtils.put(f, BytecodeViewer.loadedClasses);
JarUtils.put(f);
} catch (final Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
update = false;
@ -619,7 +755,13 @@ public class BytecodeViewer {
+ String.format("%02X", bytes[3]);
if(cafebabe.toLowerCase().equals("cafebabe")) {
final ClassNode cn = JarUtils.getNode(bytes);
BytecodeViewer.loadedClasses.put(cn.name, cn);
FileContainer container = new FileContainer();
container.name = fn;
container.classes.add(cn);
BytecodeViewer.files.add(container);
} else {
showMessage(fn+": Header does not start with CAFEBABE, ignoring.");
update = false;
@ -630,13 +772,17 @@ public class BytecodeViewer {
}
} else if(fn.endsWith(".apk")) {
try {
BytecodeViewer.viewer.setIcon(true);
FileContainer container = new FileContainer();
container.name = fn;
if(viewer.decodeAPKResources.isSelected()) {
File decodedResources = new File(tempDirectory + fs + MiscUtils.randomString(32) + ".apk");
APKTool.decodeResources(f, decodedResources);
JarUtils.loadResources(decodedResources);
container.files = JarUtils.loadResources(decodedResources);
}
JarUtils.loadResources(f);
container.files.putAll(JarUtils.loadResources(f));
String name = getRandomizedName()+".jar";
File output = new File(tempDirectory + fs + name);
@ -645,15 +791,21 @@ public class BytecodeViewer {
Dex2Jar.dex2Jar(f, output);
else if(BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
Enjarify.apk2Jar(f, output);
container.classes = JarUtils.loadClasses(output);
BytecodeViewer.viewer.setIcon(false);
openFiles(new File[]{output}, false);
BytecodeViewer.files.add(container);
} catch (final Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
return;
} else if(fn.endsWith(".dex")) {
try {
BytecodeViewer.viewer.setIcon(true);
FileContainer container = new FileContainer();
container.name = fn;
String name = getRandomizedName()+".jar";
File output = new File(tempDirectory + fs + name);
@ -661,16 +813,27 @@ public class BytecodeViewer {
Dex2Jar.dex2Jar(f, output);
else if(BytecodeViewer.viewer.apkConversionGroup.isSelected(BytecodeViewer.viewer.apkConversionEnjarify.getModel()))
Enjarify.apk2Jar(f, output);
container.classes = JarUtils.loadClasses(output);
BytecodeViewer.viewer.setIcon(false);
openFiles(new File[]{output}, false);
BytecodeViewer.files.add(container);
} catch (final Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
return;
} else {
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
byte[] bytes = JarUtils.getBytes(new FileInputStream(f));
BytecodeViewer.loadedResources.put(f.getName(), bytes);
files.put(f.getName(), bytes);
FileContainer container = new FileContainer();
container.name = fn;
container.files = files;
BytecodeViewer.files.add(container);
}
}
}
@ -721,8 +884,7 @@ public class BytecodeViewer {
*/
public static void resetWorkSpace(boolean ask) {
if(!ask) {
loadedResources.clear();
loadedClasses.clear();
files.clear();
MainViewerGUI.getComponent(FileNavigationPane.class).resetWorkspace();
MainViewerGUI.getComponent(WorkPane.class).resetWorkspace();
MainViewerGUI.getComponent(SearchingPane.class).resetWorkspace();
@ -742,8 +904,7 @@ public class BytecodeViewer {
result = k;
if (result == 0) {
loadedResources.clear();
loadedClasses.clear();
files.clear();
MainViewerGUI.getComponent(FileNavigationPane.class).resetWorkspace();
MainViewerGUI.getComponent(WorkPane.class).resetWorkspace();
MainViewerGUI.getComponent(SearchingPane.class).resetWorkspace();
@ -876,19 +1037,6 @@ public class BytecodeViewer {
}
return name;
}
/**
* Replaces an old node with a new instance
* @param oldNode the old instance
* @param newNode the new instance
*/
public static void relocate(String name, ClassNode node) {
if (BytecodeViewer.loadedClasses.containsKey(name))
BytecodeViewer.loadedClasses.remove(name);
BytecodeViewer.loadedClasses.put(node.name, node);
}
/**
* Returns the BCV directory

View file

@ -0,0 +1,22 @@
package the.bytecode.club.bytecodeviewer;
import java.util.ArrayList;
import java.util.HashMap;
import org.objectweb.asm.tree.ClassNode;
/**
* Represents a file container
*
* @author Konloch
*
*/
public class FileContainer {
public String name;
public HashMap<String, byte[]> files = new HashMap<String, byte[]>();
public ArrayList<ClassNode> classes = new ArrayList<ClassNode>();
}

View file

@ -33,7 +33,11 @@ public class JarUtils {
* @param clazzList the existing map of loaded classes
* @throws IOException
*/
public static void put(final File jarFile, final HashMap<String, ClassNode> clazzList) throws IOException {
public static void put(final File jarFile) throws IOException {
FileContainer container = new FileContainer();
container.name = jarFile.getName();
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
ZipInputStream jis = new ZipInputStream(new FileInputStream(jarFile));
ZipEntry entry;
while ((entry = jis.getNextEntry()) != null) {
@ -41,7 +45,7 @@ public class JarUtils {
final String name = entry.getName();
if (!name.endsWith(".class")) {
if(!entry.isDirectory())
BytecodeViewer.loadedResources.put(name, getBytes(jis));
files.put(name, getBytes(jis));
} else {
byte[] bytes = getBytes(jis);
String cafebabe = String.format("%02X", bytes[0])
@ -51,7 +55,7 @@ public class JarUtils {
if(cafebabe.toLowerCase().equals("cafebabe")) {
try {
final ClassNode cn = getNode(bytes);
clazzList.put(cn.name, cn);
container.classes.add(cn);
} catch(Exception e) {
e.printStackTrace();
}
@ -67,18 +71,58 @@ public class JarUtils {
}
}
jis.close();
container.files = files;
BytecodeViewer.files.add(container);
}
public static ArrayList<ClassNode> loadClasses(final File jarFile) throws IOException {
ArrayList<ClassNode> classes = new ArrayList<ClassNode>();
ZipInputStream jis = new ZipInputStream(new FileInputStream(jarFile));
ZipEntry entry;
while ((entry = jis.getNextEntry()) != null) {
try {
final String name = entry.getName();
if (name.endsWith(".class")) {
byte[] bytes = getBytes(jis);
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 {
final ClassNode cn = getNode(bytes);
classes.add(cn);
} catch(Exception e) {
e.printStackTrace();
}
} else {
System.out.println(jarFile+">"+name+": Header does not start with CAFEBABE, ignoring.");
}
}
} catch(Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
} finally {
jis.closeEntry();
}
}
jis.close();
return classes;
}
/**
* Loads resources only, just for .APK
* @param zipFile the input zip file
* @throws IOException
*/
public static void loadResources(final File zipFile) throws IOException {
public static HashMap<String, byte[]> loadResources(final File zipFile) throws IOException {
if(!zipFile.exists())
return; //just ignore
return null; //just ignore
HashMap<String, byte[]> files = new HashMap<String, byte[]>();
ZipInputStream jis = new ZipInputStream(new FileInputStream(zipFile));
ZipEntry entry;
while ((entry = jis.getNextEntry()) != null) {
@ -86,7 +130,7 @@ public class JarUtils {
final String name = entry.getName();
if (!name.endsWith(".class") && !name.endsWith(".dex")) {
if(!entry.isDirectory())
BytecodeViewer.loadedResources.put(name, getBytes(jis));
files.put(name, getBytes(jis));
jis.closeEntry();
continue;
@ -98,6 +142,8 @@ public class JarUtils {
}
}
jis.close();
return files;
}
@ -164,15 +210,15 @@ public class JarUtils {
out.write((manifest.trim() + "\r\n\r\n").getBytes());
out.closeEntry();
for (Entry<String, byte[]> entry : BytecodeViewer.loadedResources
.entrySet()) {
String filename = entry.getKey();
if (!filename.startsWith("META-INF")) {
out.putNextEntry(new ZipEntry(filename));
out.write(entry.getValue());
out.closeEntry();
for(FileContainer container : BytecodeViewer.files)
for (Entry<String, byte[]> entry : container.files.entrySet()) {
String filename = entry.getKey();
if (!filename.startsWith("META-INF")) {
out.putNextEntry(new ZipEntry(filename));
out.write(entry.getValue());
out.closeEntry();
}
}
}
out.close();
} catch (IOException e) {
@ -198,15 +244,15 @@ public class JarUtils {
out.closeEntry();
}
for (Entry<String, byte[]> entry : BytecodeViewer.loadedResources
.entrySet()) {
String filename = entry.getKey();
if (!filename.startsWith("META-INF")) {
out.putNextEntry(new ZipEntry(filename));
out.write(entry.getValue());
out.closeEntry();
for(FileContainer container : BytecodeViewer.files)
for (Entry<String, byte[]> entry : container.files.entrySet()) {
String filename = entry.getKey();
if (!filename.startsWith("META-INF")) {
out.putNextEntry(new ZipEntry(filename));
out.write(entry.getValue());
out.closeEntry();
}
}
}
out.close();
} catch (IOException e) {

View file

@ -77,7 +77,10 @@ public class ExceptionUI extends JFrame {
e.printStackTrace(new PrintWriter(sw));
e.printStackTrace();
txtrBytecodeViewerIs.setText("Bytecode Viewer Version: " + BytecodeViewer.version + BytecodeViewer.nl + BytecodeViewer.nl + sw.toString());
txtrBytecodeViewerIs.setText("Bytecode Viewer Version: " + BytecodeViewer.version+
", Preview Copy: " + BytecodeViewer.previewCopy +
", Fat Jar: " + BytecodeViewer.fatJar +
BytecodeViewer.nl + BytecodeViewer.nl + sw.toString());
this.setLocationRelativeTo(null);
this.setVisible(true);
}

View file

@ -46,6 +46,8 @@ scrollPane.setViewportView(textArea);
textArea.setText("Bytecode Viewer "+BytecodeViewer.version+" is an open source program developed and maintained by Konloch (konloch@gmail.com)\r\n"+
"100% free and open sourced licensed under GPL v3 CopyLeft\r\n\r\n"+
"Settings:"+BytecodeViewer.nl+
" Preview Copy:"+BytecodeViewer.previewCopy+BytecodeViewer.nl+
" Fat Jar:"+BytecodeViewer.fatJar+BytecodeViewer.nl+
" BCV Dir: " + BytecodeViewer.getBCVDirectory()+BytecodeViewer.nl+
" Python 2.7 (or PyPy): " + BytecodeViewer.python+BytecodeViewer.nl+
" Python 3.X (or PyPy): " + BytecodeViewer.python3+BytecodeViewer.nl+

View file

@ -17,6 +17,7 @@ import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
@ -624,6 +625,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Procyon Decompiler"));
panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -650,6 +652,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("CFR Decompiler"));
panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -677,6 +680,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("FernFlower Decompiler"));
panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -705,6 +709,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Bytecode Decompiler"));
panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -718,7 +723,7 @@ public class ClassViewer extends Viewer {
hex.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
}
if (pane1 == 6) {// bytecode
if (pane1 == 6) {//smali bytecode
RSyntaxTextArea panelArea = new RSyntaxTextArea();
panelArea
.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
@ -741,6 +746,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Smali Decompiler"));
panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -768,6 +774,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Krakatau Decompiler"));
panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -799,6 +806,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Krakatau Disassembler"));
panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -826,6 +834,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("JD-GUI Decompiler"));
panel1.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -870,6 +879,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Procyon Decompiler"));
panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -897,6 +907,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("CFR Decompiler"));
panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -924,6 +935,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("CFR Decompiler"));
panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -950,6 +962,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Bytecode Decompiler"));
panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -985,6 +998,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Smali Decompiler"));
panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1012,6 +1026,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Krakatau Decompiler"));
panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1041,6 +1056,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Krakatau Disassembler"));
panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1068,6 +1084,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("JD-GUI Decompiler"));
panel2.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1113,6 +1130,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Procyon Decompiler"));
panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1140,6 +1158,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("CFR Decompiler"));
panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1167,6 +1186,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("CFR Decompiler"));
panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1193,6 +1213,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Bytecode Decompiler"));
panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1228,6 +1249,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Smali Decompiler"));
panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1255,6 +1277,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Krakatau Decompiler"));
panel3.add(scrollPane);
java3 = panelArea;
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1284,6 +1307,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("Krakatau Disassembler"));
panel3.add(scrollPane);
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));
@ -1311,6 +1335,7 @@ public class ClassViewer extends Viewer {
@Override public void keyReleased(KeyEvent arg0) { }
@Override public void keyTyped(KeyEvent arg0) { }
});
scrollPane.setColumnHeaderView(new JLabel("JD-GUI Decompiler"));
panel3.add(scrollPane);
java3 = panelArea;
panelArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int)BytecodeViewer.viewer.fontSpinner.getValue()));

View file

@ -56,8 +56,8 @@ public class FileNavigationPane extends VisibleComponent implements
JButton open = new JButton("+");
JButton close = new JButton("-");
MyTreeNode treeRoot = new MyTreeNode("Root");
MyTree tree;
MyTreeNode treeRoot = new MyTreeNode("Loaded Files:");
MyTree tree = new MyTree(treeRoot);
public FileNavigationPane(final FileChangeNotifier fcn) {
super("ClassNavigation");
@ -87,8 +87,6 @@ public class FileNavigationPane extends VisibleComponent implements
});
getContentPane().setLayout(new BorderLayout());
this.tree = new MyTree(treeRoot);
getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
MouseAdapter ml = new MouseAdapter() {
@ -97,7 +95,7 @@ public class FileNavigationPane extends VisibleComponent implements
if (path == null)
return;
final StringBuffer nameBuffer = new StringBuffer();
for (int i = 1; i < path.getPathCount(); i++) {
for (int i = 2; i < path.getPathCount(); i++) {
nameBuffer.append(path.getPathComponent(i));
if (i < path.getPathCount() - 1) {
nameBuffer.append("/");
@ -290,61 +288,70 @@ public class FileNavigationPane extends VisibleComponent implements
public void updateTree() {
try {
treeRoot.removeAllChildren();
for (final Entry<String, ClassNode> entry : BytecodeViewer.loadedClasses
.entrySet()) {
String name = entry.getKey();
final String[] spl = name.split("/");
if (spl.length < 2) {
treeRoot.add(new MyTreeNode(name+".class"));
} else {
MyTreeNode parent = treeRoot;
for (int i1 = 0; i1 < spl.length; i1++) {
String s = spl[i1];
MyTreeNode child = null;
for (int i = 0; i < parent.getChildCount(); i++) {
if (((MyTreeNode) parent.getChildAt(i)).getUserObject()
.equals(s)) {
child = (MyTreeNode) parent.getChildAt(i);
break;
for (FileContainer container : BytecodeViewer.files) {
MyTreeNode root = new MyTreeNode(container.name);
treeRoot.add(root);
if(!container.classes.isEmpty()) {
for(ClassNode c : container.classes) {
String name = c.name;
final String[] spl = name.split("/");
if (spl.length < 2) {
root.add(new MyTreeNode(name+".class"));
} else {
MyTreeNode parent = root;
for (int i1 = 0; i1 < spl.length; i1++) {
String s = spl[i1];
MyTreeNode child = null;
for (int i = 0; i < parent.getChildCount(); i++) {
if (((MyTreeNode) parent.getChildAt(i)).getUserObject()
.equals(s)) {
child = (MyTreeNode) parent.getChildAt(i);
break;
}
}
if (child == null) {
if(i1 == spl.length-1)
child = new MyTreeNode(s+".class");
else
child = new MyTreeNode(s);
parent.add(child);
}
parent = child;
}
}
if (child == null) {
if(i1 == spl.length-1)
child = new MyTreeNode(s+".class");
else
child = new MyTreeNode(s);
parent.add(child);
}
parent = child;
}
}
if(!container.files.isEmpty()) {
for (final Entry<String, byte[]> entry : container.files.entrySet()) {
String name = entry.getKey();
final String[] spl = name.split("/");
if (spl.length < 2) {
root.add(new MyTreeNode(name));
} else {
MyTreeNode parent = root;
for (final String s : spl) {
MyTreeNode child = null;
for (int i = 0; i < parent.getChildCount(); i++) {
if (((MyTreeNode) parent.getChildAt(i)).getUserObject()
.equals(s)) {
child = (MyTreeNode) parent.getChildAt(i);
break;
}
}
if (child == null) {
child = new MyTreeNode(s);
parent.add(child);
}
parent = child;
}
}
}
}
}
for (final Entry<String, byte[]> entry : BytecodeViewer.loadedResources.entrySet()) {
String name = entry.getKey();
final String[] spl = name.split("/");
if (spl.length < 2) {
treeRoot.add(new MyTreeNode(name));
} else {
MyTreeNode parent = treeRoot;
for (final String s : spl) {
MyTreeNode child = null;
for (int i = 0; i < parent.getChildCount(); i++) {
if (((MyTreeNode) parent.getChildAt(i)).getUserObject()
.equals(s)) {
child = (MyTreeNode) parent.getChildAt(i);
break;
}
}
if (child == null) {
child = new MyTreeNode(s);
parent.add(child);
}
parent = child;
}
}
}
treeRoot.sort();
tree.expandPath(new TreePath(tree.getModel().getRoot()));
tree.updateUI();

View file

@ -86,7 +86,6 @@ public class FileViewer extends Viewer {
JLabel label = new JLabel("", new ImageIcon(image), JLabel.CENTER);
panel2.add( label, BorderLayout.CENTER );
panel2.addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
int notches = e.getWheelRotation();
@ -100,7 +99,6 @@ public class FileViewer extends Viewer {
panel2.add( label, BorderLayout.CENTER );
panel2.updateUI();
}
});
return;
} catch(Exception e) {
@ -134,7 +132,7 @@ public class FileViewer extends Viewer {
} else if(name.endsWith(".properties") || name.endsWith(".mf") || name.endsWith(".sf")) {
panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PROPERTIES_FILE);
panelArea.setText(contentsS);
} else if(name.endsWith(".php") || name.startsWith("<?php")) {
} else if(name.endsWith(".php") || contentsS.startsWith("<?php")) {
panelArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_PHP);
panelArea.setText(contentsS);
} else if(name.endsWith(".js")) {

View file

@ -37,7 +37,6 @@ import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Dex2Jar;
import the.bytecode.club.bytecodeviewer.Enjarify;
import the.bytecode.club.bytecodeviewer.FileChangeNotifier;
import the.bytecode.club.bytecodeviewer.JarUtils;
import the.bytecode.club.bytecodeviewer.MiscUtils;
@ -1907,7 +1906,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
setSize(new Dimension(800, 400));
if(BytecodeViewer.previewCopy)
setTitle("Bytecode Viewer "+BytecodeViewer.version+" preview - https://bytecodeviewer.com | https://the.bytecode.club - @Konloch");
setTitle("Bytecode Viewer "+BytecodeViewer.version+" Preview - https://bytecodeviewer.com | https://the.bytecode.club - @Konloch");
else
setTitle("Bytecode Viewer "+BytecodeViewer.version+" - https://bytecodeviewer.com | https://the.bytecode.club - @Konloch");

View file

@ -42,9 +42,9 @@ public class Refactorer {
cr.accept(cn, 0);
refactored.put(oldName, cn);
}
for (Map.Entry<String, ClassNode> factor : refactored.entrySet()) {
/*for (Map.Entry<String, ClassNode> factor : refactored.entrySet()) {
BytecodeViewer.relocate(factor.getKey(), factor.getValue());
}
}*/
mapper.printMap();
}