2018-01-31 15:03:53 +00:00
|
|
|
package the.bytecode.club.bytecodeviewer;
|
|
|
|
|
|
|
|
import java.awt.event.KeyEvent;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.net.URL;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
2021-04-12 22:31:22 +00:00
|
|
|
import java.util.Objects;
|
2021-06-26 01:13:46 +00:00
|
|
|
import javax.swing.*;
|
2021-06-26 12:59:51 +00:00
|
|
|
|
2021-06-29 09:41:29 +00:00
|
|
|
import com.google.gson.Gson;
|
|
|
|
import com.google.gson.GsonBuilder;
|
2018-01-31 15:03:53 +00:00
|
|
|
import me.konloch.kontainer.io.HTTPRequest;
|
|
|
|
import org.apache.commons.io.FileUtils;
|
|
|
|
import org.objectweb.asm.tree.ClassNode;
|
|
|
|
import the.bytecode.club.bootloader.Boot;
|
|
|
|
import the.bytecode.club.bytecodeviewer.api.ClassNodeLoader;
|
2021-06-26 14:21:23 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.compilers.Compiler;
|
2021-06-26 17:36:26 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.gui.components.*;
|
2021-06-26 12:26:12 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.TabbedPane;
|
2021-06-26 01:13:46 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer;
|
2021-06-22 18:05:25 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.gui.resourcelist.ResourceListPane;
|
2018-01-31 15:03:53 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.gui.MainViewerGUI;
|
2021-06-26 01:13:46 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.gui.resourcesearch.SearchBoxPane;
|
|
|
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.WorkPaneMainComponent;
|
2021-06-26 12:26:12 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ResourceViewer;
|
2018-01-31 15:03:53 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.obfuscators.mapping.Refactorer;
|
|
|
|
import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
|
2021-06-21 09:45:31 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.util.*;
|
2021-06-26 15:10:02 +00:00
|
|
|
import the.bytecode.club.bytecodeviewer.resources.importing.ImportResource;
|
2021-06-21 09:45:31 +00:00
|
|
|
|
2021-07-05 03:34:37 +00:00
|
|
|
import static javax.swing.JOptionPane.INFORMATION_MESSAGE;
|
2021-06-21 09:45:31 +00:00
|
|
|
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
2021-06-29 09:41:29 +00:00
|
|
|
import static the.bytecode.club.bytecodeviewer.Settings.addRecentPlugin;
|
2021-07-06 00:25:55 +00:00
|
|
|
import static the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComponent.DecompilerComponentTypes.JAVA;
|
|
|
|
import static the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComponent.DecompilerComponentTypes.JAVA_AND_BYTECODE;
|
2021-06-29 09:41:29 +00:00
|
|
|
import static the.bytecode.club.bytecodeviewer.util.MiscUtils.guessLanguage;
|
2018-01-31 15:03:53 +00:00
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* 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 <http://www.gnu.org/licenses/>. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A lightweight Java Reverse Engineering suite, developed by Konloch - http://konloch.me
|
2021-06-21 09:45:31 +00:00
|
|
|
*
|
2019-04-13 03:42:04 +00:00
|
|
|
* All you have to do is add a jar or class file into the workspace,
|
2019-04-17 06:45:15 +00:00
|
|
|
* select the file you want then it will start decompiling the class in the background.
|
|
|
|
* When it's done it will show the Source code, Bytecode and Hexcode of the class file you chose.
|
2021-06-21 09:45:31 +00:00
|
|
|
*
|
2019-04-17 06:45:15 +00:00
|
|
|
* There is also a plugin system that will allow you to interact with the loaded classfiles.
|
|
|
|
* For example you can write a String deobfuscator, a malicious code searcher,
|
|
|
|
* or anything else you can think of.
|
2021-06-21 09:45:31 +00:00
|
|
|
*
|
2019-04-17 06:45:15 +00:00
|
|
|
* You can either use one of the pre-written plugins, or write your own. It supports java scripting.
|
|
|
|
* Once a plugin is activated, it will send a ClassNode ArrayList of every single class loaded in the
|
|
|
|
* file system to the execute function, this allows the user to handle it completely using ASM.
|
2021-06-21 09:45:31 +00:00
|
|
|
*
|
2019-04-17 06:45:15 +00:00
|
|
|
* Are you a Java Reverse Engineer? Or maybe you want to learn Java Reverse Engineering?
|
2021-04-12 20:19:12 +00:00
|
|
|
* Join The Bytecode Club, we're noob friendly, and censorship free.
|
|
|
|
* http://the.bytecode.club
|
2021-06-21 09:45:31 +00:00
|
|
|
*
|
2021-06-26 02:59:43 +00:00
|
|
|
* TODO BUGS:
|
2021-07-05 04:50:28 +00:00
|
|
|
* + Panes that currently are being opened/decompiled should not be able to be refreshed - Causes a lock
|
2021-06-28 04:14:20 +00:00
|
|
|
* + View>Visual Settings>Show Class Methods
|
2021-06-26 05:25:50 +00:00
|
|
|
* + Spam-clicking the refresh button will cause the swing thread to deadlock (Quickly opening resources used to also do this)
|
2021-06-26 02:59:43 +00:00
|
|
|
* This is caused by the ctrlMouseWheelZoom code, a temporary patch is just removing it worst case
|
2021-07-05 02:07:34 +00:00
|
|
|
* + Versioning and updating need to be fixed
|
2021-06-26 05:25:50 +00:00
|
|
|
* + Fix classfile searcher
|
|
|
|
* + Smali Assembly compile - Needs to be fixed
|
2021-06-26 02:59:43 +00:00
|
|
|
*
|
|
|
|
* TODO IN-PROGRESS:
|
2021-07-01 21:54:10 +00:00
|
|
|
* + While loading an external plugin it should check if its java or JS, if so it should ask if you'd like to run or edit the plugin using the PluginWriter
|
2021-07-05 02:07:34 +00:00
|
|
|
* + Resource Importer needs to be rewritten to handle resources better
|
2021-07-05 04:50:28 +00:00
|
|
|
* + Resource Exporter/Save/Decompile As Zip needs to be rewrittern
|
2021-06-26 05:25:50 +00:00
|
|
|
* + Finish dragging code
|
|
|
|
* + Finish right-click tab menu detection
|
|
|
|
* + Fix hook inject for EZ-Injection
|
2021-06-26 02:59:43 +00:00
|
|
|
*
|
|
|
|
* TODO FEATURES:
|
2021-07-01 21:54:10 +00:00
|
|
|
* + CLI Headless needs to be supported
|
2021-06-26 05:25:50 +00:00
|
|
|
* + Add stackmapframes to bytecode decompiler
|
|
|
|
* + Add JEB decompiler optionally, requires them to add jeb library jar
|
|
|
|
* + Add https://github.com/exbin/bined as the replacement Hed Viewer/Editor
|
|
|
|
* + Make the decompilers launch in a separate process
|
|
|
|
* + Make it use that global last used inside of export as jar
|
|
|
|
* + Make zipfile not include the decode shit
|
|
|
|
* + Make ez-injection plugin console show all sys.out calls
|
|
|
|
* + Add decompile as zip for krakatau-bytecode, jd-gui and smali for CLI
|
|
|
|
* + Add decompile all as zip for CLI
|
2018-01-31 15:41:24 +00:00
|
|
|
*
|
2021-07-04 08:51:05 +00:00
|
|
|
* TODO IDEAS:
|
2021-07-05 02:07:34 +00:00
|
|
|
* + App Bundle Support
|
2021-07-05 04:50:28 +00:00
|
|
|
* + Add the setting to force all non-class resources to be opened with the Hex Viewer
|
2021-07-04 10:23:14 +00:00
|
|
|
* ^ Optionally a right-click menu open-as would work inside of the resource list
|
2021-07-04 08:51:05 +00:00
|
|
|
* + Allow class files to be opened without needing the .class extension
|
|
|
|
* ^ Easiest way to do this is to read the file header CAFEBABE on resource view
|
|
|
|
* + Look into removing the loaded classes from inside the FileContainer & then generate the ClassNodes on demand
|
|
|
|
* ^ This has the added benefit of only extracting on decompilation/when needed. It would also mean everything
|
|
|
|
* could be treated as byte[] file resources instead of juggling between Classes and File resources.
|
|
|
|
* ^ An added bonus would be you could also support BCEL (along with other bytecode manipulation libraries)
|
|
|
|
* and add support for https://github.com/ptnkjke/Java-Bytecode-Editor visualizer as a plugin
|
|
|
|
*
|
2018-01-31 15:03:53 +00:00
|
|
|
* @author Konloch
|
2019-04-17 06:45:15 +00:00
|
|
|
* @author The entire BCV community
|
2018-01-31 15:03:53 +00:00
|
|
|
*/
|
|
|
|
|
2021-06-21 09:45:31 +00:00
|
|
|
public class BytecodeViewer
|
|
|
|
{
|
|
|
|
public static String[] args;
|
|
|
|
public static MainViewerGUI viewer = null;
|
|
|
|
public static ClassNodeLoader loader = new ClassNodeLoader(); //might be insecure due to assholes targeting BCV,
|
2021-06-29 15:17:42 +00:00
|
|
|
public static SecurityMan sm = new SecurityMan(); //might be insecure due to assholes targeting BCV,
|
2021-06-21 09:45:31 +00:00
|
|
|
public static Refactorer refactorer = new Refactorer();
|
|
|
|
public static List<FileContainer> files = new ArrayList<>(); //all of BCV's loaded files/classes/etc
|
|
|
|
public static List<Process> createdProcesses = new ArrayList<>();
|
2021-07-06 00:25:55 +00:00
|
|
|
public static final DecompilerViewComponent krakatau = new DecompilerViewComponent("Krakatau", JAVA_AND_BYTECODE);
|
2021-06-29 09:41:29 +00:00
|
|
|
public static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
2021-06-22 18:05:25 +00:00
|
|
|
public static final boolean EXPERIMENTAL_TAB_CODE = false;
|
2021-07-05 04:50:28 +00:00
|
|
|
public static final boolean DEV_MODE = false; //if true error streams as preserved
|
2021-06-21 11:13:11 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
/**
|
|
|
|
* The version checker thread
|
|
|
|
*/
|
2021-07-01 09:48:10 +00:00
|
|
|
private static final Thread versionChecker = new Thread(new VersionChecker(), "Version Checker");
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Pings back to bytecodeviewer.com to be added into the total running statistics
|
|
|
|
*/
|
2021-06-21 11:32:07 +00:00
|
|
|
private static final Thread pingBack = new Thread(() -> {
|
2021-04-12 22:31:22 +00:00
|
|
|
try {
|
|
|
|
new HTTPRequest(new URL("https://bytecodeviewer.com/add.php")).read();
|
|
|
|
} catch (Exception e) {
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.pingback = false;
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
2021-07-01 09:48:10 +00:00
|
|
|
}, "Pingback");
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Downloads & installs the krakatau & enjarify zips
|
|
|
|
*/
|
2021-06-21 11:32:07 +00:00
|
|
|
private static final Thread installFatJar = new Thread(() -> {
|
2021-04-12 22:31:22 +00:00
|
|
|
try {
|
2021-06-21 09:45:31 +00:00
|
|
|
if (OFFLINE_MODE) {
|
2021-04-12 22:31:22 +00:00
|
|
|
Boot.dropKrakatau();
|
|
|
|
Boot.dropEnjarify();
|
|
|
|
} else {
|
|
|
|
Boot.populateUrlList();
|
|
|
|
Boot.populateLibsDirectory();
|
|
|
|
Boot.downloadZipsOnly();
|
|
|
|
Boot.checkKrakatau();
|
|
|
|
Boot.checkEnjarify();
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
2021-04-12 22:31:22 +00:00
|
|
|
} catch (Exception e) {
|
|
|
|
e.printStackTrace();
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
2021-07-01 09:48:10 +00:00
|
|
|
}, "Install Fat-Jar");
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Used to check incase booting failed for some reason, this kicks in as a fail safe
|
|
|
|
*/
|
2021-07-01 09:48:10 +00:00
|
|
|
private static final Thread bootCheck = new Thread(new BootCheck(), "Boot Check");
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Main startup
|
|
|
|
*
|
|
|
|
* @param args files you want to open or CLI
|
|
|
|
*/
|
2021-07-01 21:54:10 +00:00
|
|
|
public static void main(String[] args)
|
|
|
|
{
|
2018-01-31 15:41:24 +00:00
|
|
|
BytecodeViewer.args = args;
|
2021-06-21 09:45:31 +00:00
|
|
|
System.out.println("https://the.bytecode.club - Created by @Konloch - Bytecode Viewer " + VERSION + ", " + "Fat-Jar: " + FAT_JAR);
|
2018-01-31 15:41:24 +00:00
|
|
|
System.setSecurityManager(sm);
|
2021-06-21 09:45:31 +00:00
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
try {
|
2021-06-26 01:13:46 +00:00
|
|
|
//precache settings file
|
2021-06-29 09:41:29 +00:00
|
|
|
SettingsSerializer.preloadSettingsFile();
|
2021-06-26 01:13:46 +00:00
|
|
|
//setup look and feel
|
|
|
|
Configuration.lafTheme.setLAF();
|
|
|
|
|
2019-04-17 06:45:15 +00:00
|
|
|
if (PREVIEW_COPY && !CommandLineInput.containsCommand(args))
|
2021-04-12 20:19:12 +00:00
|
|
|
showMessage("WARNING: This is a preview/dev copy, you WON'T be alerted when " + VERSION + " is "
|
|
|
|
+ "actually out if you use this." + nl +
|
2021-06-21 09:45:31 +00:00
|
|
|
"Make sure to watch the repo: https://github.com/Konloch/bytecode-viewer for " + VERSION + "'s release");
|
2021-07-01 21:54:10 +00:00
|
|
|
|
|
|
|
//set swing specific system properties
|
|
|
|
System.setProperty("swing.aatext", "true");
|
|
|
|
|
|
|
|
//setup swing components
|
2018-01-31 15:41:24 +00:00
|
|
|
viewer = new MainViewerGUI();
|
2021-06-29 00:05:18 +00:00
|
|
|
SwingUtilities.updateComponentTreeUI(viewer);
|
2021-07-01 21:54:10 +00:00
|
|
|
|
|
|
|
//load settings and set swing components state
|
2021-06-29 09:41:29 +00:00
|
|
|
SettingsSerializer.loadSettings();
|
2021-07-01 21:54:10 +00:00
|
|
|
|
|
|
|
//set translation language
|
2021-06-29 09:41:29 +00:00
|
|
|
if(!Settings.hasSetLanguageAsSystemLanguage)
|
|
|
|
MiscUtils.setLanguage(guessLanguage());
|
2021-06-29 00:05:18 +00:00
|
|
|
|
2021-07-01 21:54:10 +00:00
|
|
|
//handle CLI
|
2018-01-31 15:41:24 +00:00
|
|
|
int CLI = CommandLineInput.parseCommandLine(args);
|
|
|
|
|
|
|
|
if (CLI == CommandLineInput.STOP)
|
|
|
|
return;
|
|
|
|
|
2019-04-17 06:45:15 +00:00
|
|
|
if (!FAT_JAR) {
|
2018-01-31 15:41:24 +00:00
|
|
|
bootCheck.start();
|
|
|
|
|
2021-04-12 20:19:12 +00:00
|
|
|
Boot.boot(args, CLI != CommandLineInput.OPEN_FILE);
|
2018-01-31 15:41:24 +00:00
|
|
|
} else
|
2021-06-21 11:32:07 +00:00
|
|
|
installFatJar.start();
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
if (CLI == CommandLineInput.OPEN_FILE)
|
2021-06-21 11:32:07 +00:00
|
|
|
BytecodeViewer.boot(false);
|
2018-01-31 15:41:24 +00:00
|
|
|
else {
|
2021-06-21 11:32:07 +00:00
|
|
|
BytecodeViewer.boot(true);
|
2018-01-31 15:41:24 +00:00
|
|
|
CommandLineInput.executeCommandLine(args);
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Boot after all of the libraries have been loaded
|
|
|
|
*
|
|
|
|
* @param cli is it running CLI mode or not
|
|
|
|
*/
|
2021-07-05 02:07:34 +00:00
|
|
|
public static void boot(boolean cli)
|
|
|
|
{
|
2021-07-01 09:06:12 +00:00
|
|
|
cleanupAsync();
|
2021-07-05 02:07:34 +00:00
|
|
|
Runtime.getRuntime().addShutdownHook(new Thread(() ->
|
|
|
|
{
|
2021-04-12 22:31:22 +00:00
|
|
|
for (Process proc : createdProcesses)
|
|
|
|
proc.destroy();
|
2021-06-29 09:41:29 +00:00
|
|
|
SettingsSerializer.saveSettings();
|
2021-04-12 22:31:22 +00:00
|
|
|
cleanup();
|
2021-07-01 09:48:10 +00:00
|
|
|
}, "Shutdown Hook"));
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
viewer.calledAfterLoad();
|
2021-06-29 09:41:29 +00:00
|
|
|
Settings.resetRecentFilesMenu();
|
2018-01-31 15:41:24 +00:00
|
|
|
|
2021-07-05 02:07:34 +00:00
|
|
|
//ping back once on first boot to add to global user count
|
|
|
|
if (!Configuration.pingback)
|
|
|
|
{
|
2021-06-21 11:32:07 +00:00
|
|
|
pingBack.start();
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.pingback = true;
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
|
|
|
|
2021-06-21 22:45:00 +00:00
|
|
|
if (viewer.updateCheck.isSelected())
|
2018-01-31 15:41:24 +00:00
|
|
|
versionChecker.start();
|
|
|
|
|
|
|
|
if (!cli)
|
|
|
|
viewer.setVisible(true);
|
|
|
|
|
2021-06-21 11:13:11 +00:00
|
|
|
System.out.println("Start up took " + ((System.currentTimeMillis() - Configuration.start) / 1000) + " seconds");
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
if (!cli)
|
|
|
|
if (args.length >= 1)
|
2021-06-21 11:13:11 +00:00
|
|
|
for (String s : args)
|
2018-01-31 15:41:24 +00:00
|
|
|
openFiles(new File[]{new File(s)}, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* because Smali and Baksmali System.exit if it failed
|
|
|
|
*
|
|
|
|
* @param i
|
|
|
|
*/
|
|
|
|
public static void exit(int i) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the java command it can use to launch the decompilers
|
|
|
|
*
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
public static synchronized String getJavaCommand() {
|
|
|
|
try {
|
|
|
|
sm.stopBlocking();
|
|
|
|
ProcessBuilder pb = new ProcessBuilder("java", "-version");
|
2021-04-12 22:31:22 +00:00
|
|
|
pb.start();
|
2018-01-31 15:41:24 +00:00
|
|
|
sm.setBlocking();
|
2021-04-12 22:31:22 +00:00
|
|
|
return "java"; //java is set
|
2018-01-31 15:41:24 +00:00
|
|
|
} catch (Exception e) { //ignore
|
|
|
|
sm.setBlocking();
|
2021-06-21 11:13:11 +00:00
|
|
|
boolean empty = Configuration.java.isEmpty();
|
2018-01-31 15:41:24 +00:00
|
|
|
while (empty) {
|
2021-06-21 09:45:31 +00:00
|
|
|
showMessage("You need to set your Java path, this requires the JRE to be downloaded." + nl +
|
2021-06-21 11:13:11 +00:00
|
|
|
"(C:/Program Files/Java/JDK_xx/bin/java.exe)");
|
2021-06-21 14:55:18 +00:00
|
|
|
viewer.selectJava();
|
2021-06-21 11:13:11 +00:00
|
|
|
empty = Configuration.java.isEmpty();
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
|
|
|
}
|
2021-06-21 11:13:11 +00:00
|
|
|
return Configuration.java;
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the currently opened ClassNode
|
|
|
|
*
|
|
|
|
* @return the currently opened ClassNode
|
|
|
|
*/
|
|
|
|
public static ClassNode getCurrentlyOpenedClassNode() {
|
|
|
|
return viewer.workPane.getCurrentViewer().cn;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the ClassNode by the specified name
|
|
|
|
*
|
|
|
|
* @param name the class name
|
|
|
|
* @return the ClassNode instance
|
|
|
|
*/
|
|
|
|
public static ClassNode getClassNode(String name) {
|
|
|
|
for (FileContainer container : files)
|
|
|
|
for (ClassNode c : container.classes)
|
|
|
|
if (c.name.equals(name))
|
|
|
|
return c;
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2019-04-17 06:45:15 +00:00
|
|
|
public static FileContainer getFileContainer(String name) {
|
|
|
|
for (FileContainer container : files)
|
|
|
|
if (container.name.equals(name))
|
|
|
|
return container;
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2019-06-01 01:04:07 +00:00
|
|
|
public static List<FileContainer> getFiles() {
|
|
|
|
return files;
|
|
|
|
}
|
|
|
|
|
2019-04-17 06:45:15 +00:00
|
|
|
public static ClassNode getClassNode(FileContainer container, String name) {
|
|
|
|
for (ClassNode c : container.classes)
|
|
|
|
if (c.name.equals(name))
|
|
|
|
return c;
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
/**
|
|
|
|
* Grabs the file contents of the loaded resources.
|
|
|
|
*
|
|
|
|
* @param name the file name
|
|
|
|
* @return the file contents as a byte[]
|
|
|
|
*/
|
|
|
|
public static byte[] getFileContents(String name) {
|
2021-06-26 12:59:51 +00:00
|
|
|
for (FileContainer container : files)
|
|
|
|
if (container.files.containsKey(name))
|
|
|
|
return container.files.get(name);
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
2021-06-26 12:38:58 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Grab the byte array from the loaded Class object
|
|
|
|
*
|
|
|
|
* @param clazz
|
|
|
|
* @return
|
|
|
|
* @throws IOException
|
|
|
|
*/
|
|
|
|
public static byte[] getClassFile(Class<?> clazz) throws IOException {
|
|
|
|
try (InputStream is = clazz.getResourceAsStream(
|
|
|
|
"/" + clazz.getName().replace('.', '/') + ".class");
|
|
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
|
|
|
int r;
|
|
|
|
byte[] buffer = new byte[8192];
|
|
|
|
while ((r = Objects.requireNonNull(is).read(buffer)) >= 0) {
|
|
|
|
baos.write(buffer, 0, r);
|
|
|
|
}
|
|
|
|
return baos.toByteArray();
|
|
|
|
}
|
|
|
|
}
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces an old node with a new instance
|
|
|
|
*
|
|
|
|
* @param oldNode the old instance
|
|
|
|
* @param newNode the new instance
|
|
|
|
*/
|
2021-07-05 02:07:34 +00:00
|
|
|
public static void updateNode(ClassNode oldNode, ClassNode newNode)
|
|
|
|
{
|
2018-01-31 15:41:24 +00:00
|
|
|
for (FileContainer container : files) {
|
|
|
|
if (container.classes.remove(oldNode))
|
|
|
|
container.classes.add(newNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets all of the loaded classes as an array list
|
|
|
|
*
|
|
|
|
* @return the loaded classes as an array list
|
|
|
|
*/
|
|
|
|
public static ArrayList<ClassNode> getLoadedClasses() {
|
2021-04-12 22:31:22 +00:00
|
|
|
ArrayList<ClassNode> a = new ArrayList<>();
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
for (FileContainer container : files)
|
|
|
|
for (ClassNode c : container.classes)
|
|
|
|
if (!a.contains(c))
|
|
|
|
a.add(c);
|
|
|
|
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2021-07-03 19:29:31 +00:00
|
|
|
/**
|
|
|
|
* Called any time refresh is called to automatically compile all of the compilable panes that're opened.
|
|
|
|
*/
|
|
|
|
public static boolean autoCompileSuccessful()
|
|
|
|
{
|
|
|
|
if(!BytecodeViewer.viewer.autoCompileOnRefresh.isSelected())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
try {
|
2021-07-05 03:37:01 +00:00
|
|
|
return compile(true, false);
|
2021-07-03 19:29:31 +00:00
|
|
|
} catch (NullPointerException ignored) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-31 15:41:24 +00:00
|
|
|
/**
|
|
|
|
* Compile all of the compilable panes that're opened.
|
|
|
|
*
|
|
|
|
* @param message if it should send a message saying it's compiled sucessfully.
|
|
|
|
* @return true if no errors, false if it failed to compile.
|
|
|
|
*/
|
2021-07-05 03:37:01 +00:00
|
|
|
public static boolean compile(boolean message, boolean successAlert) {
|
2021-06-21 23:37:55 +00:00
|
|
|
BytecodeViewer.viewer.updateBusyStatus(true);
|
2021-07-05 02:07:34 +00:00
|
|
|
boolean noErrors = true;
|
2018-01-31 15:41:24 +00:00
|
|
|
boolean actuallyTried = false;
|
2021-07-06 00:06:05 +00:00
|
|
|
|
2021-06-26 01:13:46 +00:00
|
|
|
for (java.awt.Component c : BytecodeViewer.viewer.workPane.getLoadedViewers())
|
|
|
|
{
|
|
|
|
if (c instanceof ClassViewer)
|
|
|
|
{
|
2018-01-31 15:41:24 +00:00
|
|
|
ClassViewer cv = (ClassViewer) c;
|
2021-06-26 01:13:46 +00:00
|
|
|
|
2021-07-05 02:07:34 +00:00
|
|
|
if(noErrors && !cv.resourceViewPanel1.compile())
|
|
|
|
noErrors = false;
|
|
|
|
if(noErrors && !cv.resourceViewPanel2.compile())
|
|
|
|
noErrors = false;
|
|
|
|
if(noErrors && !cv.resourceViewPanel3.compile())
|
|
|
|
noErrors = false;
|
|
|
|
|
2021-07-06 00:06:05 +00:00
|
|
|
if(cv.resourceViewPanel1.textArea != null && cv.resourceViewPanel1.textArea.isEditable())
|
2018-01-31 15:41:24 +00:00
|
|
|
actuallyTried = true;
|
2021-07-06 00:06:05 +00:00
|
|
|
if(cv.resourceViewPanel2.textArea != null && cv.resourceViewPanel2.textArea.isEditable())
|
2018-01-31 15:41:24 +00:00
|
|
|
actuallyTried = true;
|
2021-07-06 00:06:05 +00:00
|
|
|
if(cv.resourceViewPanel3.textArea != null && cv.resourceViewPanel3.textArea.isEditable())
|
2018-01-31 15:41:24 +00:00
|
|
|
actuallyTried = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (message)
|
2021-07-05 02:07:34 +00:00
|
|
|
{
|
2018-01-31 15:41:24 +00:00
|
|
|
if (actuallyTried)
|
2021-07-05 02:07:34 +00:00
|
|
|
{
|
2021-07-05 03:37:01 +00:00
|
|
|
if(noErrors && successAlert)
|
2021-07-05 02:07:34 +00:00
|
|
|
BytecodeViewer.showMessage("Compiled Successfully.");
|
|
|
|
}
|
2018-01-31 15:41:24 +00:00
|
|
|
else
|
2021-07-05 02:07:34 +00:00
|
|
|
{
|
2018-01-31 15:41:24 +00:00
|
|
|
BytecodeViewer.showMessage("You have no editable panes opened, make one editable and try again.");
|
2021-07-05 02:07:34 +00:00
|
|
|
}
|
|
|
|
}
|
2021-07-06 00:06:05 +00:00
|
|
|
|
2021-06-21 23:37:55 +00:00
|
|
|
BytecodeViewer.viewer.updateBusyStatus(false);
|
2018-01-31 15:41:24 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Opens a file, optional if it should append to the recent files menu
|
|
|
|
*
|
|
|
|
* @param files the file(s) you wish to open
|
|
|
|
* @param recentFiles if it should append to the recent files menu
|
|
|
|
*/
|
|
|
|
public static void openFiles(final File[] files, boolean recentFiles) {
|
|
|
|
if (recentFiles)
|
2021-07-01 09:06:12 +00:00
|
|
|
{
|
2018-01-31 15:41:24 +00:00
|
|
|
for (File f : files)
|
|
|
|
if (f.exists())
|
2021-06-29 09:41:29 +00:00
|
|
|
Settings.addRecentFile(f);
|
2021-07-01 09:06:12 +00:00
|
|
|
|
|
|
|
SettingsSerializer.saveSettingsAsync();
|
|
|
|
}
|
2018-01-31 15:41:24 +00:00
|
|
|
|
2021-06-21 23:37:55 +00:00
|
|
|
BytecodeViewer.viewer.updateBusyStatus(true);
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.needsReDump = true;
|
2021-07-01 09:48:10 +00:00
|
|
|
Thread t = new Thread(new ImportResource(files), "Import Resource");
|
2018-01-31 15:41:24 +00:00
|
|
|
t.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts the specified plugin
|
|
|
|
*
|
|
|
|
* @param file the file of the plugin
|
|
|
|
*/
|
|
|
|
public static void startPlugin(File file) {
|
|
|
|
if (!file.exists())
|
2021-07-05 04:24:19 +00:00
|
|
|
{
|
|
|
|
BytecodeViewer.showMessage("The plugin file " + file.getAbsolutePath() + " could not be found.");
|
|
|
|
Settings.removeRecentPlugin(file);
|
2018-01-31 15:41:24 +00:00
|
|
|
return;
|
2021-07-05 04:24:19 +00:00
|
|
|
}
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
PluginManager.runPlugin(file);
|
|
|
|
} catch (Throwable e) {
|
|
|
|
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
|
|
|
|
}
|
|
|
|
addRecentPlugin(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Send a message to alert the user
|
|
|
|
*
|
|
|
|
* @param message the message you need to send
|
|
|
|
*/
|
|
|
|
public static void showMessage(String message) {
|
2021-07-05 03:34:37 +00:00
|
|
|
BetterJOptionPane.showMessageDialog(viewer, message);
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resets the workspace with optional user input required
|
|
|
|
*
|
|
|
|
* @param ask if should require user input or not
|
|
|
|
*/
|
2021-06-26 18:10:55 +00:00
|
|
|
public static void resetWorkSpace(boolean ask)
|
|
|
|
{
|
|
|
|
if (ask)
|
|
|
|
{
|
|
|
|
MultipleChoiceDialogue dialogue = new MultipleChoiceDialogue("Bytecode Viewer - Reset Workspace",
|
|
|
|
"Are you sure you want to reset the workspace?" +
|
|
|
|
"\n\rIt will also reset your file navigator and search.",
|
|
|
|
new String[]{"Yes", "No"});
|
|
|
|
|
|
|
|
if (dialogue.promptChoice() != 0)
|
2019-04-17 06:45:15 +00:00
|
|
|
return;
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
2019-04-17 06:45:15 +00:00
|
|
|
|
|
|
|
files.clear();
|
|
|
|
LazyNameUtil.reset();
|
2021-06-21 22:45:00 +00:00
|
|
|
Objects.requireNonNull(MainViewerGUI.getComponent(ResourceListPane.class)).resetWorkspace();
|
2021-06-26 01:13:46 +00:00
|
|
|
Objects.requireNonNull(MainViewerGUI.getComponent(WorkPaneMainComponent.class)).resetWorkspace();
|
2021-06-21 22:45:00 +00:00
|
|
|
Objects.requireNonNull(MainViewerGUI.getComponent(SearchBoxPane.class)).resetWorkspace();
|
2019-04-17 06:45:15 +00:00
|
|
|
the.bytecode.club.bytecodeviewer.api.BytecodeViewer.getClassNodeLoader().clear();
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
2021-07-01 09:06:12 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Clears the temp directory
|
|
|
|
*/
|
|
|
|
public static void cleanupAsync()
|
|
|
|
{
|
2021-07-01 09:48:10 +00:00
|
|
|
Thread cleanupThread = new Thread(BytecodeViewer::cleanup, "Cleanup");
|
2021-07-01 09:06:12 +00:00
|
|
|
cleanupThread.start();
|
|
|
|
}
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Clears the temp directory
|
|
|
|
*/
|
2021-07-01 09:06:12 +00:00
|
|
|
public static void cleanup()
|
|
|
|
{
|
2021-04-12 22:31:22 +00:00
|
|
|
File tempF = new File(tempDirectory);
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
FileUtils.deleteDirectory(tempF);
|
2021-04-12 22:31:22 +00:00
|
|
|
} catch (Exception ignored) {
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (!tempF.exists()) // keep making dirs
|
|
|
|
tempF.mkdir();
|
|
|
|
}
|
2021-06-26 12:26:12 +00:00
|
|
|
|
|
|
|
public static void refreshAllTabTitles()
|
|
|
|
{
|
|
|
|
for(int i = 0; i < BytecodeViewer.viewer.workPane.tabs.getTabCount(); i++)
|
|
|
|
{
|
|
|
|
ResourceViewer viewer = ((TabbedPane) BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i)).resource;
|
|
|
|
viewer.refreshTitle();
|
|
|
|
}
|
|
|
|
}
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks the hotkeys
|
|
|
|
*
|
|
|
|
* @param e
|
|
|
|
*/
|
2018-01-31 15:03:53 +00:00
|
|
|
public static void checkHotKey(KeyEvent e) {
|
2021-06-21 11:13:11 +00:00
|
|
|
if (System.currentTimeMillis() - Configuration.lastHotKeyExecuted <= (4000))
|
2018-01-31 15:41:24 +00:00
|
|
|
return;
|
|
|
|
|
2021-07-01 23:08:56 +00:00
|
|
|
if ((e.getKeyCode() == KeyEvent.VK_O) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0))
|
|
|
|
{
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.lastHotKeyExecuted = System.currentTimeMillis();
|
2021-07-01 23:08:56 +00:00
|
|
|
|
|
|
|
final File file = DialogueUtils.fileChooser("Select File or Folder to open in BCV",
|
2021-06-26 12:38:58 +00:00
|
|
|
"APKs, DEX, Class Files or Zip/Jar/War Archives",
|
|
|
|
Constants.SUPPORTED_FILE_EXTENSIONS);
|
|
|
|
|
2021-07-01 23:08:56 +00:00
|
|
|
if(file == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
BytecodeViewer.viewer.updateBusyStatus(true);
|
|
|
|
BytecodeViewer.openFiles(new File[]{file}, true);
|
|
|
|
BytecodeViewer.viewer.updateBusyStatus(false);
|
2018-01-31 15:03:53 +00:00
|
|
|
} else if ((e.getKeyCode() == KeyEvent.VK_N) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.lastHotKeyExecuted = System.currentTimeMillis();
|
2018-01-31 15:41:24 +00:00
|
|
|
BytecodeViewer.resetWorkSpace(true);
|
2018-01-31 15:03:53 +00:00
|
|
|
} else if ((e.getKeyCode() == KeyEvent.VK_T) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.lastHotKeyExecuted = System.currentTimeMillis();
|
2021-07-05 03:37:01 +00:00
|
|
|
Thread t = new Thread(() -> BytecodeViewer.compile(true, false), "Compile");
|
2018-01-31 15:41:24 +00:00
|
|
|
t.start();
|
2018-01-31 15:03:53 +00:00
|
|
|
} else if ((e.getKeyCode() == KeyEvent.VK_R) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.lastHotKeyExecuted = System.currentTimeMillis();
|
2018-01-31 15:41:24 +00:00
|
|
|
if (BytecodeViewer.getLoadedClasses().isEmpty()) {
|
|
|
|
BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
new RunOptions().setVisible(true);
|
2018-01-31 15:03:53 +00:00
|
|
|
} else if ((e.getKeyCode() == KeyEvent.VK_S) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.lastHotKeyExecuted = System.currentTimeMillis();
|
2018-01-31 15:41:24 +00:00
|
|
|
|
|
|
|
if (BytecodeViewer.getLoadedClasses().isEmpty()) {
|
|
|
|
BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-01 09:48:10 +00:00
|
|
|
Thread resourceExport = new Thread(() ->
|
|
|
|
{
|
2021-07-03 19:29:31 +00:00
|
|
|
if (BytecodeViewer.autoCompileSuccessful())
|
2021-04-12 22:31:22 +00:00
|
|
|
return;
|
2021-06-26 12:38:58 +00:00
|
|
|
|
2021-07-01 21:54:10 +00:00
|
|
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
2021-06-26 12:38:58 +00:00
|
|
|
"Select Zip Export",
|
|
|
|
"Zip Archives",
|
|
|
|
"zip");
|
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
int returnVal = fc.showSaveDialog(viewer);
|
2021-06-26 15:56:39 +00:00
|
|
|
if (returnVal == JFileChooser.APPROVE_OPTION)
|
|
|
|
{
|
|
|
|
Configuration.lastDirectory = fc.getSelectedFile().getAbsolutePath();
|
2021-04-12 22:31:22 +00:00
|
|
|
File file = fc.getSelectedFile();
|
2021-07-01 21:54:10 +00:00
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
if (!file.getAbsolutePath().endsWith(".zip"))
|
|
|
|
file = new File(file.getAbsolutePath() + ".zip");
|
2021-07-01 21:54:10 +00:00
|
|
|
|
|
|
|
if (!DialogueUtils.canOverwriteFile(file))
|
|
|
|
return;
|
2018-01-31 15:41:24 +00:00
|
|
|
|
2021-04-12 22:31:22 +00:00
|
|
|
final File file2 = file;
|
2018-01-31 15:41:24 +00:00
|
|
|
|
2021-06-21 23:37:55 +00:00
|
|
|
BytecodeViewer.viewer.updateBusyStatus(true);
|
2021-07-01 09:48:10 +00:00
|
|
|
Thread jarExport = new Thread(() -> {
|
2021-04-12 22:31:22 +00:00
|
|
|
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(),
|
|
|
|
file2.getAbsolutePath());
|
2021-06-21 23:37:55 +00:00
|
|
|
BytecodeViewer.viewer.updateBusyStatus(false);
|
2021-07-01 09:48:10 +00:00
|
|
|
}, "Jar Export");
|
|
|
|
jarExport.start();
|
2018-01-31 15:41:24 +00:00
|
|
|
}
|
2021-07-01 09:48:10 +00:00
|
|
|
}, "Resource Export");
|
|
|
|
resourceExport.start();
|
|
|
|
}
|
|
|
|
else if ((e.getKeyCode() == KeyEvent.VK_W) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0))
|
|
|
|
{
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.lastHotKeyExecuted = System.currentTimeMillis();
|
2018-01-31 15:41:24 +00:00
|
|
|
if (viewer.workPane.getCurrentViewer() != null)
|
|
|
|
viewer.workPane.tabs.remove(viewer.workPane.getCurrentViewer());
|
2018-01-31 15:03:53 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-13 03:42:04 +00:00
|
|
|
|
2021-06-26 12:38:58 +00:00
|
|
|
public static File[] dumpTempFile(FileContainer container)
|
|
|
|
{
|
2019-04-17 06:45:15 +00:00
|
|
|
File[] files = new File[2];
|
2021-06-26 12:38:58 +00:00
|
|
|
|
2019-04-17 06:45:15 +00:00
|
|
|
//currently won't optimize if you've got two containers with the same name, will need to add this later
|
2021-04-12 20:19:12 +00:00
|
|
|
if (!LazyNameUtil.SAME_NAME_JAR_WORKSPACE) {
|
2021-06-21 11:13:11 +00:00
|
|
|
if (Configuration.krakatauTempJar != null && !Configuration.krakatauTempJar.exists()) {
|
|
|
|
Configuration.needsReDump = true;
|
2019-04-17 06:45:15 +00:00
|
|
|
}
|
2019-04-13 03:42:04 +00:00
|
|
|
|
2021-06-21 11:13:11 +00:00
|
|
|
if (Configuration.needsReDump && Configuration.krakatauTempJar != null) {
|
|
|
|
Configuration.krakatauTempDir = null;
|
|
|
|
Configuration.krakatauTempJar = null;
|
2019-04-17 06:45:15 +00:00
|
|
|
}
|
2019-04-13 19:30:03 +00:00
|
|
|
|
2019-04-17 06:45:15 +00:00
|
|
|
boolean passes = false;
|
|
|
|
|
2021-06-21 14:55:18 +00:00
|
|
|
if (BytecodeViewer.viewer.viewPane1.getGroup().isSelected(BytecodeViewer.viewer.viewPane1.getKrakatau().getJava().getModel()))
|
2019-04-17 06:45:15 +00:00
|
|
|
passes = true;
|
2021-06-21 14:55:18 +00:00
|
|
|
else if (BytecodeViewer.viewer.viewPane1.getGroup().isSelected(BytecodeViewer.viewer.viewPane1.getKrakatau().getBytecode().getModel()))
|
2019-04-17 06:45:15 +00:00
|
|
|
passes = true;
|
2021-06-21 14:55:18 +00:00
|
|
|
else if (BytecodeViewer.viewer.viewPane2.getGroup().isSelected(BytecodeViewer.viewer.viewPane2.getKrakatau().getJava().getModel()))
|
2019-04-17 06:45:15 +00:00
|
|
|
passes = true;
|
2021-06-21 14:55:18 +00:00
|
|
|
else if (BytecodeViewer.viewer.viewPane2.getGroup().isSelected(BytecodeViewer.viewer.viewPane2.getKrakatau().getBytecode().getModel()))
|
2019-04-17 06:45:15 +00:00
|
|
|
passes = true;
|
2021-06-21 14:55:18 +00:00
|
|
|
else if (BytecodeViewer.viewer.viewPane3.getGroup().isSelected(BytecodeViewer.viewer.viewPane3.getKrakatau().getJava().getModel()))
|
2019-04-17 06:45:15 +00:00
|
|
|
passes = true;
|
2021-06-21 14:55:18 +00:00
|
|
|
else if (BytecodeViewer.viewer.viewPane3.getGroup().isSelected(BytecodeViewer.viewer.viewPane3.getKrakatau().getBytecode().getModel()))
|
2019-04-17 06:45:15 +00:00
|
|
|
passes = true;
|
|
|
|
|
2021-06-21 11:13:11 +00:00
|
|
|
if (Configuration.krakatauTempJar != null || !passes) {
|
|
|
|
files[0] = Configuration.krakatauTempJar;
|
|
|
|
files[1] = Configuration.krakatauTempDir;
|
2019-04-17 06:45:15 +00:00
|
|
|
return files;
|
|
|
|
}
|
2019-04-13 03:42:04 +00:00
|
|
|
}
|
2021-06-21 11:13:11 +00:00
|
|
|
|
|
|
|
Configuration.currentlyDumping = true;
|
|
|
|
Configuration.needsReDump = false;
|
|
|
|
Configuration.krakatauTempDir = new File(tempDirectory + fs + MiscUtils.randomString(32) + fs);
|
|
|
|
Configuration.krakatauTempDir.mkdir();
|
|
|
|
Configuration.krakatauTempJar = new File(tempDirectory + fs + "temp" + MiscUtils.randomString(32) + ".jar");
|
2021-04-12 22:31:22 +00:00
|
|
|
//krakatauTempJar = new File(BytecodeViewer.tempDirectory + BytecodeViewer.fs + "temp" + MiscUtils
|
|
|
|
// .randomString(32) + ".jar."+container.name);
|
2021-06-21 11:13:11 +00:00
|
|
|
JarUtils.saveAsJarClassesOnly(container.classes, Configuration.krakatauTempJar.getAbsolutePath());
|
|
|
|
Configuration.currentlyDumping = false;
|
2021-04-12 22:31:22 +00:00
|
|
|
|
2021-06-21 11:13:11 +00:00
|
|
|
files[0] = Configuration.krakatauTempJar;
|
|
|
|
files[1] = Configuration.krakatauTempDir;
|
2019-04-17 06:45:15 +00:00
|
|
|
return files;
|
2019-04-13 03:42:04 +00:00
|
|
|
}
|
|
|
|
|
2021-04-12 20:19:12 +00:00
|
|
|
public synchronized static void rtCheck() {
|
2021-06-21 11:13:11 +00:00
|
|
|
if (Configuration.rt.isEmpty()) {
|
2021-04-12 20:19:12 +00:00
|
|
|
if (RT_JAR.exists()) {
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.rt = RT_JAR.getAbsolutePath();
|
2021-04-12 20:19:12 +00:00
|
|
|
} else if (RT_JAR_DUMPED.exists()) {
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.rt = RT_JAR_DUMPED.getAbsolutePath();
|
2021-04-12 20:19:12 +00:00
|
|
|
} else {
|
|
|
|
try {
|
2019-06-01 01:04:07 +00:00
|
|
|
JRTExtractor.extractRT(RT_JAR_DUMPED.getAbsolutePath());
|
2021-06-21 11:13:11 +00:00
|
|
|
Configuration.rt = RT_JAR_DUMPED.getAbsolutePath();
|
2021-04-12 20:19:12 +00:00
|
|
|
} catch (Throwable t) {
|
2019-06-01 01:04:07 +00:00
|
|
|
t.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
2019-04-13 03:42:04 +00:00
|
|
|
}
|
|
|
|
}
|
2018-01-31 15:03:53 +00:00
|
|
|
}
|