Code Style Update
This commit is contained in:
parent
c85a8a21f3
commit
fda1ecab66
|
@ -1,14 +1,11 @@
|
|||
package me.konloch.kontainer.io;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.util.EncodeUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import the.bytecode.club.bytecodeviewer.util.EncodeUtils;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Used to load from the disk, optional caching
|
||||
|
@ -16,7 +13,8 @@ import the.bytecode.club.bytecodeviewer.util.EncodeUtils;
|
|||
* @author Konloch
|
||||
*/
|
||||
|
||||
public class DiskReader {
|
||||
public class DiskReader
|
||||
{
|
||||
|
||||
public static Random random = new Random();
|
||||
public static Map<String, List<String>> map = new HashMap<>();
|
||||
|
@ -24,17 +22,19 @@ public class DiskReader {
|
|||
/**
|
||||
* Used to load from file, allows caching
|
||||
*/
|
||||
public synchronized static List<String> loadArrayList(String fileName,
|
||||
boolean cache) {
|
||||
public synchronized static List<String> loadArrayList(String fileName, boolean cache)
|
||||
{
|
||||
List<String> array = new ArrayList<>();
|
||||
if (!map.containsKey(fileName)) {
|
||||
try {
|
||||
if (!map.containsKey(fileName))
|
||||
{
|
||||
try
|
||||
{
|
||||
File file = new File(fileName);
|
||||
if (!file.exists()) // doesn't exist, return empty
|
||||
return array;
|
||||
|
||||
try (FileReader fr = new FileReader(file);
|
||||
BufferedReader reader = new BufferedReader(fr)) {
|
||||
try (FileReader fr = new FileReader(file); BufferedReader reader = new BufferedReader(fr))
|
||||
{
|
||||
String add;
|
||||
|
||||
while ((add = reader.readLine()) != null)
|
||||
|
@ -44,10 +44,14 @@ public class DiskReader {
|
|||
|
||||
if (cache)
|
||||
map.put(fileName, array);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
array = map.get(fileName);
|
||||
}
|
||||
|
||||
|
@ -58,12 +62,14 @@ public class DiskReader {
|
|||
/**
|
||||
* Used to load from file
|
||||
*/
|
||||
public synchronized static String loadAsString(String fileName) throws Exception {
|
||||
public synchronized static String loadAsString(String fileName) throws Exception
|
||||
{
|
||||
StringBuilder s = new StringBuilder();
|
||||
|
||||
try (FileReader fr = new FileReader(fileName);
|
||||
BufferedReader reader = new BufferedReader(fr)) {
|
||||
for (String add = reader.readLine(); add != null; add = reader.readLine()) {
|
||||
try (FileReader fr = new FileReader(fileName); BufferedReader reader = new BufferedReader(fr))
|
||||
{
|
||||
for (String add = reader.readLine(); add != null; add = reader.readLine())
|
||||
{
|
||||
s.append(EncodeUtils.unicodeToString(add)).append(System.lineSeparator());
|
||||
}
|
||||
}
|
||||
|
@ -74,16 +80,17 @@ public class DiskReader {
|
|||
/**
|
||||
* Used to load a string via line number lineNumber = -1 means random.
|
||||
*/
|
||||
public static String loadString(String fileName, int lineNumber,
|
||||
boolean cache) throws Exception {
|
||||
public static String loadString(String fileName, int lineNumber, boolean cache) throws Exception
|
||||
{
|
||||
|
||||
List<String> array;
|
||||
if (!map.containsKey(fileName)) {
|
||||
if (!map.containsKey(fileName))
|
||||
{
|
||||
array = new ArrayList<>();
|
||||
File file = new File(fileName);
|
||||
|
||||
try (FileReader fr = new FileReader(file);
|
||||
BufferedReader reader = new BufferedReader(fr)) {
|
||||
try (FileReader fr = new FileReader(file); BufferedReader reader = new BufferedReader(fr))
|
||||
{
|
||||
String add;
|
||||
|
||||
while ((add = reader.readLine()) != null)
|
||||
|
@ -92,14 +99,18 @@ public class DiskReader {
|
|||
|
||||
if (cache)
|
||||
map.put(fileName, array);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
array = map.get(fileName);
|
||||
}
|
||||
|
||||
if (lineNumber == -1) {
|
||||
if (lineNumber == -1)
|
||||
{
|
||||
int size = array.size();
|
||||
return array.get(random.nextInt(size));
|
||||
} else
|
||||
}
|
||||
else
|
||||
return array.get(lineNumber);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
package me.konloch.kontainer.io;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
|
@ -13,7 +9,8 @@ import java.util.Arrays;
|
|||
* @author Konloch
|
||||
*/
|
||||
|
||||
public class DiskWriter {
|
||||
public class DiskWriter
|
||||
{
|
||||
|
||||
/**
|
||||
* Used to insert a difference string with preserving the file extension
|
||||
|
@ -23,13 +20,15 @@ public class DiskWriter {
|
|||
* @return The filename with the difference inserted and the file extension
|
||||
* preserved
|
||||
*/
|
||||
public static String insertFileName(String fileName, String difference) {
|
||||
public static String insertFileName(String fileName, String difference)
|
||||
{
|
||||
String[] babe = fileName.split("\\.");
|
||||
int count = 0;
|
||||
int math = babe.length;
|
||||
StringBuilder m = new StringBuilder();
|
||||
|
||||
for (String s2 : babe) {
|
||||
for (String s2 : babe)
|
||||
{
|
||||
m.append(s2);
|
||||
if (math - 2 == count)
|
||||
m.append(difference).append(".");
|
||||
|
@ -49,8 +48,8 @@ public class DiskWriter {
|
|||
* @param fileContents
|
||||
* @param debug
|
||||
*/
|
||||
public static synchronized void writeNewLine(String filename,
|
||||
byte[] fileContents, boolean debug) {
|
||||
public static synchronized void writeNewLine(String filename, byte[] fileContents, boolean debug)
|
||||
{
|
||||
new File(filename).getParentFile().mkdirs();
|
||||
String original = filename;
|
||||
int counter = 0;
|
||||
|
@ -59,20 +58,22 @@ public class DiskWriter {
|
|||
int failSafe = 0;
|
||||
while (!saved && failSafe++ <= 42069)
|
||||
{
|
||||
try (FileWriter fr = new FileWriter(filename, true);
|
||||
BufferedWriter bw = new BufferedWriter(fr);
|
||||
PrintWriter writer = new PrintWriter(bw)) {
|
||||
try (FileWriter fr = new FileWriter(filename, true); BufferedWriter bw = new BufferedWriter(fr); PrintWriter writer = new PrintWriter(bw))
|
||||
{
|
||||
writer.println(Arrays.toString(fileContents));
|
||||
if (debug)
|
||||
System.out.println("Saved " + filename + " to disk");
|
||||
saved = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (debug)
|
||||
System.out.println("Failed saving, trying to save as "
|
||||
+ filename);
|
||||
if (original.contains(".")) {
|
||||
System.out.println("Failed saving, trying to save as " + filename);
|
||||
if (original.contains("."))
|
||||
{
|
||||
filename = insertFileName(original, "" + counter);
|
||||
} else
|
||||
}
|
||||
else
|
||||
filename = original + counter;
|
||||
counter++;
|
||||
}
|
||||
|
@ -90,8 +91,8 @@ public class DiskWriter {
|
|||
/**
|
||||
* Writes a string to the file
|
||||
*/
|
||||
public static synchronized void writeNewLine(String filename,
|
||||
String lineToWrite, boolean debug) {
|
||||
public static synchronized void writeNewLine(String filename, String lineToWrite, boolean debug)
|
||||
{
|
||||
new File(filename).getParentFile().mkdirs();
|
||||
String original = filename;
|
||||
int counter = 0;
|
||||
|
@ -100,21 +101,22 @@ public class DiskWriter {
|
|||
int failSafe = 0;
|
||||
while (!saved && failSafe++ <= 42069)
|
||||
{
|
||||
try (FileWriter fr = new FileWriter(filename, true);
|
||||
BufferedWriter bw = new BufferedWriter(fr);
|
||||
PrintWriter writer = new PrintWriter(bw)) {
|
||||
try (FileWriter fr = new FileWriter(filename, true); BufferedWriter bw = new BufferedWriter(fr); PrintWriter writer = new PrintWriter(bw))
|
||||
{
|
||||
writer.println(lineToWrite);
|
||||
if (debug)
|
||||
System.out.println("Saved " + filename + ">" + lineToWrite
|
||||
+ " to disk");
|
||||
System.out.println("Saved " + filename + ">" + lineToWrite + " to disk");
|
||||
saved = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (debug)
|
||||
System.out.println("Failed saving, trying to save as "
|
||||
+ filename);
|
||||
if (original.contains(".")) {
|
||||
System.out.println("Failed saving, trying to save as " + filename);
|
||||
if (original.contains("."))
|
||||
{
|
||||
filename = insertFileName(original, "" + counter);
|
||||
} else
|
||||
}
|
||||
else
|
||||
filename = original + counter;
|
||||
counter++;
|
||||
}
|
||||
|
@ -129,8 +131,8 @@ public class DiskWriter {
|
|||
* @param fileContents
|
||||
* @param debug
|
||||
*/
|
||||
public static synchronized void replaceFileBytes(String filename,
|
||||
byte[] fileContents, boolean debug) {
|
||||
public static synchronized void replaceFileBytes(String filename, byte[] fileContents, boolean debug)
|
||||
{
|
||||
new File(filename).getParentFile().mkdirs();
|
||||
File f = new File(filename);
|
||||
if (f.exists())
|
||||
|
@ -150,13 +152,16 @@ public class DiskWriter {
|
|||
if (debug)
|
||||
System.out.println("Saved " + filename + " to disk");
|
||||
saved = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (debug)
|
||||
System.out.println("Failed saving, trying to save as "
|
||||
+ filename);
|
||||
if (original.contains(".")) {
|
||||
System.out.println("Failed saving, trying to save as " + filename);
|
||||
if (original.contains("."))
|
||||
{
|
||||
filename = insertFileName(original, "" + counter);
|
||||
} else
|
||||
}
|
||||
else
|
||||
filename = original + counter;
|
||||
counter++;
|
||||
}
|
||||
|
@ -171,8 +176,8 @@ public class DiskWriter {
|
|||
* @param lineToWrite
|
||||
* @param debug
|
||||
*/
|
||||
public static synchronized void replaceFile(String filename,
|
||||
String lineToWrite, boolean debug) {
|
||||
public static synchronized void replaceFile(String filename, String lineToWrite, boolean debug)
|
||||
{
|
||||
new File(filename).getParentFile().mkdirs();
|
||||
File f = new File(filename);
|
||||
if (f.exists())
|
||||
|
@ -184,21 +189,22 @@ public class DiskWriter {
|
|||
int failSafe = 0;
|
||||
while (!saved && failSafe++ <= 42069)
|
||||
{
|
||||
try (FileWriter fr = new FileWriter(filename, true);
|
||||
BufferedWriter bw = new BufferedWriter(fr);
|
||||
PrintWriter writer = new PrintWriter(bw)) {
|
||||
try (FileWriter fr = new FileWriter(filename, true); BufferedWriter bw = new BufferedWriter(fr); PrintWriter writer = new PrintWriter(bw))
|
||||
{
|
||||
writer.println(lineToWrite);
|
||||
if (debug)
|
||||
System.out.println("Saved " + filename + ">" + lineToWrite
|
||||
+ " to disk");
|
||||
System.out.println("Saved " + filename + ">" + lineToWrite + " to disk");
|
||||
saved = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (debug)
|
||||
System.out.println("Failed saving, trying to save as "
|
||||
+ filename + "_");
|
||||
if (original.contains(".")) {
|
||||
System.out.println("Failed saving, trying to save as " + filename + "_");
|
||||
if (original.contains("."))
|
||||
{
|
||||
filename = insertFileName(original, "" + counter);
|
||||
} else
|
||||
}
|
||||
else
|
||||
filename = original + counter;
|
||||
counter++;
|
||||
}
|
||||
|
|
|
@ -20,14 +20,6 @@ package the.bytecode.club.bytecodeviewer;
|
|||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import javax.swing.*;
|
||||
|
||||
import me.konloch.kontainer.io.DiskReader;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
@ -50,56 +42,55 @@ import the.bytecode.club.bytecodeviewer.plugin.PluginWriter;
|
|||
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
|
||||
import the.bytecode.club.bytecodeviewer.resources.importing.ImportResource;
|
||||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||
import the.bytecode.club.bytecodeviewer.util.BootCheck;
|
||||
import the.bytecode.club.bytecodeviewer.util.ClassFileUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.LazyNameUtil;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.PingBack;
|
||||
import the.bytecode.club.bytecodeviewer.util.SecurityMan;
|
||||
import the.bytecode.club.bytecodeviewer.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import static javax.swing.JOptionPane.QUESTION_MESSAGE;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.DEV_MODE;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.FAT_JAR;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.VERSION;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
* A lightweight Java Reverse Engineering suite, developed by Konloch - http://konloch.me
|
||||
*
|
||||
* <p>
|
||||
* All you have to do is add a jar or class file into the workspace,
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
* Are you a Java Reverse Engineer? Or maybe you want to learn Java Reverse Engineering?
|
||||
* Join The Bytecode Club, we're noob friendly, and censorship free.
|
||||
* http://the.bytecode.club
|
||||
*
|
||||
* <p>
|
||||
* TODO BUGS:
|
||||
* + View>Visual Settings>Show Class Methods
|
||||
* + Spam-clicking the refresh button will cause the swing thread to deadlock (Quickly opening resources used to also do this)
|
||||
* This is caused by the ctrlMouseWheelZoom code, a temporary patch is just removing it worst case
|
||||
*
|
||||
* <p>
|
||||
* TODO API BUGS:
|
||||
* + All of the plugins that modify code need to include BytecodeViewer.updateAllClassNodeByteArrays();
|
||||
* + All of the plugins that do any code changes should also include BytecodeViewer.refreshAllTabs();
|
||||
* + Anything using getLoadedClasses() needs to be replaced with the new API
|
||||
* + Anything using blindlySearchForClassNode() should instead search through the resource container search function
|
||||
* + BCV's classLoader should be destroyed each time a resource is added or removed
|
||||
*
|
||||
* <p>
|
||||
* TODO IN-PROGRESS:
|
||||
* + Resource Exporter/Save/Decompile As Zip needs to be rewritten
|
||||
* + Finish dragging code
|
||||
* + Finish right-click tab menu detection
|
||||
* + Fix hook inject for EZ-Injection
|
||||
*
|
||||
* <p>
|
||||
* TODO FEATURES:
|
||||
* + On refresh save scroll position
|
||||
* + Option to only compile currently viewed class (true by default)
|
||||
|
@ -111,7 +102,7 @@ import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
|||
* + Add decompile all as zip for CLI
|
||||
* + Console on the Main Viewer UI
|
||||
* + Font settings
|
||||
*
|
||||
* <p>
|
||||
* TODO IDEAS:
|
||||
* + App Bundle Support
|
||||
* + Add JEB decompiler optionally, requires them to add jeb library jar
|
||||
|
@ -138,7 +129,7 @@ public class BytecodeViewer
|
|||
public static MainViewerGUI viewer;
|
||||
|
||||
//All of the opened resources (Files/Classes/Etc)
|
||||
public static Map<String,ResourceContainer> resourceContainers = new LinkedHashMap<>();
|
||||
public static Map<String, ResourceContainer> resourceContainers = new LinkedHashMap<>();
|
||||
|
||||
//All of the created processes (Decompilers/etc)
|
||||
public static List<Process> createdProcesses = new ArrayList<>();
|
||||
|
@ -176,9 +167,12 @@ public class BytecodeViewer
|
|||
System.out.println(" - https://bytecodeviewer.com\r\nCreated by @Konloch - https://konloch.com\r\nPresented by https://the.bytecode.club");
|
||||
|
||||
// Set the security manager
|
||||
try {
|
||||
try
|
||||
{
|
||||
System.setSecurityManager(sm);
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
System.err.println("Cannot set security manager! Are you on Java 18+ and have not enabled support for it?");
|
||||
System.err.println("Because of this, you may be susceptible to some exploits!");
|
||||
System.err.println("Either deal with it or allow it using the -Djava.security.manager=allow parameter.");
|
||||
|
@ -303,9 +297,12 @@ public class BytecodeViewer
|
|||
resourceContainers.put(container.name, container);
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
viewer.resourcePane.addResourceContainer(container);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
@ -424,7 +421,7 @@ public class BytecodeViewer
|
|||
|
||||
/**
|
||||
* Gets all of the loaded classes as an array list
|
||||
*
|
||||
* <p>
|
||||
* TODO: remove this and replace it with:
|
||||
* BytecodeViewer.getResourceContainers().forEach(container -> {
|
||||
* execute(new ArrayList<>(container.resourceClasses.values()));
|
||||
|
@ -588,8 +585,7 @@ public class BytecodeViewer
|
|||
*/
|
||||
public static String showInput(String message, String title, String initialMessage)
|
||||
{
|
||||
return (String) ExtendedJOptionPane.showInputDialog(viewer, message, title,
|
||||
QUESTION_MESSAGE, null, null, initialMessage);
|
||||
return (String) ExtendedJOptionPane.showInputDialog(viewer, message, title, QUESTION_MESSAGE, null, null, initialMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -665,7 +661,7 @@ public class BytecodeViewer
|
|||
*/
|
||||
public static void refreshAllTabTitles()
|
||||
{
|
||||
for(int i = 0; i < BytecodeViewer.viewer.workPane.tabs.getTabCount(); i++)
|
||||
for (int i = 0; i < BytecodeViewer.viewer.workPane.tabs.getTabCount(); i++)
|
||||
{
|
||||
//ResourceViewer viewer = ((TabbedPane) BytecodeViewer.viewer.workPane.tabs.getTabComponentAt(i)).resource;
|
||||
//viewer.refreshTitle();
|
||||
|
@ -678,7 +674,7 @@ public class BytecodeViewer
|
|||
*/
|
||||
public static void refreshAllTabs()
|
||||
{
|
||||
new Thread(()->
|
||||
new Thread(() ->
|
||||
{
|
||||
updateBusyStatus(true);
|
||||
for (int i = 0; i < BytecodeViewer.viewer.workPane.tabs.getTabCount(); i++)
|
||||
|
@ -699,9 +695,7 @@ public class BytecodeViewer
|
|||
{
|
||||
if (ask)
|
||||
{
|
||||
MultipleChoiceDialog dialog = new MultipleChoiceDialog(TranslatedStrings.RESET_TITLE.toString(),
|
||||
TranslatedStrings.RESET_CONFIRM.toString(),
|
||||
new String[]{TranslatedStrings.YES.toString(), TranslatedStrings.NO.toString()});
|
||||
MultipleChoiceDialog dialog = new MultipleChoiceDialog(TranslatedStrings.RESET_TITLE.toString(), TranslatedStrings.RESET_CONFIRM.toString(), new String[]{TranslatedStrings.YES.toString(), TranslatedStrings.NO.toString()});
|
||||
|
||||
if (dialog.promptChoice() != 0)
|
||||
return;
|
||||
|
@ -740,9 +734,13 @@ public class BytecodeViewer
|
|||
{
|
||||
File tempF = new File(tempDirectory);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
FileUtils.deleteDirectory(tempF);
|
||||
} catch (Exception ignored) { }
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
}
|
||||
|
||||
while (!tempF.exists()) // keep making dirs
|
||||
tempF.mkdir();
|
||||
|
@ -751,31 +749,36 @@ public class BytecodeViewer
|
|||
/**
|
||||
* because Smali and Baksmali System.exit if it failed
|
||||
*/
|
||||
public static void exit(int i) { }
|
||||
public static void exit(int i)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all UI components fonts.
|
||||
*
|
||||
* @param font The font to change everything to.
|
||||
* @implNote {@link SearchableRSyntaxTextArea} and {@link SearchableJTextArea}
|
||||
* do not update until "Refresh" button is clicked.
|
||||
*
|
||||
* @param font The font to change everything to.
|
||||
*/
|
||||
public static void updateAllFonts(Font font) {
|
||||
public static void updateAllFonts(Font font)
|
||||
{
|
||||
Enumeration<Object> enumeration = UIManager.getDefaults().keys();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
while (enumeration.hasMoreElements())
|
||||
{
|
||||
Object key = enumeration.nextElement();
|
||||
Object value = UIManager.get (key);
|
||||
Object value = UIManager.get(key);
|
||||
if (value instanceof Font)
|
||||
UIManager.put (key, font);
|
||||
UIManager.put(key, font);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all swing components.
|
||||
*/
|
||||
public static void updateUI() {
|
||||
for (Window w : Window.getWindows()) {
|
||||
public static void updateUI()
|
||||
{
|
||||
for (Window w : Window.getWindows())
|
||||
{
|
||||
SwingUtilities.updateComponentTreeUI(w);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer;
|
||||
|
||||
import java.io.File;
|
||||
import me.konloch.kontainer.io.DiskWriter;
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.CommandLineParser;
|
||||
|
@ -31,9 +30,9 @@ import the.bytecode.club.bytecodeviewer.translation.Language;
|
|||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.VERSION;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
||||
import java.io.File;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
* Used to allow BCV to be integrated as CLI instead of GUI.
|
||||
|
@ -41,7 +40,8 @@ import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
|||
* @author Konloch
|
||||
*/
|
||||
|
||||
public class CommandLineInput {
|
||||
public class CommandLineInput
|
||||
{
|
||||
|
||||
private static final Options options = new Options();
|
||||
private static final CommandLineParser parser = new DefaultParser();
|
||||
|
@ -51,7 +51,8 @@ public class CommandLineInput {
|
|||
public static int GUI = 0;
|
||||
public static int CLI = 1;
|
||||
|
||||
static {
|
||||
static
|
||||
{
|
||||
options.addOption("help", false, "prints the help menu.");
|
||||
options.addOption("list", false, "lists all the available decompilers for BCV " + VERSION + ".");
|
||||
options.addOption("decompiler", true, "sets the decompiler, procyon by default.");
|
||||
|
@ -61,38 +62,36 @@ public class CommandLineInput {
|
|||
options.addOption("nowait", true, "won't wait the 5 seconds to allow the user to read the CLI.");
|
||||
}
|
||||
|
||||
public static boolean containsCommand(String[] args) {
|
||||
public static boolean containsCommand(String[] args)
|
||||
{
|
||||
if (args == null || args.length == 0)
|
||||
return false;
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
CommandLine cmd = parser.parse(options, args);
|
||||
if (
|
||||
cmd.hasOption("help") ||
|
||||
cmd.hasOption("clean") ||
|
||||
cmd.hasOption("english") ||
|
||||
cmd.hasOption("list") ||
|
||||
cmd.hasOption("decompiler") ||
|
||||
cmd.hasOption("i") ||
|
||||
cmd.hasOption("o") ||
|
||||
cmd.hasOption("t") ||
|
||||
cmd.hasOption("nowait")
|
||||
) {
|
||||
if (cmd.hasOption("help") || cmd.hasOption("clean") || cmd.hasOption("english") || cmd.hasOption("list") || cmd.hasOption("decompiler") || cmd.hasOption("i") || cmd.hasOption("o") || cmd.hasOption("t") || cmd.hasOption("nowait"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int parseCommandLine(String[] args) {
|
||||
public static int parseCommandLine(String[] args)
|
||||
{
|
||||
if (!containsCommand(args))
|
||||
return GUI;
|
||||
try {
|
||||
try
|
||||
{
|
||||
CommandLine cmd = parser.parse(options, args);
|
||||
if (cmd.hasOption("list")) {
|
||||
if (cmd.hasOption("list"))
|
||||
{
|
||||
System.out.println("Procyon");
|
||||
System.out.println("CFR");
|
||||
System.out.println("FernFlower");
|
||||
|
@ -102,38 +101,38 @@ public class CommandLineInput {
|
|||
System.out.println("Smali");
|
||||
System.out.println("ASMifier");
|
||||
return STOP;
|
||||
} else if (cmd.hasOption("clean")) {
|
||||
}
|
||||
else if (cmd.hasOption("clean"))
|
||||
{
|
||||
new File(Constants.getBCVDirectory()).delete();
|
||||
if(cmd.getOptionValue("i") == null && cmd.getOptionValue("o") == null
|
||||
&& cmd.getOptionValue("t") == null)
|
||||
if (cmd.getOptionValue("i") == null && cmd.getOptionValue("o") == null && cmd.getOptionValue("t") == null)
|
||||
return GUI;
|
||||
} else if (cmd.hasOption("english")) {
|
||||
}
|
||||
else if (cmd.hasOption("english"))
|
||||
{
|
||||
Configuration.language = Language.ENGLISH;
|
||||
return GUI;
|
||||
} else if (cmd.hasOption("help")) {
|
||||
for (String s : new String[]{
|
||||
"-help Displays the help menu",
|
||||
"-clean Deletes the BCV directory",
|
||||
"-english Forces English language translations",
|
||||
"-list Displays the available decompilers",
|
||||
"-decompiler <decompiler> Selects the decompiler, procyon by default",
|
||||
"-i <input file> Selects the input file",
|
||||
"-o <output file> Selects the output file",
|
||||
"-t <target classname> Must either be the fully qualified classname or \"all\" to decompile all as zip",
|
||||
"-nowait Doesn't wait for the user to read the CLI messages"
|
||||
})
|
||||
}
|
||||
else if (cmd.hasOption("help"))
|
||||
{
|
||||
for (String s : new String[]{"-help Displays the help menu", "-clean Deletes the BCV directory", "-english Forces English language translations", "-list Displays the available decompilers", "-decompiler <decompiler> Selects the decompiler, procyon by default", "-i <input file> Selects the input file", "-o <output file> Selects the output file", "-t <target classname> Must either be the fully qualified classname or \"all\" to decompile all as zip", "-nowait Doesn't wait for the user to read the CLI messages"})
|
||||
System.out.println(s);
|
||||
return STOP;
|
||||
} else {
|
||||
if (cmd.getOptionValue("i") == null) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cmd.getOptionValue("i") == null)
|
||||
{
|
||||
System.err.println("Set the input with -i");
|
||||
return STOP;
|
||||
}
|
||||
if (cmd.getOptionValue("o") == null) {
|
||||
if (cmd.getOptionValue("o") == null)
|
||||
{
|
||||
System.err.println("Set the output with -o");
|
||||
return STOP;
|
||||
}
|
||||
if (cmd.getOptionValue("t") == null) {
|
||||
if (cmd.getOptionValue("t") == null)
|
||||
{
|
||||
System.err.println("Set the target with -t");
|
||||
return STOP;
|
||||
}
|
||||
|
@ -142,12 +141,14 @@ public class CommandLineInput {
|
|||
File output = new File(cmd.getOptionValue("o"));
|
||||
String decompiler = cmd.getOptionValue("decompiler");
|
||||
|
||||
if (!input.exists()) {
|
||||
if (!input.exists())
|
||||
{
|
||||
System.err.println(input.getAbsolutePath() + " does not exist.");
|
||||
return STOP;
|
||||
}
|
||||
|
||||
if (output.exists()) {
|
||||
if (output.exists())
|
||||
{
|
||||
System.err.println("WARNING: Deleted old " + output.getAbsolutePath() + ".");
|
||||
output.delete();
|
||||
}
|
||||
|
@ -156,19 +157,9 @@ public class CommandLineInput {
|
|||
//if its zip/jar/apk/dex attempt unzip as whole zip
|
||||
//if its just class allow any
|
||||
|
||||
if (
|
||||
decompiler != null &&
|
||||
!decompiler.equalsIgnoreCase("procyon") &&
|
||||
!decompiler.equalsIgnoreCase("cfr") &&
|
||||
!decompiler.equalsIgnoreCase("fernflower") &&
|
||||
!decompiler.equalsIgnoreCase("krakatau") &&
|
||||
!decompiler.equalsIgnoreCase("krakatau-bytecode") &&
|
||||
!decompiler.equalsIgnoreCase("jd-gui") &&
|
||||
!decompiler.equalsIgnoreCase("smali") &&
|
||||
!decompiler.equalsIgnoreCase("asmifier")
|
||||
) {
|
||||
System.out.println("Error, no decompiler called '" + decompiler + "' found. Type -list"
|
||||
+ " for the list");
|
||||
if (decompiler != null && !decompiler.equalsIgnoreCase("procyon") && !decompiler.equalsIgnoreCase("cfr") && !decompiler.equalsIgnoreCase("fernflower") && !decompiler.equalsIgnoreCase("krakatau") && !decompiler.equalsIgnoreCase("krakatau-bytecode") && !decompiler.equalsIgnoreCase("jd-gui") && !decompiler.equalsIgnoreCase("smali") && !decompiler.equalsIgnoreCase("asmifier"))
|
||||
{
|
||||
System.out.println("Error, no decompiler called '" + decompiler + "' found. Type -list" + " for the list");
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,24 +168,28 @@ public class CommandLineInput {
|
|||
|
||||
return CLI;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
|
||||
return GUI;
|
||||
}
|
||||
|
||||
public static void executeCommandLine(String[] args) {
|
||||
try {
|
||||
public static void executeCommandLine(String[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandLine cmd = parser.parse(options, args);
|
||||
String decompiler = cmd.getOptionValue("decompiler");
|
||||
File input = new File(cmd.getOptionValue("i"));
|
||||
File output = new File(cmd.getOptionValue("o"));
|
||||
String target = cmd.getOptionValue("t");
|
||||
|
||||
if (cmd.getOptionValue("decompiler") == null) {
|
||||
System.out.println("You can define another decompiler by appending -decompiler \"name\", by default "
|
||||
+ "procyon has been set.");
|
||||
if (cmd.getOptionValue("decompiler") == null)
|
||||
{
|
||||
System.out.println("You can define another decompiler by appending -decompiler \"name\", by default " + "procyon has been set.");
|
||||
decompiler = "procyon";
|
||||
}
|
||||
|
||||
|
@ -202,178 +197,247 @@ public class CommandLineInput {
|
|||
//if its zip/jar/apk/dex attempt unzip as whole zip
|
||||
//if its just class allow any
|
||||
|
||||
File tempZip =
|
||||
new File(tempDirectory + fs + "temp_" + MiscUtils.getRandomizedName() + ".jar");
|
||||
File tempZip = new File(tempDirectory + fs + "temp_" + MiscUtils.getRandomizedName() + ".jar");
|
||||
if (tempZip.exists())
|
||||
tempZip.delete();
|
||||
|
||||
JarUtils.saveAsJarClassesOnly(BytecodeViewer.getLoadedClasses(), tempZip.getAbsolutePath());
|
||||
|
||||
if (decompiler.equalsIgnoreCase("procyon")) {
|
||||
if (decompiler.equalsIgnoreCase("procyon"))
|
||||
{
|
||||
System.out.println("Decompiling " + input.getAbsolutePath() + " with Procyon");
|
||||
BytecodeViewer.openFiles(new File[]{input}, false);
|
||||
|
||||
Thread.sleep(5 * 1000);
|
||||
|
||||
if (target.equalsIgnoreCase("all")) {
|
||||
if (target.equalsIgnoreCase("all"))
|
||||
{
|
||||
Decompiler.PROCYON_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||
final ClassWriter cw = accept(cn);
|
||||
String contents = Decompiler.PROCYON_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
} else if (decompiler.equalsIgnoreCase("cfr")) {
|
||||
}
|
||||
else if (decompiler.equalsIgnoreCase("cfr"))
|
||||
{
|
||||
System.out.println("Decompiling " + input.getAbsolutePath() + " with CFR");
|
||||
BytecodeViewer.openFiles(new File[]{input}, false);
|
||||
|
||||
Thread.sleep(5 * 1000);
|
||||
|
||||
if (target.equalsIgnoreCase("all")) {
|
||||
if (target.equalsIgnoreCase("all"))
|
||||
{
|
||||
Decompiler.CFR_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||
final ClassWriter cw = accept(cn);
|
||||
String contents = Decompiler.CFR_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
} else if (decompiler.equalsIgnoreCase("fernflower")) {
|
||||
}
|
||||
else if (decompiler.equalsIgnoreCase("fernflower"))
|
||||
{
|
||||
System.out.println("Decompiling " + input.getAbsolutePath() + " with FernFlower");
|
||||
BytecodeViewer.openFiles(new File[]{input}, false);
|
||||
|
||||
Thread.sleep(5 * 1000);
|
||||
|
||||
if (target.equalsIgnoreCase("all")) {
|
||||
if (target.equalsIgnoreCase("all"))
|
||||
{
|
||||
Decompiler.FERNFLOWER_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||
final ClassWriter cw = accept(cn);
|
||||
String contents = Decompiler.FERNFLOWER_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
} else if (decompiler.equalsIgnoreCase("krakatau")) {
|
||||
}
|
||||
else if (decompiler.equalsIgnoreCase("krakatau"))
|
||||
{
|
||||
System.out.println("Decompiling " + input.getAbsolutePath() + " with Krakatau");
|
||||
BytecodeViewer.openFiles(new File[]{input}, false);
|
||||
|
||||
Thread.sleep(5 * 1000);
|
||||
|
||||
if (target.equalsIgnoreCase("all")) {
|
||||
if (target.equalsIgnoreCase("all"))
|
||||
{
|
||||
Decompiler.KRAKATAU_DECOMPILER.getDecompiler().decompileToZip(tempZip.getAbsolutePath(), output.getAbsolutePath());
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||
final ClassWriter cw = accept(cn);
|
||||
String contents = Decompiler.KRAKATAU_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
} else if (decompiler.equalsIgnoreCase("krakatau-bytecode")) {
|
||||
}
|
||||
else if (decompiler.equalsIgnoreCase("krakatau-bytecode"))
|
||||
{
|
||||
System.out.println("Decompiling " + input.getAbsolutePath() + " with Krakatau-Bytecode");
|
||||
BytecodeViewer.openFiles(new File[]{input}, false);
|
||||
|
||||
Thread.sleep(5 * 1000);
|
||||
|
||||
if (target.equalsIgnoreCase("all")) {
|
||||
if (target.equalsIgnoreCase("all"))
|
||||
{
|
||||
System.out.println("Coming soon.");
|
||||
//Decompiler.krakatauDA.decompileToZip(output.getAbsolutePath());
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||
final ClassWriter cw = accept(cn);
|
||||
String contents = Decompiler.KRAKATAU_DISASSEMBLER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
} else if (decompiler.equalsIgnoreCase("jd-gui")) {
|
||||
}
|
||||
else if (decompiler.equalsIgnoreCase("jd-gui"))
|
||||
{
|
||||
System.out.println("Decompiling " + input.getAbsolutePath() + " with JD-GUI");
|
||||
BytecodeViewer.openFiles(new File[]{input}, false);
|
||||
|
||||
Thread.sleep(5 * 1000);
|
||||
|
||||
if (target.equalsIgnoreCase("all")) {
|
||||
if (target.equalsIgnoreCase("all"))
|
||||
{
|
||||
System.out.println("Coming soon.");
|
||||
//Decompiler.jdgui.decompileToZip(output.getAbsolutePath());
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||
final ClassWriter cw = accept(cn);
|
||||
String contents = Decompiler.JD_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
} else if (decompiler.equalsIgnoreCase("smali")) {
|
||||
}
|
||||
else if (decompiler.equalsIgnoreCase("smali"))
|
||||
{
|
||||
System.out.println("Decompiling " + input.getAbsolutePath() + " with Smali");
|
||||
BytecodeViewer.openFiles(new File[]{input}, false);
|
||||
|
||||
Thread.sleep(5 * 1000);
|
||||
|
||||
if (target.equalsIgnoreCase("all")) {
|
||||
if (target.equalsIgnoreCase("all"))
|
||||
{
|
||||
System.out.println("Coming soon.");
|
||||
//Decompiler.smali.decompileToZip(output.getAbsolutePath());
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||
final ClassWriter cw = accept(cn);
|
||||
String contents = Decompiler.SMALI_DISASSEMBLER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
} else if (decompiler.equalsIgnoreCase("jadx")) {
|
||||
}
|
||||
else if (decompiler.equalsIgnoreCase("jadx"))
|
||||
{
|
||||
System.out.println("Decompiling " + input.getAbsolutePath() + " with JADX");
|
||||
BytecodeViewer.openFiles(new File[]{input}, false);
|
||||
|
||||
Thread.sleep(5 * 1000);
|
||||
|
||||
if (target.equalsIgnoreCase("all")) {
|
||||
if (target.equalsIgnoreCase("all"))
|
||||
{
|
||||
System.out.println("Coming soon.");
|
||||
//Decompiler.smali.decompileToZip(output.getAbsolutePath());
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||
final ClassWriter cw = accept(cn);
|
||||
String contents = Decompiler.JADX_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (decompiler.equalsIgnoreCase("asmifier")) {
|
||||
else if (decompiler.equalsIgnoreCase("asmifier"))
|
||||
{
|
||||
System.out.println("Generating ASM code for " + input.getAbsolutePath() + " with ASMifier");
|
||||
BytecodeViewer.openFiles(new File[]{input}, false);
|
||||
|
||||
Thread.sleep(5 * 1000);
|
||||
|
||||
if (target.equalsIgnoreCase("all")) {
|
||||
if (target.equalsIgnoreCase("all"))
|
||||
{
|
||||
System.out.println("Coming soon.");
|
||||
//Decompiler.smali.decompileToZip(output.getAbsolutePath());
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ClassNode cn = BytecodeViewer.blindlySearchForClassNode(target);
|
||||
final ClassWriter cw = accept(cn);
|
||||
String contents = Decompiler.ASMIFIER_DECOMPILER.getDecompiler().decompileClassNode(cn, cw.toByteArray());
|
||||
DiskWriter.replaceFile(output.getAbsolutePath(), contents, false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
|
@ -383,21 +447,30 @@ public class CommandLineInput {
|
|||
System.out.println("Bytecode Viewer " + VERSION + " [CLI] - Created by @Konloch - https://bytecodeviewer.com");
|
||||
Configuration.canExit = true;
|
||||
System.exit(0);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static ClassWriter accept(ClassNode cn) {
|
||||
public static ClassWriter accept(ClassNode cn)
|
||||
{
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
try {
|
||||
try
|
||||
{
|
||||
cn.accept(cw);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
try {
|
||||
try
|
||||
{
|
||||
Thread.sleep(200);
|
||||
cn.accept(cw);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
catch (InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
return cw;
|
||||
|
|
|
@ -18,15 +18,15 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.BootState;
|
||||
import the.bytecode.club.bytecodeviewer.gui.theme.LAFTheme;
|
||||
import the.bytecode.club.bytecodeviewer.gui.theme.RSTATheme;
|
||||
import the.bytecode.club.bytecodeviewer.translation.Language;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* A collection of variables that can be configured through the settings menu or some form of UI/plugin
|
||||
*
|
||||
|
@ -42,8 +42,7 @@ public class Configuration
|
|||
public static boolean python3Extra = false;
|
||||
public static String rt = "";
|
||||
public static String library = "";
|
||||
public static String java = Constants.JAVA_BINARY.exists() ? Constants.JAVA_BINARY.getAbsolutePath() :
|
||||
Constants.JAVA_BINARY_NIX.exists() ? Constants.JAVA_BINARY_NIX.getAbsolutePath() : "";
|
||||
public static String java = Constants.JAVA_BINARY.exists() ? Constants.JAVA_BINARY.getAbsolutePath() : Constants.JAVA_BINARY_NIX.exists() ? Constants.JAVA_BINARY_NIX.getAbsolutePath() : "";
|
||||
public static String javac = "";
|
||||
public static String javaTools = "";
|
||||
public static File krakatauTempDir;
|
||||
|
@ -108,7 +107,7 @@ public class Configuration
|
|||
public static File getLastOpenDirectory()
|
||||
{
|
||||
File lastDir = new File(lastOpenDirectory);
|
||||
if(lastDir.getParentFile() != null && lastDir.getParentFile().exists())
|
||||
if (lastDir.getParentFile() != null && lastDir.getParentFile().exists())
|
||||
return lastDir;
|
||||
|
||||
return new File(".");
|
||||
|
@ -117,7 +116,7 @@ public class Configuration
|
|||
public static File getLastSaveDirectory()
|
||||
{
|
||||
File lastDir = new File(lastSaveDirectory);
|
||||
if(lastDir.getParentFile() != null && lastDir.getParentFile().exists())
|
||||
if (lastDir.getParentFile() != null && lastDir.getParentFile().exists())
|
||||
return lastDir;
|
||||
|
||||
try
|
||||
|
@ -134,7 +133,7 @@ public class Configuration
|
|||
{
|
||||
File lastDir = new File(lastPluginDirectory);
|
||||
|
||||
if(lastDir.getParentFile() != null && lastDir.getParentFile().exists())
|
||||
if (lastDir.getParentFile() != null && lastDir.getParentFile().exists())
|
||||
return lastDir;
|
||||
|
||||
return new File(".");
|
||||
|
@ -144,7 +143,7 @@ public class Configuration
|
|||
{
|
||||
Language language = Language.getLanguageCodeLookup().get(Locale.getDefault().getLanguage());
|
||||
|
||||
if(language != null)
|
||||
if (language != null)
|
||||
return language;
|
||||
|
||||
//fallback to english
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import the.bytecode.club.bytecodeviewer.resources.ResourceType;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
|
||||
/**
|
||||
* General program constants, to use this class include everything as a wildcard static import:
|
||||
* import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
@ -93,18 +93,18 @@ public class Constants
|
|||
File defaultLocation = new File(System.getProperty("user.home") + fs + ".Bytecode-Viewer");
|
||||
|
||||
//if BCV was previously installed using the default directory, continue to use that
|
||||
if(defaultLocation.exists())
|
||||
if (defaultLocation.exists())
|
||||
return defaultLocation;
|
||||
|
||||
//handle XDG Base Directory - https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
if(isNix())
|
||||
if (isNix())
|
||||
{
|
||||
File homeLocal = new File(System.getProperty("user.home") + fs + ".local");
|
||||
if(homeLocal.exists())
|
||||
if (homeLocal.exists())
|
||||
return new File(homeLocal, "share" + fs + ".Bytecode-Viewer");
|
||||
|
||||
File homeConfig = new File(System.getProperty("user.home") + fs + ".config");
|
||||
if(homeConfig.exists())
|
||||
if (homeConfig.exists())
|
||||
return new File(homeConfig, ".Bytecode-Viewer");
|
||||
}
|
||||
|
||||
|
@ -125,13 +125,15 @@ public class Constants
|
|||
//hides the BCV directory
|
||||
if (isWindows() && !BCVDir.isHidden())
|
||||
{
|
||||
new Thread(()->{
|
||||
try {
|
||||
new Thread(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
// Hide file by running attrib system command (on Windows)
|
||||
Process p = new ProcessBuilder("attrib",
|
||||
"+H",
|
||||
BCVDir.getAbsolutePath()).start();
|
||||
} catch (Exception e) {
|
||||
Process p = new ProcessBuilder("attrib", "+H", BCVDir.getAbsolutePath()).start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//ignore
|
||||
}
|
||||
}, "Hide BCV Dir").start();
|
||||
|
@ -166,10 +168,10 @@ public class Constants
|
|||
*/
|
||||
public static String getVersion(String mavenVersion)
|
||||
{
|
||||
if(FORCE_VERSION_CHECKER_PROMPT)
|
||||
if (FORCE_VERSION_CHECKER_PROMPT)
|
||||
return "1.0.0";
|
||||
|
||||
if(mavenVersion == null)
|
||||
if (mavenVersion == null)
|
||||
{
|
||||
DEV_MODE = true;
|
||||
return "Developer Mode";
|
||||
|
|
|
@ -18,15 +18,16 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
import javax.swing.JFileChooser;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.RunOptions;
|
||||
import the.bytecode.club.bytecodeviewer.util.DialogUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Whenever a key is pressed on the swing UI it should get logged here
|
||||
*
|
||||
|
@ -49,11 +50,9 @@ public class GlobalHotKeys
|
|||
{
|
||||
Configuration.lastHotKeyExecuted = System.currentTimeMillis();
|
||||
|
||||
final File file = DialogUtils.fileChooser("Select File or Folder to open in BCV",
|
||||
"APKs, DEX, Class Files or Zip/Jar/War Archives",
|
||||
Constants.SUPPORTED_FILE_EXTENSIONS);
|
||||
final File file = DialogUtils.fileChooser("Select File or Folder to open in BCV", "APKs, DEX, Class Files or Zip/Jar/War Archives", Constants.SUPPORTED_FILE_EXTENSIONS);
|
||||
|
||||
if(file == null)
|
||||
if (file == null)
|
||||
return;
|
||||
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
|
@ -104,10 +103,7 @@ public class GlobalHotKeys
|
|||
if (!BytecodeViewer.autoCompileSuccessful())
|
||||
return;
|
||||
|
||||
JFileChooser fc = new FileChooser(Configuration.getLastSaveDirectory(),
|
||||
"Select Zip Export",
|
||||
"Zip Archives",
|
||||
"zip");
|
||||
JFileChooser fc = new FileChooser(Configuration.getLastSaveDirectory(), "Select Zip Export", "Zip Archives", "zip");
|
||||
|
||||
int returnVal = fc.showSaveDialog(BytecodeViewer.viewer);
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION)
|
||||
|
@ -120,9 +116,9 @@ public class GlobalHotKeys
|
|||
return;
|
||||
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
Thread jarExport = new Thread(() -> {
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(),
|
||||
file.getAbsolutePath());
|
||||
Thread jarExport = new Thread(() ->
|
||||
{
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), file.getAbsolutePath());
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
}, "Jar Export");
|
||||
jarExport.start();
|
||||
|
@ -149,10 +145,10 @@ public class GlobalHotKeys
|
|||
|
||||
String recentFile = Settings.getRecentFile();
|
||||
|
||||
if(!BytecodeViewer.hasResources() && recentFile != null)
|
||||
if (!BytecodeViewer.hasResources() && recentFile != null)
|
||||
{
|
||||
File file = new File(recentFile);
|
||||
if(file.exists())
|
||||
if (file.exists())
|
||||
{
|
||||
BytecodeViewer.openFiles(new File[]{file}, false);
|
||||
}
|
||||
|
|
|
@ -19,20 +19,18 @@
|
|||
package the.bytecode.club.bytecodeviewer;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.JMenuItem;
|
||||
import me.konloch.kontainer.io.DiskReader;
|
||||
import me.konloch.kontainer.io.DiskWriter;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.BytecodeViewer.gson;
|
||||
import static the.bytecode.club.bytecodeviewer.Configuration.maxRecentFiles;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.filesName;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.getBCVDirectory;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.pluginsName;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
|
@ -84,7 +82,7 @@ public class Settings
|
|||
|
||||
public static synchronized void removeRecentFile(File f)
|
||||
{
|
||||
if(recentFiles.remove(f.getAbsolutePath()))
|
||||
if (recentFiles.remove(f.getAbsolutePath()))
|
||||
{
|
||||
DiskWriter.replaceFile(filesName, MiscUtils.listToString(recentFiles), false);
|
||||
resetRecentFilesMenu();
|
||||
|
@ -93,7 +91,7 @@ public class Settings
|
|||
|
||||
public static String getRecentFile()
|
||||
{
|
||||
if(recentFiles.isEmpty())
|
||||
if (recentFiles.isEmpty())
|
||||
return null;
|
||||
|
||||
return recentFiles.get(0);
|
||||
|
@ -115,7 +113,7 @@ public class Settings
|
|||
|
||||
public static synchronized void removeRecentPlugin(File f)
|
||||
{
|
||||
if(recentPlugins.remove(f.getAbsolutePath()))
|
||||
if (recentPlugins.remove(f.getAbsolutePath()))
|
||||
{
|
||||
DiskWriter.replaceFile(pluginsName, MiscUtils.listToString(recentPlugins), false);
|
||||
resetRecentFilesMenu();
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer;
|
||||
|
||||
import java.io.File;
|
||||
import javax.swing.JFrame;
|
||||
import me.konloch.kontainer.io.DiskReader;
|
||||
import me.konloch.kontainer.io.DiskWriter;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
||||
|
@ -27,6 +25,9 @@ import the.bytecode.club.bytecodeviewer.gui.theme.LAFTheme;
|
|||
import the.bytecode.club.bytecodeviewer.gui.theme.RSTATheme;
|
||||
import the.bytecode.club.bytecodeviewer.translation.Language;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.VERSION;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.settingsName;
|
||||
|
||||
|
@ -201,7 +202,9 @@ public class SettingsSerializer
|
|||
save(Configuration.python3Extra);
|
||||
save(BytecodeViewer.viewer.getMinSdkVersion());
|
||||
save(BytecodeViewer.viewer.printLineNumbers.isSelected());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
|
@ -215,7 +218,7 @@ public class SettingsSerializer
|
|||
{
|
||||
settingsFileExists = new File(settingsName).exists();
|
||||
|
||||
if(!settingsFileExists)
|
||||
if (!settingsFileExists)
|
||||
return;
|
||||
|
||||
//precache the file
|
||||
|
@ -240,7 +243,7 @@ public class SettingsSerializer
|
|||
//utilizes the Disk Reader's caching system.
|
||||
public static void loadSettings()
|
||||
{
|
||||
if(!settingsFileExists)
|
||||
if (!settingsFileExists)
|
||||
return;
|
||||
|
||||
Settings.firstBoot = false;
|
||||
|
@ -335,7 +338,8 @@ public class SettingsSerializer
|
|||
BytecodeViewer.viewer.refreshOnChange.setSelected(asBoolean(84));
|
||||
|
||||
boolean bool = Boolean.parseBoolean(asString(85));
|
||||
if (bool) {
|
||||
if (bool)
|
||||
{
|
||||
BytecodeViewer.viewer.setExtendedState(JFrame.MAXIMIZED_BOTH);
|
||||
BytecodeViewer.viewer.isMaximized = true;
|
||||
}
|
||||
|
@ -353,7 +357,7 @@ public class SettingsSerializer
|
|||
Configuration.deleteForeignLibraries = asBoolean(113);
|
||||
|
||||
//APK Decompiler
|
||||
switch(asInt(114))
|
||||
switch (asInt(114))
|
||||
{
|
||||
case 0:
|
||||
BytecodeViewer.viewer.apkConversionGroup.setSelected(BytecodeViewer.viewer.apkConversionDex.getModel(), true);
|
||||
|
@ -382,7 +386,7 @@ public class SettingsSerializer
|
|||
Configuration.simplifiedTabNames = BytecodeViewer.viewer.simplifyNameInTabTitle.isSelected();
|
||||
|
||||
//line 130 is used for preload
|
||||
if(Configuration.language != Language.ENGLISH)
|
||||
if (Configuration.language != Language.ENGLISH)
|
||||
Configuration.language.setLanguageTranslations(); //load language translations
|
||||
Settings.hasSetLanguageAsSystemLanguage = true;
|
||||
|
||||
|
|
|
@ -18,15 +18,7 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.api;
|
||||
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
import org.objectweb.asm.tree.InnerClassNode;
|
||||
import org.objectweb.asm.tree.LocalVariableNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
import org.objectweb.asm.tree.*;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
/**
|
||||
|
@ -58,9 +50,7 @@ public final class ASMResourceUtil
|
|||
return defaultFQN;
|
||||
}
|
||||
|
||||
public static void renameFieldNode(String originalParentName,
|
||||
String originalFieldName, String originalFieldDesc,
|
||||
String newFieldParent, String newFieldName, String newFieldDesc)
|
||||
public static void renameFieldNode(String originalParentName, String originalFieldName, String originalFieldDesc, String newFieldParent, String newFieldName, String newFieldDesc)
|
||||
{
|
||||
for (ClassNode c : BytecodeViewer.getLoadedClasses())
|
||||
{
|
||||
|
@ -73,9 +63,7 @@ public final class ASMResourceUtil
|
|||
{
|
||||
FieldInsnNode field = (FieldInsnNode) i;
|
||||
|
||||
if (field.owner.equals(originalParentName)
|
||||
&& field.name.equals(originalFieldName)
|
||||
&& field.desc.equals(originalFieldDesc))
|
||||
if (field.owner.equals(originalParentName) && field.name.equals(originalFieldName) && field.desc.equals(originalFieldDesc))
|
||||
{
|
||||
if (newFieldParent != null)
|
||||
field.owner = newFieldParent;
|
||||
|
@ -90,9 +78,7 @@ public final class ASMResourceUtil
|
|||
}
|
||||
}
|
||||
|
||||
public static void renameMethodNode(String originalParentName,
|
||||
String originalMethodName, String originalMethodDesc,
|
||||
String newParent, String newName, String newDesc)
|
||||
public static void renameMethodNode(String originalParentName, String originalMethodName, String originalMethodDesc, String newParent, String newName, String newDesc)
|
||||
{
|
||||
for (ClassNode c : BytecodeViewer.getLoadedClasses())
|
||||
{
|
||||
|
@ -104,9 +90,7 @@ public final class ASMResourceUtil
|
|||
if (i instanceof MethodInsnNode)
|
||||
{
|
||||
MethodInsnNode mi = (MethodInsnNode) i;
|
||||
if (mi.owner.equals(originalParentName)
|
||||
&& mi.name.equals(originalMethodName)
|
||||
&& mi.desc.equals(originalMethodDesc))
|
||||
if (mi.owner.equals(originalParentName) && mi.name.equals(originalMethodName) && mi.desc.equals(originalMethodDesc))
|
||||
{
|
||||
if (newParent != null)
|
||||
mi.owner = newParent;
|
||||
|
@ -123,16 +107,12 @@ public final class ASMResourceUtil
|
|||
if (m.signature != null)
|
||||
{
|
||||
if (newName != null)
|
||||
m.signature = m.signature.replace(originalMethodName,
|
||||
newName);
|
||||
m.signature = m.signature.replace(originalMethodName, newName);
|
||||
if (newParent != null)
|
||||
m.signature = m.signature.replace(originalParentName,
|
||||
newParent);
|
||||
m.signature = m.signature.replace(originalParentName, newParent);
|
||||
}
|
||||
|
||||
if (m.name.equals(originalMethodName)
|
||||
&& m.desc.equals(originalMethodDesc)
|
||||
&& c.name.equals(originalParentName))
|
||||
if (m.name.equals(originalMethodName) && m.desc.equals(originalMethodDesc) && c.name.equals(originalParentName))
|
||||
{
|
||||
if (newName != null)
|
||||
m.name = newName;
|
||||
|
|
|
@ -36,9 +36,12 @@ public class ASMUtil
|
|||
{
|
||||
ClassReader cr = new ClassReader(b);
|
||||
ClassNode cn = new ClassNode();
|
||||
try {
|
||||
try
|
||||
{
|
||||
cr.accept(cn, ClassReader.EXPAND_FRAMES);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
cr.accept(cn, ClassReader.SKIP_FRAMES);
|
||||
}
|
||||
return cn;
|
||||
|
@ -51,14 +54,21 @@ public class ASMUtil
|
|||
{
|
||||
final ClassWriter cw = new ClassWriter(0);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
cn.accept(cw);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
try {
|
||||
try
|
||||
{
|
||||
Thread.sleep(200);
|
||||
cn.accept(cw);
|
||||
} catch (InterruptedException ignored) { }
|
||||
}
|
||||
catch (InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return cw.toByteArray();
|
||||
|
@ -66,9 +76,9 @@ public class ASMUtil
|
|||
|
||||
public static MethodNode getMethodByName(ClassNode cn, String name)
|
||||
{
|
||||
for(MethodNode m : cn.methods)
|
||||
for (MethodNode m : cn.methods)
|
||||
{
|
||||
if(m.name.equals(name))
|
||||
if (m.name.equals(name))
|
||||
return m;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,17 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
@ -42,9 +31,18 @@ import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
|||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.SleepUtil;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.DEV_MODE;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
* An easier to use version of the BCV API, this is designed for anyone who wants to extend BCV, in any shape
|
||||
|
@ -62,7 +60,8 @@ public class BCV
|
|||
*
|
||||
* @return the static ClassNodeLoader instance
|
||||
*/
|
||||
public static ClassNodeLoader getClassNodeLoader() {
|
||||
public static ClassNodeLoader getClassNodeLoader()
|
||||
{
|
||||
return loader;
|
||||
}
|
||||
|
||||
|
@ -71,7 +70,8 @@ public class BCV
|
|||
*
|
||||
* @return the URLClassLoader instance
|
||||
*/
|
||||
public static URLClassLoader getClassLoaderInstance() {
|
||||
public static URLClassLoader getClassLoaderInstance()
|
||||
{
|
||||
return cl;
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ public class BCV
|
|||
*/
|
||||
public static Class<?> loadClassIntoClassLoader(ClassNode cn)
|
||||
{
|
||||
if(cn == null)
|
||||
if (cn == null)
|
||||
return null;
|
||||
|
||||
getClassNodeLoader().addClass(cn);
|
||||
|
@ -91,11 +91,13 @@ public class BCV
|
|||
try
|
||||
{
|
||||
//TODO this should be rebuilding the class loader each time a new resource has been added or removed
|
||||
if(cl == null)
|
||||
if (cl == null)
|
||||
loadClassesIntoClassLoader();
|
||||
|
||||
return cl.loadClass(cn.name);
|
||||
} catch (Exception classLoadException) {
|
||||
}
|
||||
catch (Exception classLoadException)
|
||||
{
|
||||
BytecodeViewer.handleException(classLoadException);
|
||||
}
|
||||
|
||||
|
@ -115,14 +117,16 @@ public class BCV
|
|||
List<Class<?>> ret = new ArrayList<>();
|
||||
|
||||
JarUtils.saveAsJar(BCV.getLoadedClasses(), f.getAbsolutePath());
|
||||
try (JarFile jarFile = new JarFile("" + f.getAbsolutePath())) {
|
||||
try (JarFile jarFile = new JarFile("" + f.getAbsolutePath()))
|
||||
{
|
||||
|
||||
Enumeration<JarEntry> e = jarFile.entries();
|
||||
URL[] urls = {new URL("jar:file:" + "" + f.getAbsolutePath() + "!/")};
|
||||
|
||||
cl = URLClassLoader.newInstance(urls);
|
||||
|
||||
while (e.hasMoreElements()) {
|
||||
while (e.hasMoreElements())
|
||||
{
|
||||
JarEntry je = e.nextElement();
|
||||
|
||||
if (je.isDirectory() || !je.getName().endsWith(".class"))
|
||||
|
@ -131,16 +135,21 @@ public class BCV
|
|||
String className = je.getName().replace("/", ".").replace(".class", "");
|
||||
className = className.replace('/', '.');
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
ret.add(cl.loadClass(className));
|
||||
} catch (Exception classLoadException) {
|
||||
}
|
||||
catch (Exception classLoadException)
|
||||
{
|
||||
BytecodeViewer.handleException(classLoadException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
return null;
|
||||
|
@ -149,7 +158,8 @@ public class BCV
|
|||
/**
|
||||
* Creates a new instance of the ClassNode loader.
|
||||
*/
|
||||
public static void createNewClassNodeLoaderInstance() {
|
||||
public static void createNewClassNodeLoaderInstance()
|
||||
{
|
||||
loader.clear();
|
||||
loader = new ClassNodeLoader();
|
||||
}
|
||||
|
@ -159,7 +169,8 @@ public class BCV
|
|||
*
|
||||
* @param plugin the file of the plugin
|
||||
*/
|
||||
public static void startPlugin(File plugin) {
|
||||
public static void startPlugin(File plugin)
|
||||
{
|
||||
BytecodeViewer.startPlugin(plugin);
|
||||
}
|
||||
|
||||
|
@ -169,7 +180,8 @@ public class BCV
|
|||
* @param files an array of the files you want loaded.
|
||||
* @param recentFiles if it should save to the recent files menu.
|
||||
*/
|
||||
public static void openFiles(File[] files, boolean recentFiles) {
|
||||
public static void openFiles(File[] files, boolean recentFiles)
|
||||
{
|
||||
BytecodeViewer.openFiles(files, recentFiles);
|
||||
}
|
||||
|
||||
|
@ -178,7 +190,8 @@ public class BCV
|
|||
*
|
||||
* @return The opened class node or a null if nothing is opened
|
||||
*/
|
||||
public static ClassNode getCurrentlyOpenedClassNode() {
|
||||
public static ClassNode getCurrentlyOpenedClassNode()
|
||||
{
|
||||
return BytecodeViewer.getCurrentlyOpenedClassNode();
|
||||
}
|
||||
|
||||
|
@ -192,14 +205,20 @@ public class BCV
|
|||
final ClassNode cn = BytecodeViewer.getCurrentlyOpenedClassNode();
|
||||
final ClassWriter cw = new ClassWriter(0);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
Objects.requireNonNull(cn).accept(cw);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
try {
|
||||
try
|
||||
{
|
||||
Thread.sleep(200);
|
||||
Objects.requireNonNull(cn).accept(cw);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
catch (InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,7 +242,8 @@ public class BCV
|
|||
* @param name the full name of the ClassNode
|
||||
* @return the ClassNode
|
||||
*/
|
||||
public static ClassNode getClassNode(String name) {
|
||||
public static ClassNode getClassNode(String name)
|
||||
{
|
||||
return BytecodeViewer.blindlySearchForClassNode(name);
|
||||
}
|
||||
|
||||
|
@ -232,7 +252,8 @@ public class BCV
|
|||
*
|
||||
* @return the loaded classes
|
||||
*/
|
||||
public static List<ClassNode> getLoadedClasses() {
|
||||
public static List<ClassNode> getLoadedClasses()
|
||||
{
|
||||
return BytecodeViewer.getLoadedClasses();
|
||||
}
|
||||
|
||||
|
@ -241,7 +262,8 @@ public class BCV
|
|||
*
|
||||
* @param hook
|
||||
*/
|
||||
public static void insertHook(BytecodeHook hook) {
|
||||
public static void insertHook(BytecodeHook hook)
|
||||
{
|
||||
EZInjection.hookArray.add(hook);
|
||||
}
|
||||
|
||||
|
@ -251,7 +273,8 @@ public class BCV
|
|||
*
|
||||
* @param ask if it should ask the user about resetting the workspace
|
||||
*/
|
||||
public static void resetWorkSpace(boolean ask) {
|
||||
public static void resetWorkSpace(boolean ask)
|
||||
{
|
||||
BytecodeViewer.resetWorkspace(ask);
|
||||
}
|
||||
|
||||
|
@ -261,7 +284,8 @@ public class BCV
|
|||
*
|
||||
* @param busy if it should display the busy icon or not
|
||||
*/
|
||||
public static void setBusy(boolean busy) {
|
||||
public static void setBusy(boolean busy)
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(busy);
|
||||
}
|
||||
|
||||
|
@ -270,14 +294,16 @@ public class BCV
|
|||
*
|
||||
* @param message the message you want to display
|
||||
*/
|
||||
public static void showMessage(String message) {
|
||||
public static void showMessage(String message)
|
||||
{
|
||||
BytecodeViewer.showMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks if the user would like to overwrite the file
|
||||
*/
|
||||
public static boolean canOverwriteFile(File file) {
|
||||
public static boolean canOverwriteFile(File file)
|
||||
{
|
||||
return DialogUtils.canOverwriteFile(file);
|
||||
}
|
||||
|
||||
|
@ -289,7 +315,7 @@ public class BCV
|
|||
*/
|
||||
public static void hideFrame(JFrame frame, long milliseconds)
|
||||
{
|
||||
new Thread(()->
|
||||
new Thread(() ->
|
||||
{
|
||||
SleepUtil.sleep(milliseconds);
|
||||
|
||||
|
@ -310,7 +336,7 @@ public class BCV
|
|||
*/
|
||||
public static void log(boolean devModeOnly, String s)
|
||||
{
|
||||
if(!devModeOnly || DEV_MODE)
|
||||
if (!devModeOnly || DEV_MODE)
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
|
@ -327,7 +353,7 @@ public class BCV
|
|||
*/
|
||||
public static void logE(boolean devModeOnly, String s)
|
||||
{
|
||||
if(!devModeOnly || DEV_MODE)
|
||||
if (!devModeOnly || DEV_MODE)
|
||||
System.err.println(s);
|
||||
}
|
||||
|
||||
|
@ -336,7 +362,8 @@ public class BCV
|
|||
*
|
||||
* @return The wrapped Krakatau Decompiler instance
|
||||
*/
|
||||
public static InternalDecompiler getKrakatauDecompiler() {
|
||||
public static InternalDecompiler getKrakatauDecompiler()
|
||||
{
|
||||
return Decompiler.KRAKATAU_DECOMPILER.getDecompiler();
|
||||
}
|
||||
|
||||
|
@ -345,7 +372,8 @@ public class BCV
|
|||
*
|
||||
* @return The wrapped Procyon Decompiler instance
|
||||
*/
|
||||
public static InternalDecompiler getProcyonDecompiler() {
|
||||
public static InternalDecompiler getProcyonDecompiler()
|
||||
{
|
||||
return Decompiler.PROCYON_DECOMPILER.getDecompiler();
|
||||
}
|
||||
|
||||
|
@ -354,7 +382,8 @@ public class BCV
|
|||
*
|
||||
* @return The wrapped CFR Decompiler instance
|
||||
*/
|
||||
public static InternalDecompiler getCFRDecompiler() {
|
||||
public static InternalDecompiler getCFRDecompiler()
|
||||
{
|
||||
return Decompiler.CFR_DECOMPILER.getDecompiler();
|
||||
}
|
||||
|
||||
|
@ -363,7 +392,8 @@ public class BCV
|
|||
*
|
||||
* @return The wrapped FernFlower Decompiler instance
|
||||
*/
|
||||
public static InternalDecompiler getFernFlowerDecompiler() {
|
||||
public static InternalDecompiler getFernFlowerDecompiler()
|
||||
{
|
||||
return Decompiler.FERNFLOWER_DECOMPILER.getDecompiler();
|
||||
}
|
||||
|
||||
|
@ -372,7 +402,8 @@ public class BCV
|
|||
*
|
||||
* @return The wrapped Krakatau Disassembler instance
|
||||
*/
|
||||
public static InternalDecompiler getKrakatauDisassembler() {
|
||||
public static InternalDecompiler getKrakatauDisassembler()
|
||||
{
|
||||
return Decompiler.KRAKATAU_DISASSEMBLER.getDecompiler();
|
||||
}
|
||||
|
||||
|
@ -381,7 +412,8 @@ public class BCV
|
|||
*
|
||||
* @return The wrapped JD-GUI Decompiler instance
|
||||
*/
|
||||
public static InternalDecompiler getDJGUIDecompiler() {
|
||||
public static InternalDecompiler getDJGUIDecompiler()
|
||||
{
|
||||
return Decompiler.JD_DECOMPILER.getDecompiler();
|
||||
}
|
||||
|
||||
|
@ -390,7 +422,8 @@ public class BCV
|
|||
*
|
||||
* @return The wrapped JADX Decompiler instance
|
||||
*/
|
||||
public static InternalDecompiler getJADXDecompiler() {
|
||||
public static InternalDecompiler getJADXDecompiler()
|
||||
{
|
||||
return Decompiler.JADX_DECOMPILER.getDecompiler();
|
||||
}
|
||||
|
||||
|
@ -399,7 +432,8 @@ public class BCV
|
|||
*
|
||||
* @return The wrapped Java Compiler instance
|
||||
*/
|
||||
public static InternalCompiler getJavaCompiler() {
|
||||
public static InternalCompiler getJavaCompiler()
|
||||
{
|
||||
return Compiler.JAVA_COMPILER.getCompiler();
|
||||
}
|
||||
|
||||
|
@ -408,7 +442,8 @@ public class BCV
|
|||
*
|
||||
* @return The wrapped Krakatau Assembler instance
|
||||
*/
|
||||
public static InternalCompiler getKrakatauCompiler() {
|
||||
public static InternalCompiler getKrakatauCompiler()
|
||||
{
|
||||
return Compiler.KRAKATAU_ASSEMBLER.getCompiler();
|
||||
}
|
||||
|
||||
|
@ -417,7 +452,8 @@ public class BCV
|
|||
*
|
||||
* @return The wrapped Smali Assembler instance
|
||||
*/
|
||||
public static InternalCompiler getSmaliCompiler() {
|
||||
public static InternalCompiler getSmaliCompiler()
|
||||
{
|
||||
return Compiler.SMALI_ASSEMBLER.getCompiler();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,18 +18,15 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.api;
|
||||
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import java.security.AllPermission;
|
||||
import java.security.CodeSource;
|
||||
import java.security.Permissions;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Demmonic
|
||||
|
@ -44,7 +41,8 @@ public final class ClassNodeLoader extends ClassLoader
|
|||
*
|
||||
* @param cn The class
|
||||
*/
|
||||
public void addClass(ClassNode cn) {
|
||||
public void addClass(ClassNode cn)
|
||||
{
|
||||
classes.put(cn.name.replace("/", "."), cn);
|
||||
}
|
||||
|
||||
|
@ -52,33 +50,41 @@ public final class ClassNodeLoader extends ClassLoader
|
|||
* @param name The name of the class
|
||||
* @return If this class loader contains the provided class node
|
||||
*/
|
||||
public boolean contains(String name) {
|
||||
public boolean contains(String name)
|
||||
{
|
||||
return (classes.get(name) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return All class nodes in this loader
|
||||
*/
|
||||
public Collection<ClassNode> getAll() {
|
||||
public Collection<ClassNode> getAll()
|
||||
{
|
||||
return classes.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears out all class nodes
|
||||
*/
|
||||
public void clear() {
|
||||
public void clear()
|
||||
{
|
||||
classes.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return All classes in this loader
|
||||
*/
|
||||
public Collection<Class<?>> getAllClasses() {
|
||||
public Collection<Class<?>> getAllClasses()
|
||||
{
|
||||
List<Class<?>> classes = new ArrayList<>();
|
||||
for (String s : this.classes.keySet()) {
|
||||
try {
|
||||
for (String s : this.classes.keySet())
|
||||
{
|
||||
try
|
||||
{
|
||||
classes.add(loadClass(s));
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -90,20 +96,26 @@ public final class ClassNodeLoader extends ClassLoader
|
|||
* @param name The name of the class
|
||||
* @return The class node with the provided name
|
||||
*/
|
||||
public ClassNode get(String name) {
|
||||
public ClassNode get(String name)
|
||||
{
|
||||
return classes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String className) throws ClassNotFoundException {
|
||||
public Class<?> loadClass(String className) throws ClassNotFoundException
|
||||
{
|
||||
return findClass(className);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
if (classes.containsKey(name)) {
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException
|
||||
{
|
||||
if (classes.containsKey(name))
|
||||
{
|
||||
return nodeToClass(classes.get(name));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return super.loadClass(name);
|
||||
}
|
||||
}
|
||||
|
@ -120,21 +132,24 @@ public final class ClassNodeLoader extends ClassLoader
|
|||
return findLoadedClass(node.name.replace("/", "."));
|
||||
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
try {
|
||||
try
|
||||
{
|
||||
node.accept(cw);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
byte[] b = cw.toByteArray();
|
||||
return defineClass(node.name.replaceAll("/", "."), b, 0, b.length,
|
||||
getDomain());
|
||||
return defineClass(node.name.replaceAll("/", "."), b, 0, b.length, getDomain());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return This class loader's protection domain
|
||||
*/
|
||||
private ProtectionDomain getDomain() {
|
||||
private ProtectionDomain getDomain()
|
||||
{
|
||||
CodeSource code = new CodeSource(null, (Certificate[]) null);
|
||||
return new ProtectionDomain(code, getPermissions());
|
||||
}
|
||||
|
@ -142,7 +157,8 @@ public final class ClassNodeLoader extends ClassLoader
|
|||
/**
|
||||
* @return This class loader's permissions
|
||||
*/
|
||||
private Permissions getPermissions() {
|
||||
private Permissions getPermissions()
|
||||
{
|
||||
Permissions permissions = new Permissions();
|
||||
permissions.add(new AllPermission());
|
||||
return permissions;
|
||||
|
|
|
@ -18,11 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.api;
|
||||
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.JFrameConsole;
|
||||
|
@ -30,9 +25,12 @@ import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
|
|||
import the.bytecode.club.bytecodeviewer.resources.IconResources;
|
||||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.FAT_JAR;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.VERSION;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
* A simple class designed to show exceptions in the UI.
|
||||
|
@ -49,14 +47,16 @@ public class ExceptionUI extends JFrameConsole
|
|||
/**
|
||||
* @param e The exception to be shown
|
||||
*/
|
||||
public ExceptionUI(Throwable e) {
|
||||
public ExceptionUI(Throwable e)
|
||||
{
|
||||
setupException(e, KONLOCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param e The exception to be shown
|
||||
*/
|
||||
public ExceptionUI(String e) {
|
||||
public ExceptionUI(String e)
|
||||
{
|
||||
setupFrame(e, KONLOCH);
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,8 @@ public class ExceptionUI extends JFrameConsole
|
|||
* @param e The exception to be shown
|
||||
* @param author the author of the plugin throwing this exception.
|
||||
*/
|
||||
public ExceptionUI(Throwable e, String author) {
|
||||
public ExceptionUI(Throwable e, String author)
|
||||
{
|
||||
setupException(e, author);
|
||||
}
|
||||
|
||||
|
@ -72,7 +73,8 @@ public class ExceptionUI extends JFrameConsole
|
|||
* @param e The exception to be shown
|
||||
* @param author the author of the plugin throwing this exception.
|
||||
*/
|
||||
public ExceptionUI(String e, String author) {
|
||||
public ExceptionUI(String e, String author)
|
||||
{
|
||||
setupFrame(e, author);
|
||||
}
|
||||
|
||||
|
@ -82,23 +84,25 @@ public class ExceptionUI extends JFrameConsole
|
|||
private void setupException(Throwable error, String author)
|
||||
{
|
||||
//exceptions are completely hidden
|
||||
if(Configuration.silenceExceptionGUI > 0)
|
||||
if (Configuration.silenceExceptionGUI > 0)
|
||||
return;
|
||||
|
||||
//exception GUI is disabled but printstack is still enabled
|
||||
if(Configuration.pauseExceptionGUI > 0)
|
||||
if (Configuration.pauseExceptionGUI > 0)
|
||||
{
|
||||
error.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
try (StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw)) {
|
||||
try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw))
|
||||
{
|
||||
error.printStackTrace(pw);
|
||||
error.printStackTrace();
|
||||
|
||||
setupFrame(sw.toString(), author);
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
catch (IOException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +120,7 @@ public class ExceptionUI extends JFrameConsole
|
|||
getTextArea().setCaretPosition(0);
|
||||
|
||||
//embed error log as a new tab
|
||||
if(Configuration.errorLogsAsNewTab)
|
||||
if (Configuration.errorLogsAsNewTab)
|
||||
PluginManager.addExceptionUI(this);
|
||||
|
||||
//pop open a new window frame
|
||||
|
@ -134,11 +138,7 @@ public class ExceptionUI extends JFrameConsole
|
|||
{
|
||||
String fatJar = FAT_JAR ? " [Fat Jar]" : "";
|
||||
|
||||
return TranslatedStrings.PLEASE_SEND_THIS_ERROR_LOG_TO + " " + author +
|
||||
"\n" + TranslatedStrings.PLEASE_SEND_RESOURCES +
|
||||
"\nBytecode Viewer Version: " + VERSION + fatJar +
|
||||
", OS: " + System.getProperty("os.name") +
|
||||
", Java: " + System.getProperty("java.version");
|
||||
return TranslatedStrings.PLEASE_SEND_THIS_ERROR_LOG_TO + " " + author + "\n" + TranslatedStrings.PLEASE_SEND_RESOURCES + "\nBytecode Viewer Version: " + VERSION + fatJar + ", OS: " + System.getProperty("os.name") + ", Java: " + System.getProperty("java.version");
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -5230501978224926296L;
|
||||
|
|
|
@ -18,12 +18,13 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A simple plugin class, it will run the plugin in a background thread.
|
||||
*
|
||||
|
@ -47,9 +48,13 @@ public abstract class Plugin extends Thread
|
|||
return;
|
||||
|
||||
executeContainer();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
} finally {
|
||||
}
|
||||
finally
|
||||
{
|
||||
finished = true;
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
}
|
||||
|
@ -62,7 +67,8 @@ public abstract class Plugin extends Thread
|
|||
*
|
||||
* @return true if the plugin is finished executing
|
||||
*/
|
||||
public boolean isFinished() {
|
||||
public boolean isFinished()
|
||||
{
|
||||
return finished;
|
||||
}
|
||||
|
||||
|
@ -71,7 +77,8 @@ public abstract class Plugin extends Thread
|
|||
* still be considered finished (EZ-Injection), you can call this function
|
||||
* and it will set the finished boolean to true.
|
||||
*/
|
||||
public void setFinished() {
|
||||
public void setFinished()
|
||||
{
|
||||
finished = true;
|
||||
}
|
||||
|
||||
|
@ -80,7 +87,8 @@ public abstract class Plugin extends Thread
|
|||
*/
|
||||
public void executeContainer()
|
||||
{
|
||||
BytecodeViewer.getResourceContainers().forEach(container -> {
|
||||
BytecodeViewer.getResourceContainers().forEach(container ->
|
||||
{
|
||||
//set the active container
|
||||
activeContainer = container;
|
||||
|
||||
|
|
|
@ -37,21 +37,20 @@ public class PluginConsole extends SystemConsole
|
|||
|
||||
public PluginConsole(String pluginName)
|
||||
{
|
||||
super(Configuration.pluginConsoleAsNewTab ? (pluginName + " Output")
|
||||
: (TranslatedStrings.PLUGIN_CONSOLE_TITLE + " - " + pluginName));
|
||||
super(Configuration.pluginConsoleAsNewTab ? (pluginName + " Output") : (TranslatedStrings.PLUGIN_CONSOLE_TITLE + " - " + pluginName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visible)
|
||||
{
|
||||
if(!added && visible)
|
||||
if (!added && visible)
|
||||
{
|
||||
added = true;
|
||||
PluginManager.addConsole(this);
|
||||
}
|
||||
|
||||
//do nothing
|
||||
if(!showWindow)
|
||||
if (!showWindow)
|
||||
return;
|
||||
|
||||
super.setVisible(visible);
|
||||
|
|
|
@ -18,15 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.bootloader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import com.konloch.httprequest.HTTPRequest;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
@ -40,18 +31,24 @@ import the.bytecode.club.bytecodeviewer.bootloader.resource.external.ExternalRes
|
|||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.ZipUtils;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.getBCVDirectory;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.krakatauVersion;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.krakatauWorkingDirectory;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
* @author Bibl (don't ban me pls)
|
||||
* @since 19 Jul 2015 03:22:37
|
||||
*/
|
||||
public class Boot {
|
||||
public class Boot
|
||||
{
|
||||
|
||||
/*flags*/
|
||||
public static boolean globalstop = false;
|
||||
|
@ -63,7 +60,8 @@ public class Boot {
|
|||
private static final List<String> libsFileList = new ArrayList<>();
|
||||
private static final List<String> urlList = new ArrayList<>();
|
||||
|
||||
public static void boot(String[] args, boolean CLI) throws Exception {
|
||||
public static void boot(String[] args, boolean CLI) throws Exception
|
||||
{
|
||||
bootstrap();
|
||||
ILoader<?> loader = findLoader();
|
||||
|
||||
|
@ -77,27 +75,30 @@ public class Boot {
|
|||
SwingUtilities.invokeLater(() -> screen.setVisible(false));
|
||||
}
|
||||
|
||||
public static void hide() {
|
||||
public static void hide()
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> screen.setVisible(false));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private static void create(ILoader<?> loader, boolean clean) throws Exception {
|
||||
private static void create(ILoader<?> loader, boolean clean) throws Exception
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - Checking Libraries...");
|
||||
final File libsDirectory = libsDir();
|
||||
|
||||
populateUrlList();
|
||||
|
||||
if (globalstop) {
|
||||
while (true) {
|
||||
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);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -113,46 +114,52 @@ public class Boot {
|
|||
|
||||
int completedCheck = 0;
|
||||
|
||||
for (String s : urlList) {
|
||||
String fileName = s.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length()
|
||||
);
|
||||
for (String s : urlList)
|
||||
{
|
||||
String fileName = s.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length());
|
||||
File file = new File(libsDirectory, fileName);
|
||||
|
||||
boolean passed = false;
|
||||
while (!passed) {
|
||||
if (!libsList.contains(fileName)) {
|
||||
while (!passed)
|
||||
{
|
||||
if (!libsList.contains(fileName))
|
||||
{
|
||||
downloading = true;
|
||||
setState("Bytecode Viewer Boot Screen - Downloading " + fileName + "...");
|
||||
System.out.println("Downloading " + fileName);
|
||||
|
||||
try (InputStream is = new URL("https://github.com/Konloch/bytecode-viewer/raw/master/libs/" + fileName)
|
||||
.openConnection().getInputStream();
|
||||
FileOutputStream fos = new FileOutputStream(file)) {
|
||||
try (InputStream is = new URL("https://github.com/Konloch/bytecode-viewer/raw/master/libs/" + fileName).openConnection().getInputStream(); FileOutputStream 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) {
|
||||
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 (mbs % 5 == 0 && mbs != 0)
|
||||
{
|
||||
if (!flag)
|
||||
System.out.println("Downloaded " + mbs + "MBs so far");
|
||||
flag = true;
|
||||
} else
|
||||
}
|
||||
else
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - Verifying " + fileName + "...");
|
||||
System.out.println("Verifying " + fileName + "...");
|
||||
|
||||
File f = new File(Constants.tempDirectory, "temp");
|
||||
if (!f.exists()) {
|
||||
if (!f.exists())
|
||||
{
|
||||
f.getParentFile().mkdirs();
|
||||
}
|
||||
ZipUtils.zipFile(file, f);
|
||||
|
@ -161,13 +168,18 @@ public class Boot {
|
|||
libsFileList.add(file.getAbsolutePath());
|
||||
System.out.println("Download finished!");
|
||||
passed = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
System.out.println("Jar or Zip" + file.getAbsolutePath() + " is corrupt, redownloading.");
|
||||
file.delete();
|
||||
}
|
||||
} else if (Configuration.verifyCorruptedStateOnBoot) { //verify its not corrupt each boot (adds 3 seconds boot time)
|
||||
try {
|
||||
}
|
||||
else if (Configuration.verifyCorruptedStateOnBoot)
|
||||
{ //verify its not corrupt each boot (adds 3 seconds boot time)
|
||||
try
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - Verifying " + fileName + "...");
|
||||
System.out.println("Verifying " + fileName + "...");
|
||||
|
||||
|
@ -176,13 +188,17 @@ public class Boot {
|
|||
f.delete();
|
||||
|
||||
passed = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
System.out.println("Jar or Zip" + file.getAbsolutePath() + " is corrupt, redownloading.");
|
||||
libsFileList.remove(file.getAbsolutePath());
|
||||
file.delete();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
passed = true;
|
||||
}
|
||||
}
|
||||
|
@ -193,17 +209,18 @@ public class Boot {
|
|||
|
||||
setState("Bytecode Viewer Boot Screen - Checking & Deleting Foreign/Outdated Libraries...");
|
||||
System.out.println("Checking & Deleting foreign/outdated libraries");
|
||||
for (String s : libsFileList) {
|
||||
for (String s : libsFileList)
|
||||
{
|
||||
File f = new File(s);
|
||||
boolean delete = true;
|
||||
for (String urlS : urlList) {
|
||||
String fileName =
|
||||
urlS.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length()
|
||||
);
|
||||
for (String urlS : urlList)
|
||||
{
|
||||
String fileName = urlS.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length());
|
||||
if (fileName.equals(f.getName()))
|
||||
delete = false;
|
||||
}
|
||||
if (delete) {
|
||||
if (delete)
|
||||
{
|
||||
f.delete();
|
||||
System.out.println("Detected & Deleted Foreign/Outdated Jar/File: " + f.getName());
|
||||
}
|
||||
|
@ -212,23 +229,27 @@ public class Boot {
|
|||
setState("Bytecode Viewer Boot Screen - Loading Libraries...");
|
||||
System.out.println("Loading libraries...");
|
||||
|
||||
for (String s : libsFileList) {
|
||||
if (s.endsWith(".jar")) {
|
||||
for (String s : libsFileList)
|
||||
{
|
||||
if (s.endsWith(".jar"))
|
||||
{
|
||||
File f = new File(s);
|
||||
if (f.exists()) {
|
||||
if (f.exists())
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - Loading Library " + f.getName());
|
||||
System.out.println("Loading library " + f.getName());
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
ExternalResource res = new EmptyExternalResource<>(f.toURI().toURL());
|
||||
loader.bind(res);
|
||||
System.out.println("Successfully loaded " + f.getName());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
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);
|
||||
JOptionPane.showMessageDialog(null, "Error, Library " + f.getName() + " is corrupt, please " + "restart to redownload it.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -249,7 +270,8 @@ public class Boot {
|
|||
completedboot = true;
|
||||
}
|
||||
|
||||
public static File libsDir() {
|
||||
public static File libsDir()
|
||||
{
|
||||
File dir = new File(System.getProperty("user.home"), ".Bytecode-Viewer/libs");
|
||||
while (!dir.exists())
|
||||
dir.mkdirs();
|
||||
|
@ -263,7 +285,8 @@ public class Boot {
|
|||
screen.setTitle(s);
|
||||
}
|
||||
|
||||
public static ILoader<?> findLoader() {
|
||||
public static ILoader<?> findLoader()
|
||||
{
|
||||
// TODO: Find from providers
|
||||
// return new LibraryClassLoader();
|
||||
|
||||
|
@ -271,32 +294,39 @@ public class Boot {
|
|||
return AbstractLoaderFactory.find().spawnLoader();
|
||||
}
|
||||
|
||||
private static void bootstrap() {
|
||||
private static void bootstrap()
|
||||
{
|
||||
AbstractLoaderFactory.register(ClassPathLoader::new);
|
||||
}
|
||||
|
||||
public static void populateUrlList() throws Exception {
|
||||
public static void populateUrlList() throws Exception
|
||||
{
|
||||
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/")) {
|
||||
if (s.contains("href=\"/Konloch/bytecode-viewer/blob/master/libs/"))
|
||||
{
|
||||
urlList.add("https://github.com" + s.split("href=")[1].split("\"")[1]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void populateLibsDirectory() {
|
||||
public static void populateLibsDirectory()
|
||||
{
|
||||
File libsDir = libsDir();
|
||||
if (libsDir.exists())
|
||||
for (File f : MiscUtils.listFiles(libsDir)) {
|
||||
for (File f : MiscUtils.listFiles(libsDir))
|
||||
{
|
||||
libsList.add(f.getName());
|
||||
libsFileList.add(f.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
public static void dropKrakatau() {
|
||||
public static void dropKrakatau()
|
||||
{
|
||||
File temp = new File(getBCVDirectory() + fs + "krakatau_" + krakatauVersion + ".zip");
|
||||
File krakatauDirectory = new File(krakatauWorkingDirectory);
|
||||
krakatauWorkingDirectory += fs + "Krakatau-master";
|
||||
if (!krakatauDirectory.exists() || temp.exists()) {
|
||||
if (!krakatauDirectory.exists() || temp.exists())
|
||||
{
|
||||
if (temp.exists())
|
||||
temp.delete();
|
||||
|
||||
|
@ -306,30 +336,34 @@ public class Boot {
|
|||
while (temp.exists())
|
||||
temp.delete();
|
||||
|
||||
try (InputStream is = BytecodeViewer.class.getClassLoader().getResourceAsStream("Krakatau-"
|
||||
+ krakatauVersion + ".zip");
|
||||
FileOutputStream baos = new FileOutputStream(temp)) {
|
||||
try (InputStream is = BytecodeViewer.class.getClassLoader().getResourceAsStream("Krakatau-" + krakatauVersion + ".zip"); FileOutputStream baos = new FileOutputStream(temp))
|
||||
{
|
||||
int r;
|
||||
byte[] buffer = new byte[8192];
|
||||
while ((r = Objects.requireNonNull(is).read(buffer)) >= 0) {
|
||||
while ((r = Objects.requireNonNull(is).read(buffer)) >= 0)
|
||||
{
|
||||
baos.write(buffer, 0, r);
|
||||
}
|
||||
|
||||
ZipUtils.unzipFilesToPath(temp.getAbsolutePath(), krakatauDirectory.getAbsolutePath());
|
||||
temp.delete();
|
||||
System.out.println("Successfully extracted Krakatau");
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - ERROR, please contact @Konloch with your stacktrace.");
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void dropEnjarify() {
|
||||
public static void dropEnjarify()
|
||||
{
|
||||
File temp = new File(getBCVDirectory() + fs + "enjarify" + Constants.enjarifyVersion + ".zip");
|
||||
File enjarifyDirectory = new File(Constants.enjarifyWorkingDirectory);
|
||||
Constants.enjarifyWorkingDirectory += fs + "enjarify-master";
|
||||
if (!enjarifyDirectory.exists() || temp.exists()) {
|
||||
if (!enjarifyDirectory.exists() || temp.exists())
|
||||
{
|
||||
if (temp.exists())
|
||||
temp.delete();
|
||||
|
||||
|
@ -339,63 +373,73 @@ public class Boot {
|
|||
while (temp.exists())
|
||||
temp.delete();
|
||||
|
||||
try (InputStream is = BytecodeViewer.class.getClassLoader().getResourceAsStream("enjarify-" +
|
||||
Constants.enjarifyVersion + ".zip");
|
||||
FileOutputStream baos = new FileOutputStream(temp)) {
|
||||
try (InputStream is = BytecodeViewer.class.getClassLoader().getResourceAsStream("enjarify-" + Constants.enjarifyVersion + ".zip"); FileOutputStream baos = new FileOutputStream(temp))
|
||||
{
|
||||
int r;
|
||||
byte[] buffer = new byte[8192];
|
||||
while ((r = Objects.requireNonNull(is).read(buffer)) >= 0) {
|
||||
while ((r = Objects.requireNonNull(is).read(buffer)) >= 0)
|
||||
{
|
||||
baos.write(buffer, 0, r);
|
||||
}
|
||||
|
||||
ZipUtils.unzipFilesToPath(temp.getAbsolutePath(), enjarifyDirectory.getAbsolutePath());
|
||||
temp.delete();
|
||||
System.out.println("Successfully extracted Enjarify");
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - ERROR, please contact @Konloch with your stacktrace.");
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void downloadZipsOnly() {
|
||||
for (String s : urlList) {
|
||||
String fileName = s.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length()
|
||||
);
|
||||
public static void downloadZipsOnly()
|
||||
{
|
||||
for (String s : urlList)
|
||||
{
|
||||
String fileName = s.substring("https://github.com/Konloch/bytecode-viewer/blob/master/libs/".length());
|
||||
File file = new File(libsDir(), fileName);
|
||||
|
||||
boolean passed = false;
|
||||
while (!passed) {
|
||||
if (!libsList.contains(fileName) && fileName.endsWith(".zip")) {
|
||||
while (!passed)
|
||||
{
|
||||
if (!libsList.contains(fileName) && fileName.endsWith(".zip"))
|
||||
{
|
||||
downloading = true;
|
||||
setState("Bytecode Viewer Boot Screen - Downloading " + fileName + "...");
|
||||
System.out.println("Downloading " + fileName);
|
||||
|
||||
try (InputStream is = new URL("https://github.com/Konloch/bytecode-viewer/raw/master/libs/" + fileName)
|
||||
.openConnection().getInputStream();
|
||||
FileOutputStream fos = new FileOutputStream(file)) {
|
||||
try (InputStream is = new URL("https://github.com/Konloch/bytecode-viewer/raw/master/libs/" + fileName).openConnection().getInputStream(); FileOutputStream 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) {
|
||||
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 (mbs % 5 == 0 && mbs != 0)
|
||||
{
|
||||
if (!flag)
|
||||
System.out.println("Downloaded " + mbs + "MBs so far");
|
||||
flag = true;
|
||||
} else
|
||||
}
|
||||
else
|
||||
flag = false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - Verifying " + fileName + "...");
|
||||
System.out.println("Verifying " + fileName + "...");
|
||||
|
||||
|
@ -406,35 +450,46 @@ public class Boot {
|
|||
libsFileList.add(file.getAbsolutePath());
|
||||
System.out.println("Download finished!");
|
||||
passed = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
System.out.println("Jar or Zip" + file.getAbsolutePath() + " is corrupt, redownloading.");
|
||||
file.delete();
|
||||
}
|
||||
} else
|
||||
}
|
||||
else
|
||||
passed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkEnjarify() {
|
||||
public static void checkEnjarify()
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - Checking Enjarify...");
|
||||
System.out.println("Checking enjarify");
|
||||
File enjarifyZip = null;
|
||||
for (File f : MiscUtils.listFiles(new File(Constants.libsDirectory))) {
|
||||
if (f.getName().toLowerCase().startsWith("enjarify-")) {
|
||||
for (File f : MiscUtils.listFiles(new File(Constants.libsDirectory)))
|
||||
{
|
||||
if (f.getName().toLowerCase().startsWith("enjarify-"))
|
||||
{
|
||||
Constants.enjarifyVersion = f.getName().split("-")[1].split("\\.")[0];
|
||||
enjarifyZip = f;
|
||||
}
|
||||
}
|
||||
|
||||
for (File f : MiscUtils.listFiles(new File(getBCVDirectory()))) {
|
||||
if (f.getName().toLowerCase().startsWith("enjarify_") && !f.getName().split("_")[1].split("\\.")[0].equals(Constants.enjarifyVersion)) {
|
||||
for (File f : MiscUtils.listFiles(new File(getBCVDirectory())))
|
||||
{
|
||||
if (f.getName().toLowerCase().startsWith("enjarify_") && !f.getName().split("_")[1].split("\\.")[0].equals(Constants.enjarifyVersion))
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - Removing Outdated " + f.getName() + "...");
|
||||
System.out.println("Removing oudated " + f.getName());
|
||||
try {
|
||||
try
|
||||
{
|
||||
FileUtils.deleteDirectory(f);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -442,16 +497,17 @@ public class Boot {
|
|||
|
||||
Constants.enjarifyWorkingDirectory = getBCVDirectory() + fs + "enjarify_" + Constants.enjarifyVersion + fs + "enjarify-master";
|
||||
File enjarifyDirectory = new File(getBCVDirectory() + fs + "enjarify_" + Constants.enjarifyVersion);
|
||||
if (!enjarifyDirectory.exists()) {
|
||||
try {
|
||||
if (!enjarifyDirectory.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - Updating to " + enjarifyDirectory.getName() + "...");
|
||||
ZipUtils.unzipFilesToPath(Objects.requireNonNull(enjarifyZip).getAbsolutePath(),
|
||||
enjarifyDirectory.getAbsolutePath());
|
||||
ZipUtils.unzipFilesToPath(Objects.requireNonNull(enjarifyZip).getAbsolutePath(), enjarifyDirectory.getAbsolutePath());
|
||||
System.out.println("Updated to enjarify v" + Constants.enjarifyVersion);
|
||||
} catch (Exception e) {
|
||||
BytecodeViewer.showMessage("ERROR: There was an issue unzipping enjarify (possibly corrupt). Restart "
|
||||
+ "BCV." + nl +
|
||||
"If the error persists contact @Konloch.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.showMessage("ERROR: There was an issue unzipping enjarify (possibly corrupt). Restart " + "BCV." + nl + "If the error persists contact @Konloch.");
|
||||
BytecodeViewer.handleException(e);
|
||||
Objects.requireNonNull(enjarifyZip).delete();
|
||||
}
|
||||
|
@ -459,26 +515,34 @@ public class Boot {
|
|||
|
||||
}
|
||||
|
||||
public static void checkKrakatau() {
|
||||
public static void checkKrakatau()
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - Checking Krakatau...");
|
||||
System.out.println("Checking krakatau");
|
||||
|
||||
File krakatauZip = null;
|
||||
for (File f : MiscUtils.listFiles(new File(Constants.libsDirectory))) {
|
||||
if (f.getName().toLowerCase().startsWith("krakatau-")) {
|
||||
for (File f : MiscUtils.listFiles(new File(Constants.libsDirectory)))
|
||||
{
|
||||
if (f.getName().toLowerCase().startsWith("krakatau-"))
|
||||
{
|
||||
//System.out.println(f.getName());
|
||||
Constants.krakatauVersion = f.getName().split("-")[1].split("\\.")[0];
|
||||
krakatauZip = f;
|
||||
}
|
||||
}
|
||||
|
||||
for (File f : MiscUtils.listFiles(new File(getBCVDirectory()))) {
|
||||
if (f.getName().toLowerCase().startsWith("krakatau_") && !f.getName().split("_")[1].split("\\.")[0].equals(Constants.krakatauVersion)) {
|
||||
for (File f : MiscUtils.listFiles(new File(getBCVDirectory())))
|
||||
{
|
||||
if (f.getName().toLowerCase().startsWith("krakatau_") && !f.getName().split("_")[1].split("\\.")[0].equals(Constants.krakatauVersion))
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - Removing Outdated " + f.getName() + "...");
|
||||
System.out.println("Removing oudated " + f.getName());
|
||||
try {
|
||||
try
|
||||
{
|
||||
FileUtils.deleteDirectory(f);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -487,16 +551,17 @@ public class Boot {
|
|||
Constants.krakatauWorkingDirectory = getBCVDirectory() + fs + "krakatau_" + Constants.krakatauVersion + fs + "Krakatau-master";
|
||||
|
||||
File krakatauDirectory = new File(getBCVDirectory() + fs + "krakatau_" + Constants.krakatauVersion);
|
||||
if (!krakatauDirectory.exists()) {
|
||||
try {
|
||||
if (!krakatauDirectory.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
setState("Bytecode Viewer Boot Screen - Updating to " + krakatauDirectory.getName() + "...");
|
||||
ZipUtils.unzipFilesToPath(Objects.requireNonNull(krakatauZip).getAbsolutePath(),
|
||||
krakatauDirectory.getAbsolutePath());
|
||||
ZipUtils.unzipFilesToPath(Objects.requireNonNull(krakatauZip).getAbsolutePath(), krakatauDirectory.getAbsolutePath());
|
||||
System.out.println("Updated to krakatau v" + Constants.krakatauVersion);
|
||||
} catch (Exception e) {
|
||||
BytecodeViewer.showMessage("ERROR: There was an issue unzipping Krakatau decompiler (possibly "
|
||||
+ "corrupt). Restart BCV." + nl +
|
||||
"If the error persists contact @Konloch.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.showMessage("ERROR: There was an issue unzipping Krakatau decompiler (possibly " + "corrupt). Restart BCV." + nl + "If the error persists contact @Konloch.");
|
||||
BytecodeViewer.handleException(e);
|
||||
Objects.requireNonNull(krakatauZip).delete();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,5 @@ package the.bytecode.club.bytecodeviewer.bootloader;
|
|||
|
||||
public enum BootState
|
||||
{
|
||||
START_UP,
|
||||
SETTINGS_LOADED,
|
||||
GUI_SHOWING,
|
||||
START_UP, SETTINGS_LOADED, GUI_SHOWING,
|
||||
}
|
||||
|
|
|
@ -18,21 +18,16 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.bootloader;
|
||||
|
||||
import java.awt.Dimension;
|
||||
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.io.IOException;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.HTMLPane;
|
||||
import the.bytecode.club.bytecodeviewer.resources.IconResources;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.IOException;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Configuration.language;
|
||||
|
||||
/**
|
||||
|
@ -47,9 +42,11 @@ public class InitialBootScreen extends JFrame
|
|||
public InitialBootScreen() throws IOException
|
||||
{
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
addWindowListener(new WindowAdapter() {
|
||||
addWindowListener(new WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
Configuration.canExit = true;
|
||||
System.exit(0);
|
||||
}
|
||||
|
@ -98,7 +95,8 @@ public class InitialBootScreen extends JFrame
|
|||
return Toolkit.getDefaultToolkit().getScreenSize();
|
||||
}
|
||||
|
||||
public JProgressBar getProgressBar() {
|
||||
public JProgressBar getProgressBar()
|
||||
{
|
||||
return progressBar;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import static the.bytecode.club.bytecodeviewer.Constants.AUTOMATIC_LIBRARY_UPDAT
|
|||
|
||||
/**
|
||||
* Downloads & installs the krakatau & enjarify zips
|
||||
*
|
||||
* <p>
|
||||
* Alternatively if OFFLINE_MODE is enabled it will drop the Krakatau and Enjarify versions supplied with BCV
|
||||
*
|
||||
* @author Konloch
|
||||
|
|
|
@ -18,17 +18,8 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.bootloader;
|
||||
|
||||
import de.skuzzle.semantic.Version;
|
||||
import java.awt.Desktop;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import javax.swing.JFileChooser;
|
||||
import com.konloch.httprequest.HTTPRequest;
|
||||
import de.skuzzle.semantic.Version;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||
import the.bytecode.club.bytecodeviewer.api.BCV;
|
||||
|
@ -36,6 +27,12 @@ import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
|||
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog;
|
||||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.VERSION;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
|
||||
|
@ -46,8 +43,7 @@ public class UpdateCheck implements Runnable
|
|||
{
|
||||
//just brute force download the url path
|
||||
//one of these works for every single version of BCV
|
||||
public static final String[] remoteGithubReleases = new String[]
|
||||
{
|
||||
public static final String[] remoteGithubReleases = new String[]{
|
||||
//current url scheme since v2.9.12
|
||||
"https://github.com/Konloch/bytecode-viewer/releases/download/v{VERSION}/Bytecode-Viewer-{VERSION}.jar",
|
||||
//for v2.9.10 and v2.9.11
|
||||
|
@ -63,31 +59,13 @@ public class UpdateCheck implements Runnable
|
|||
//for v1.0
|
||||
"https://github.com/Konloch/bytecode-viewer/releases/download/B{VERSION}/BytecodeViewer.jar",
|
||||
//zip variant of current url scheme since v2.9.12 (not currently used but incase it ever does)
|
||||
"https://github.com/Konloch/bytecode-viewer/releases/download/v{VERSION}/Bytecode-Viewer-{VERSION}.zip",
|
||||
};
|
||||
"https://github.com/Konloch/bytecode-viewer/releases/download/v{VERSION}/Bytecode-Viewer-{VERSION}.zip",};
|
||||
|
||||
//a list of all of the released versions of BCV
|
||||
public static final String[] versions = new String[]
|
||||
{
|
||||
public static final String[] versions = new String[]{
|
||||
//"2.11.0",
|
||||
//"2.10.15",
|
||||
"2.10.14",
|
||||
"2.10.13",
|
||||
"2.10.12",
|
||||
"2.10.11",
|
||||
"2.9.22",
|
||||
"2.9.21",
|
||||
"2.9.20",
|
||||
"2.9.19",
|
||||
"2.9.18",
|
||||
"2.9.17",
|
||||
"2.9.16",
|
||||
"2.9.15",
|
||||
"2.9.14",
|
||||
"2.9.13",
|
||||
"2.9.12",
|
||||
"2.9.11",
|
||||
"2.9.10", //broken due to repo change
|
||||
"2.10.14", "2.10.13", "2.10.12", "2.10.11", "2.9.22", "2.9.21", "2.9.20", "2.9.19", "2.9.18", "2.9.17", "2.9.16", "2.9.15", "2.9.14", "2.9.13", "2.9.12", "2.9.11", "2.9.10", //broken due to repo change
|
||||
"2.9.8", //broken due to repo change & zip
|
||||
"2.9.7", //broken due to repo change & zip
|
||||
"2.9.6", //zip
|
||||
|
@ -101,48 +79,28 @@ public class UpdateCheck implements Runnable
|
|||
"2.8.0", //zip
|
||||
"2.7.1", //zip
|
||||
"2.7.0", //zip
|
||||
"2.6.0",
|
||||
"2.5.2",
|
||||
"2.5.1",
|
||||
"2.5.0",
|
||||
"2.4.0",
|
||||
"2.3.0",
|
||||
"2.2.1",
|
||||
"2.2.0",
|
||||
"2.1.1",
|
||||
"2.1.0",
|
||||
"2.0.1",
|
||||
"2.0",
|
||||
"1.5.3",
|
||||
"1.5.2",
|
||||
"1.5.1",
|
||||
"1.5",
|
||||
"1.4",
|
||||
"1.3.1",
|
||||
"1.3",
|
||||
"1.2",
|
||||
"1.1",
|
||||
"1.0",
|
||||
};
|
||||
"2.6.0", "2.5.2", "2.5.1", "2.5.0", "2.4.0", "2.3.0", "2.2.1", "2.2.0", "2.1.1", "2.1.0", "2.0.1", "2.0", "1.5.3", "1.5.2", "1.5.1", "1.5", "1.4", "1.3.1", "1.3", "1.2", "1.1", "1.0",};
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
HTTPRequest r = new HTTPRequest(new URL("https://raw.githubusercontent.com/Konloch/bytecode-viewer/master/VERSION"));
|
||||
final Version version = Version.parseVersion(r.readSingle());
|
||||
final Version localVersion = Version.parseVersion(VERSION);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
//developer version
|
||||
if (Version.compare(localVersion, version) > 0)
|
||||
return;
|
||||
} catch (Exception ignored) { }
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
}
|
||||
|
||||
MultipleChoiceDialog outdatedDialog = new MultipleChoiceDialog("Bytecode Viewer - Outdated Version",
|
||||
"Your version: " + localVersion + ", latest version: " + version + nl +
|
||||
"What would you like to do?",
|
||||
new String[]{"Open The Download Page", "Download The Updated Jar", "Do Nothing (And Don't Ask Again)"});
|
||||
MultipleChoiceDialog outdatedDialog = new MultipleChoiceDialog("Bytecode Viewer - Outdated Version", "Your version: " + localVersion + ", latest version: " + version + nl + "What would you like to do?", new String[]{"Open The Download Page", "Download The Updated Jar", "Do Nothing (And Don't Ask Again)"});
|
||||
|
||||
int result = outdatedDialog.promptChoice();
|
||||
|
||||
|
@ -151,34 +109,35 @@ public class UpdateCheck implements Runnable
|
|||
if (Desktop.isDesktopSupported())
|
||||
Desktop.getDesktop().browse(new URI("https://github.com/Konloch/bytecode-viewer/releases"));
|
||||
else
|
||||
BytecodeViewer.showMessage("Cannot open the page, please manually type it."
|
||||
+ nl + "https://github.com/Konloch/bytecode-viewer/releases");
|
||||
BytecodeViewer.showMessage("Cannot open the page, please manually type it." + nl + "https://github.com/Konloch/bytecode-viewer/releases");
|
||||
}
|
||||
else if (result == 1)
|
||||
{
|
||||
//TODO move this to after the file extension has been found
|
||||
final File file = promptFileSave("Jar Archives", "jar");
|
||||
|
||||
if(file != null)
|
||||
if (file != null)
|
||||
{
|
||||
Thread downloadThread = new Thread(() ->
|
||||
downloadBCV(version.toString(), file, ()->{}, ()->{}), "Downloader");
|
||||
Thread downloadThread = new Thread(() -> downloadBCV(version.toString(), file, () ->
|
||||
{}, () ->
|
||||
{}), "Downloader");
|
||||
downloadThread.start();
|
||||
}
|
||||
}
|
||||
else if(result == 2)
|
||||
else if (result == 2)
|
||||
{
|
||||
//TODO save version into a hashset called doNotPrompt
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static File promptFileSave(String description, String extension) throws IOException
|
||||
{
|
||||
JFileChooser fc = new FileChooser(new File("./").getCanonicalFile(),
|
||||
"Select Save File", description, extension);
|
||||
JFileChooser fc = new FileChooser(new File("./").getCanonicalFile(), "Select Save File", description, extension);
|
||||
|
||||
int returnVal = fc.showSaveDialog(BytecodeViewer.viewer);
|
||||
File file = null;
|
||||
|
@ -193,9 +152,7 @@ public class UpdateCheck implements Runnable
|
|||
|
||||
if (file.exists())
|
||||
{
|
||||
MultipleChoiceDialog overwriteDialog = new MultipleChoiceDialog("Bytecode Viewer - Overwrite File",
|
||||
"The file " + file + " exists, would you like to overwrite it?",
|
||||
new String[]{TranslatedStrings.YES.toString(), TranslatedStrings.NO.toString()});
|
||||
MultipleChoiceDialog overwriteDialog = new MultipleChoiceDialog("Bytecode Viewer - Overwrite File", "The file " + file + " exists, would you like to overwrite it?", new String[]{TranslatedStrings.YES.toString(), TranslatedStrings.NO.toString()});
|
||||
|
||||
if (overwriteDialog.promptChoice() != 0)
|
||||
return null;
|
||||
|
@ -223,28 +180,32 @@ public class UpdateCheck implements Runnable
|
|||
private static void downloadBCV(String version, File saveTo, Runnable onFinish, Runnable onFail)
|
||||
{
|
||||
boolean found = false;
|
||||
for(String urlAttempt : remoteGithubReleases)
|
||||
for (String urlAttempt : remoteGithubReleases)
|
||||
{
|
||||
try
|
||||
{
|
||||
String url = urlAttempt.replace("{VERSION}", version);
|
||||
|
||||
if(validURl(url))
|
||||
if (validURl(url))
|
||||
{
|
||||
download(url, saveTo, onFinish);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (FileNotFoundException ex) {
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
//ignore 404s
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//print network errors but don't alert user
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
if (!found)
|
||||
{
|
||||
BCV.logE("Failed to download BCV v" + version);
|
||||
BytecodeViewer.showMessage("Unable to download BCV v" + version + ", please let Konloch know.");
|
||||
|
@ -262,11 +223,10 @@ public class UpdateCheck implements Runnable
|
|||
private static void download(String url, File saveTo, Runnable onFinish) throws Exception
|
||||
{
|
||||
BCV.log("Downloading from: " + url);
|
||||
BytecodeViewer.showMessage("Downloading the jar in the background, when it's finished you will be alerted with another message box."
|
||||
+ nl + nl + "Expect this to take several minutes.");
|
||||
BytecodeViewer.showMessage("Downloading the jar in the background, when it's finished you will be alerted with another message box." + nl + nl + "Expect this to take several minutes.");
|
||||
|
||||
try (InputStream is = new URL(url).openConnection().getInputStream();
|
||||
FileOutputStream fos = new FileOutputStream(saveTo)) {
|
||||
try (InputStream is = new URL(url).openConnection().getInputStream(); FileOutputStream fos = new FileOutputStream(saveTo))
|
||||
{
|
||||
byte[] buffer = new byte[8192];
|
||||
int len;
|
||||
int downloaded = 0;
|
||||
|
@ -284,7 +244,8 @@ public class UpdateCheck implements Runnable
|
|||
if (!flag)
|
||||
System.out.println("Downloaded " + mbs + "MBs so far");
|
||||
flag = true;
|
||||
} else
|
||||
}
|
||||
else
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,32 +18,38 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.bootloader.classtree;
|
||||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
/**
|
||||
* @author Bibl (don't ban me pls)
|
||||
* @since 25 May 2015 (actually before this)
|
||||
*/
|
||||
public class ClassHelper {
|
||||
public class ClassHelper
|
||||
{
|
||||
|
||||
public static Map<String, ClassNode> convertToMap(Collection<ClassNode> classes) {
|
||||
public static Map<String, ClassNode> convertToMap(Collection<ClassNode> classes)
|
||||
{
|
||||
Map<String, ClassNode> map = new HashMap<>();
|
||||
for (ClassNode cn : classes) {
|
||||
for (ClassNode cn : classes)
|
||||
{
|
||||
map.put(cn.name, cn);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static <T, K> Map<T, K> copyOf(Map<T, K> src) {
|
||||
public static <T, K> Map<T, K> copyOf(Map<T, K> src)
|
||||
{
|
||||
Map<T, K> dst = new HashMap<>();
|
||||
copy(src, dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
public static <T, K> void copy(Map<T, K> src, Map<T, K> dst) {
|
||||
public static <T, K> void copy(Map<T, K> src, Map<T, K> dst)
|
||||
{
|
||||
dst.putAll(src);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,17 +18,13 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.bootloader.classtree;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.classtree.nullpermablehashmap.NullPermeableHashMap;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.classtree.nullpermablehashmap.SetCreator;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.bootloader.classtree.ClassHelper.convertToMap;
|
||||
import static the.bytecode.club.bytecodeviewer.bootloader.classtree.ClassHelper.copyOf;
|
||||
|
||||
|
@ -36,24 +32,28 @@ import static the.bytecode.club.bytecodeviewer.bootloader.classtree.ClassHelper.
|
|||
* @author Bibl (don't ban me pls)
|
||||
* @since 25 May 2015 (actually before this)
|
||||
*/
|
||||
public class ClassTree {
|
||||
public class ClassTree
|
||||
{
|
||||
private static final SetCreator<ClassNode> SET_CREATOR = new SetCreator<>();
|
||||
|
||||
private final Map<String, ClassNode> classes;
|
||||
private final NullPermeableHashMap<ClassNode, Set<ClassNode>> supers;
|
||||
private final NullPermeableHashMap<ClassNode, Set<ClassNode>> delgates;
|
||||
|
||||
public ClassTree() {
|
||||
public ClassTree()
|
||||
{
|
||||
classes = new HashMap<>();
|
||||
supers = new NullPermeableHashMap<>(SET_CREATOR);
|
||||
delgates = new NullPermeableHashMap<>(SET_CREATOR);
|
||||
}
|
||||
|
||||
public ClassTree(Collection<ClassNode> classes) {
|
||||
public ClassTree(Collection<ClassNode> classes)
|
||||
{
|
||||
this(convertToMap(classes));
|
||||
}
|
||||
|
||||
public ClassTree(Map<String, ClassNode> classes_) {
|
||||
public ClassTree(Map<String, ClassNode> classes_)
|
||||
{
|
||||
classes = copyOf(classes_);
|
||||
supers = new NullPermeableHashMap<>(SET_CREATOR);
|
||||
delgates = new NullPermeableHashMap<>(SET_CREATOR);
|
||||
|
@ -62,9 +62,12 @@ public class ClassTree {
|
|||
}
|
||||
|
||||
// TODO: optimise
|
||||
public void build(Map<String, ClassNode> classes) {
|
||||
for (ClassNode node : classes.values()) {
|
||||
for (String iface : node.interfaces) {
|
||||
public void build(Map<String, ClassNode> classes)
|
||||
{
|
||||
for (ClassNode node : classes.values())
|
||||
{
|
||||
for (String iface : node.interfaces)
|
||||
{
|
||||
ClassNode ifacecs = classes.get(iface);
|
||||
if (ifacecs == null)
|
||||
continue;
|
||||
|
@ -77,10 +80,12 @@ public class ClassTree {
|
|||
getSupers0(node).addAll(superinterfaces);
|
||||
}
|
||||
ClassNode currentSuper = classes.get(node.superName);
|
||||
while (currentSuper != null) {
|
||||
while (currentSuper != null)
|
||||
{
|
||||
getDelegates0(currentSuper).add(node);
|
||||
getSupers0(node).add(currentSuper);
|
||||
for (String iface : currentSuper.interfaces) {
|
||||
for (String iface : currentSuper.interfaces)
|
||||
{
|
||||
ClassNode ifacecs = classes.get(iface);
|
||||
if (ifacecs == null)
|
||||
continue;
|
||||
|
@ -98,8 +103,10 @@ public class ClassTree {
|
|||
}
|
||||
}
|
||||
|
||||
public void build(ClassNode node) {
|
||||
for (String iface : node.interfaces) {
|
||||
public void build(ClassNode node)
|
||||
{
|
||||
for (String iface : node.interfaces)
|
||||
{
|
||||
ClassNode ifacecs = classes.get(iface);
|
||||
if (ifacecs == null)
|
||||
continue;
|
||||
|
@ -112,10 +119,12 @@ public class ClassTree {
|
|||
getSupers0(node).addAll(superinterfaces);
|
||||
}
|
||||
ClassNode currentSuper = classes.get(node.superName);
|
||||
while (currentSuper != null) {
|
||||
while (currentSuper != null)
|
||||
{
|
||||
getDelegates0(currentSuper).add(node);
|
||||
getSupers0(node).add(currentSuper);
|
||||
for (String iface : currentSuper.interfaces) {
|
||||
for (String iface : currentSuper.interfaces)
|
||||
{
|
||||
ClassNode ifacecs = classes.get(iface);
|
||||
if (ifacecs == null)
|
||||
continue;
|
||||
|
@ -134,12 +143,14 @@ public class ClassTree {
|
|||
classes.put(node.name, node);
|
||||
}
|
||||
|
||||
private void buildSubTree(Map<String, ClassNode> classes, Collection<ClassNode> superinterfaces,
|
||||
ClassNode current) {
|
||||
private void buildSubTree(Map<String, ClassNode> classes, Collection<ClassNode> superinterfaces, ClassNode current)
|
||||
{
|
||||
superinterfaces.add(current);
|
||||
for (String iface : current.interfaces) {
|
||||
for (String iface : current.interfaces)
|
||||
{
|
||||
ClassNode cs = classes.get(iface);
|
||||
if (cs != null) {
|
||||
if (cs != null)
|
||||
{
|
||||
getDelegates0(cs).add(current);
|
||||
buildSubTree(classes, superinterfaces, cs);
|
||||
} /*else {
|
||||
|
@ -148,11 +159,15 @@ public class ClassTree {
|
|||
}
|
||||
}
|
||||
|
||||
public Set<MethodNode> getMethodsFromSuper(ClassNode node, String name, String desc) {
|
||||
public Set<MethodNode> getMethodsFromSuper(ClassNode node, String name, String desc)
|
||||
{
|
||||
Set<MethodNode> methods = new HashSet<>();
|
||||
for (ClassNode super_ : getSupers(node)) {
|
||||
for (MethodNode mn : super_.methods) {
|
||||
if (mn.name.equals(name) && mn.desc.equals(desc)) {
|
||||
for (ClassNode super_ : getSupers(node))
|
||||
{
|
||||
for (MethodNode mn : super_.methods)
|
||||
{
|
||||
if (mn.name.equals(name) && mn.desc.equals(desc))
|
||||
{
|
||||
methods.add(mn);
|
||||
}
|
||||
}
|
||||
|
@ -160,11 +175,15 @@ public class ClassTree {
|
|||
return methods;
|
||||
}
|
||||
|
||||
public Set<MethodNode> getMethodsFromDelegates(ClassNode node, String name, String desc) {
|
||||
public Set<MethodNode> getMethodsFromDelegates(ClassNode node, String name, String desc)
|
||||
{
|
||||
Set<MethodNode> methods = new HashSet<>();
|
||||
for (ClassNode delegate : getDelegates(node)) {
|
||||
for (MethodNode mn : delegate.methods) {
|
||||
if (mn.name.equals(name) && mn.desc.equals(desc)) {
|
||||
for (ClassNode delegate : getDelegates(node))
|
||||
{
|
||||
for (MethodNode mn : delegate.methods)
|
||||
{
|
||||
if (mn.name.equals(name) && mn.desc.equals(desc))
|
||||
{
|
||||
methods.add(mn);
|
||||
}
|
||||
}
|
||||
|
@ -172,10 +191,14 @@ public class ClassTree {
|
|||
return methods;
|
||||
}
|
||||
|
||||
public MethodNode getFirstMethodFromSuper(ClassNode node, String name, String desc) {
|
||||
for (ClassNode super_ : getSupers(node)) {
|
||||
for (MethodNode mn : super_.methods) {
|
||||
if (mn.name.equals(name) && mn.desc.equals(desc)) {
|
||||
public MethodNode getFirstMethodFromSuper(ClassNode node, String name, String desc)
|
||||
{
|
||||
for (ClassNode super_ : getSupers(node))
|
||||
{
|
||||
for (MethodNode mn : super_.methods)
|
||||
{
|
||||
if (mn.name.equals(name) && mn.desc.equals(desc))
|
||||
{
|
||||
return mn;
|
||||
}
|
||||
}
|
||||
|
@ -183,32 +206,39 @@ public class ClassTree {
|
|||
return null;
|
||||
}
|
||||
|
||||
public ClassNode getClass(String name) {
|
||||
public ClassNode getClass(String name)
|
||||
{
|
||||
return classes.get(name);
|
||||
}
|
||||
|
||||
public boolean isInherited(ClassNode cn, String name, String desc) {
|
||||
public boolean isInherited(ClassNode cn, String name, String desc)
|
||||
{
|
||||
return getFirstMethodFromSuper(cn, name, desc) != null;
|
||||
}
|
||||
|
||||
private Set<ClassNode> getSupers0(ClassNode cn) {
|
||||
private Set<ClassNode> getSupers0(ClassNode cn)
|
||||
{
|
||||
return supers.getNonNull(cn);
|
||||
}
|
||||
|
||||
private Set<ClassNode> getDelegates0(ClassNode cn) {
|
||||
private Set<ClassNode> getDelegates0(ClassNode cn)
|
||||
{
|
||||
return delgates.getNonNull(cn);
|
||||
}
|
||||
|
||||
public Map<String, ClassNode> getClasses() {
|
||||
public Map<String, ClassNode> getClasses()
|
||||
{
|
||||
return classes;
|
||||
}
|
||||
|
||||
public Set<ClassNode> getSupers(ClassNode cn) {
|
||||
public Set<ClassNode> getSupers(ClassNode cn)
|
||||
{
|
||||
return Collections.unmodifiableSet(supers.get(cn));
|
||||
// return supers.get(cn);
|
||||
}
|
||||
|
||||
public Set<ClassNode> getDelegates(ClassNode cn) {
|
||||
public Set<ClassNode> getDelegates(ClassNode cn)
|
||||
{
|
||||
return Collections.unmodifiableSet(delgates.get(cn));
|
||||
// return delgates.get(cn);
|
||||
}
|
||||
|
|
|
@ -22,10 +22,12 @@ package the.bytecode.club.bytecodeviewer.bootloader.classtree.nullpermablehashma
|
|||
* @author Bibl (don't ban me pls)
|
||||
* @since ages ago
|
||||
*/
|
||||
public class NullCreator<V> implements ValueCreator<V> {
|
||||
public class NullCreator<V> implements ValueCreator<V>
|
||||
{
|
||||
|
||||
@Override
|
||||
public V create() {
|
||||
public V create()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -24,23 +24,28 @@ import java.util.HashMap;
|
|||
* @author Bibl (don't ban me pls)
|
||||
* @since ages ago
|
||||
*/
|
||||
public class NullPermeableHashMap<K, V> extends HashMap<K, V> {
|
||||
public class NullPermeableHashMap<K, V> extends HashMap<K, V>
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final ValueCreator<V> creator;
|
||||
|
||||
public NullPermeableHashMap(ValueCreator<V> creator) {
|
||||
public NullPermeableHashMap(ValueCreator<V> creator)
|
||||
{
|
||||
this.creator = creator;
|
||||
}
|
||||
|
||||
public NullPermeableHashMap() {
|
||||
public NullPermeableHashMap()
|
||||
{
|
||||
this(new NullCreator<>());
|
||||
}
|
||||
|
||||
public V getNonNull(K k) {
|
||||
public V getNonNull(K k)
|
||||
{
|
||||
V val = get(k);
|
||||
if (val == null) {
|
||||
if (val == null)
|
||||
{
|
||||
val = creator.create();
|
||||
put(k, val);
|
||||
}
|
||||
|
|
|
@ -25,10 +25,12 @@ import java.util.Set;
|
|||
* @author Bibl (don't ban me pls)
|
||||
* @since 25 May 2015 (actually before this)
|
||||
*/
|
||||
public class SetCreator<T> implements ValueCreator<Set<T>> {
|
||||
public class SetCreator<T> implements ValueCreator<Set<T>>
|
||||
{
|
||||
|
||||
@Override
|
||||
public Set<T> create() {
|
||||
public Set<T> create()
|
||||
{
|
||||
return new HashSet<>();
|
||||
}
|
||||
}
|
|
@ -22,7 +22,8 @@ package the.bytecode.club.bytecodeviewer.bootloader.classtree.nullpermablehashma
|
|||
* @author Bibl (don't ban me pls)
|
||||
* @since ages ago
|
||||
*/
|
||||
public interface ValueCreator<V> {
|
||||
public interface ValueCreator<V>
|
||||
{
|
||||
|
||||
V create();
|
||||
}
|
|
@ -18,58 +18,71 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.bootloader.loader;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.external.ExternalResource;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.external.ExternalResource;
|
||||
|
||||
/**
|
||||
* @author Bibl (don't ban me pls)
|
||||
* @since 21 Jul 2015 00:18:07
|
||||
*/
|
||||
public final class AbstractLoaderFactory {
|
||||
public final class AbstractLoaderFactory
|
||||
{
|
||||
|
||||
private static final String DEFAULT_KEY = "default-factory";
|
||||
private static final Map<String, LoaderFactory<?>> FACTORY_CACHE = new HashMap<>();
|
||||
|
||||
public static void register(LoaderFactory<?> factory) {
|
||||
public static void register(LoaderFactory<?> factory)
|
||||
{
|
||||
register(DEFAULT_KEY, factory);
|
||||
}
|
||||
|
||||
public static void register(String key, LoaderFactory<?> factory) {
|
||||
if (key == null || factory == null) {
|
||||
public static void register(String key, LoaderFactory<?> factory)
|
||||
{
|
||||
if (key == null || factory == null)
|
||||
{
|
||||
throw new IllegalArgumentException("null key or factory");
|
||||
}
|
||||
|
||||
if (FACTORY_CACHE.containsKey(key)) {
|
||||
if (FACTORY_CACHE.containsKey(key))
|
||||
{
|
||||
throw new IllegalArgumentException("factory already registered with key: " + key);
|
||||
}
|
||||
|
||||
FACTORY_CACHE.put(key, factory);
|
||||
}
|
||||
|
||||
public static void unregister(String key) {
|
||||
if (key == null) {
|
||||
public static void unregister(String key)
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
throw new IllegalArgumentException("null key");
|
||||
}
|
||||
|
||||
if (!FACTORY_CACHE.containsKey(key)) {
|
||||
if (!FACTORY_CACHE.containsKey(key))
|
||||
{
|
||||
throw new IllegalArgumentException("factory doesn't key for key: " + key);
|
||||
}
|
||||
|
||||
FACTORY_CACHE.remove(key);
|
||||
}
|
||||
|
||||
public static <T extends ExternalResource<?>> LoaderFactory<T> find() {
|
||||
public static <T extends ExternalResource<?>> LoaderFactory<T> find()
|
||||
{
|
||||
return find(DEFAULT_KEY);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends ExternalResource<?>> LoaderFactory<T> find(String key) {
|
||||
if (key == null) {
|
||||
public static <T extends ExternalResource<?>> LoaderFactory<T> find(String key)
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
throw new IllegalArgumentException("null key");
|
||||
}
|
||||
|
||||
if (!FACTORY_CACHE.containsKey(key)) {
|
||||
if (!FACTORY_CACHE.containsKey(key))
|
||||
{
|
||||
throw new IllegalArgumentException("factory doesn't key for key: " + key);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,21 +18,22 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.bootloader.loader;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.external.ExternalResource;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.external.ExternalResource;
|
||||
|
||||
/**
|
||||
* @author Bibl (don't ban me pls)
|
||||
* @since 21 Jul 2015 00:09:53
|
||||
*/
|
||||
public class ClassPathLoader implements ILoader<Object> {
|
||||
public class ClassPathLoader implements ILoader<Object>
|
||||
{
|
||||
|
||||
void extendClassPath(URL url) throws NoSuchMethodException, SecurityException, IllegalAccessException,
|
||||
IllegalArgumentException,
|
||||
InvocationTargetException {
|
||||
void extendClassPath(URL url) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
|
||||
{
|
||||
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
|
||||
Class<URLClassLoader> urlClass = URLClassLoader.class;
|
||||
Method method = urlClass.getDeclaredMethod("addURL", URL.class);
|
||||
|
@ -46,18 +47,24 @@ public class ClassPathLoader implements ILoader<Object> {
|
|||
* @see the.bytecode.club.bootloader.ILoader#bind(the.bytecode.club.bootloader .resource.ExternalResource)
|
||||
*/
|
||||
@Override
|
||||
public void bind(ExternalResource<Object> resource) {
|
||||
try {
|
||||
if (resource != null) {
|
||||
public void bind(ExternalResource<Object> resource)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (resource != null)
|
||||
{
|
||||
URL url = resource.getLocation();
|
||||
if (url != null) {
|
||||
if (url != null)
|
||||
{
|
||||
extendClassPath(url);
|
||||
}
|
||||
}
|
||||
}/* catch (IOException e) {
|
||||
System.err.println("Error loading resource.");
|
||||
e.printStackTrace();
|
||||
}*/ catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
}*/
|
||||
catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
|
||||
{
|
||||
System.err.println("Error reflecting URLClassLoader.addURL(URL) ?");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -69,7 +76,8 @@ public class ClassPathLoader implements ILoader<Object> {
|
|||
* @see the.bytecode.club.bootloader.ILoader#findClass(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException, NoClassDefFoundError {
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException, NoClassDefFoundError
|
||||
{
|
||||
return Class.forName(name);
|
||||
}
|
||||
|
||||
|
@ -79,7 +87,8 @@ public class ClassPathLoader implements ILoader<Object> {
|
|||
* @see the.bytecode.club.bootloader.ILoader#loadClass(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException, NoClassDefFoundError {
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException, NoClassDefFoundError
|
||||
{
|
||||
return findClass(name);
|
||||
}
|
||||
}
|
|
@ -24,7 +24,8 @@ import the.bytecode.club.bytecodeviewer.bootloader.resource.external.ExternalRes
|
|||
* @author Bibl (don't ban me pls)
|
||||
* @since 19 Jul 2015 02:29:43
|
||||
*/
|
||||
public interface ILoader<T> {
|
||||
public interface ILoader<T>
|
||||
{
|
||||
|
||||
void bind(ExternalResource<T> resource);
|
||||
|
||||
|
|
|
@ -18,12 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.bootloader.loader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
@ -31,20 +25,29 @@ import the.bytecode.club.bytecodeviewer.bootloader.classtree.ClassTree;
|
|||
import the.bytecode.club.bytecodeviewer.bootloader.resource.external.ExternalResource;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.jar.contents.JarContents;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Bibl (don't ban me pls)
|
||||
* @since 19 Jul 2015 02:48:41
|
||||
*
|
||||
* <p>
|
||||
* TODO: Resource loading
|
||||
*/
|
||||
@Deprecated
|
||||
public class LibraryClassLoader extends ClassLoader implements ILoader<JarContents<ClassNode>> {
|
||||
public class LibraryClassLoader extends ClassLoader implements ILoader<JarContents<ClassNode>>
|
||||
{
|
||||
|
||||
private final Set<JarContents<ClassNode>> binded;
|
||||
private final Map<String, Class<?>> classCache;
|
||||
private final ClassTree tree;
|
||||
|
||||
public LibraryClassLoader() {
|
||||
public LibraryClassLoader()
|
||||
{
|
||||
binded = new HashSet<>();
|
||||
classCache = new HashMap<>();
|
||||
tree = new ClassTree();
|
||||
|
@ -55,16 +58,23 @@ public class LibraryClassLoader extends ClassLoader implements ILoader<JarConten
|
|||
* .ExternalResource)
|
||||
*/
|
||||
@Override
|
||||
public void bind(ExternalResource<JarContents<ClassNode>> resource) {
|
||||
try {
|
||||
public void bind(ExternalResource<JarContents<ClassNode>> resource)
|
||||
{
|
||||
try
|
||||
{
|
||||
JarContents<ClassNode> contents = resource.load();
|
||||
if (contents != null) {
|
||||
if (contents != null)
|
||||
{
|
||||
binded.add(contents);
|
||||
tree.build(contents.getClassContents().namedMap());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Null contents?");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -73,21 +83,25 @@ public class LibraryClassLoader extends ClassLoader implements ILoader<JarConten
|
|||
* @see the.bytecode.club.bytecodeviewer.loadermodel.ILoader#loadClass(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException, NoClassDefFoundError {
|
||||
public Class<?> findClass(String name) throws ClassNotFoundException, NoClassDefFoundError
|
||||
{
|
||||
String byte_name = name.replace(".", "/");
|
||||
if (classCache.containsKey(byte_name))
|
||||
return classCache.get(byte_name);
|
||||
|
||||
ClassNode cn = null;
|
||||
for (JarContents<ClassNode> contents : binded) {
|
||||
for (JarContents<ClassNode> contents : binded)
|
||||
{
|
||||
cn = contents.getClassContents().namedMap().get(byte_name);
|
||||
if (cn != null)
|
||||
break;
|
||||
}
|
||||
|
||||
if (cn != null) {
|
||||
if (cn != null)
|
||||
{
|
||||
Class<?> klass = define(cn);
|
||||
if (klass != null) {
|
||||
if (klass != null)
|
||||
{
|
||||
classCache.put(byte_name, klass);
|
||||
return klass;
|
||||
}
|
||||
|
@ -96,39 +110,46 @@ public class LibraryClassLoader extends ClassLoader implements ILoader<JarConten
|
|||
return super.loadClass(name);
|
||||
}
|
||||
|
||||
protected Class<?> define(ClassNode cn) {
|
||||
protected Class<?> define(ClassNode cn)
|
||||
{
|
||||
ClassWriter writer = new ResolvingClassWriter(tree);
|
||||
cn.accept(cn);
|
||||
byte[] bytes = writer.toByteArray();
|
||||
return defineClass(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
public static class ResolvingClassWriter extends ClassWriter {
|
||||
public static class ResolvingClassWriter extends ClassWriter
|
||||
{
|
||||
|
||||
private final ClassTree classTree;
|
||||
|
||||
public ResolvingClassWriter(ClassTree classTree) {
|
||||
public ResolvingClassWriter(ClassTree classTree)
|
||||
{
|
||||
super(ClassWriter.COMPUTE_FRAMES);
|
||||
this.classTree = classTree;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
void update(Map<String, ClassNode> classes) {
|
||||
void update(Map<String, ClassNode> classes)
|
||||
{
|
||||
classTree.build(classes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCommonSuperClass(String type1, String type2) {
|
||||
protected String getCommonSuperClass(String type1, String type2)
|
||||
{
|
||||
ClassNode ccn = classTree.getClass(type1);
|
||||
ClassNode dcn = classTree.getClass(type2);
|
||||
|
||||
//System.out.println(type1 + " " + type2);
|
||||
if (ccn == null) {
|
||||
if (ccn == null)
|
||||
{
|
||||
classTree.build(createQuick(type1));
|
||||
return getCommonSuperClass(type1, type2);
|
||||
}
|
||||
|
||||
if (dcn == null) {
|
||||
if (dcn == null)
|
||||
{
|
||||
classTree.build(createQuick(type2));
|
||||
return getCommonSuperClass(type1, type2);
|
||||
}
|
||||
|
@ -142,10 +163,14 @@ public class LibraryClassLoader extends ClassLoader implements ILoader<JarConten
|
|||
if (d.contains(ccn))
|
||||
return type2;
|
||||
|
||||
if (Modifier.isInterface(ccn.access) || Modifier.isInterface(dcn.access)) {
|
||||
if (Modifier.isInterface(ccn.access) || Modifier.isInterface(dcn.access))
|
||||
{
|
||||
return "java/lang/Object";
|
||||
} else {
|
||||
do {
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
ClassNode nccn = classTree.getClass(ccn.superName);
|
||||
if (nccn == null)
|
||||
break;
|
||||
|
@ -156,13 +181,17 @@ public class LibraryClassLoader extends ClassLoader implements ILoader<JarConten
|
|||
}
|
||||
}
|
||||
|
||||
public ClassNode createQuick(String name) {
|
||||
try {
|
||||
public ClassNode createQuick(String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
ClassReader cr = new ClassReader(name);
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG);
|
||||
return cn;
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@ package the.bytecode.club.bytecodeviewer.bootloader.loader;
|
|||
* @author Bibl (don't ban me pls)
|
||||
* @since 21 Jul 2015 00:14:53
|
||||
*/
|
||||
public interface LoaderFactory<T> {
|
||||
public interface LoaderFactory<T>
|
||||
{
|
||||
|
||||
ILoader<T> spawnLoader();
|
||||
}
|
|
@ -26,19 +26,23 @@ import java.util.Map;
|
|||
* @author Bibl (don't ban me pls)
|
||||
* @since 21 Jul 2013
|
||||
*/
|
||||
public abstract class DataContainer<T> extends ArrayList<T> {
|
||||
public abstract class DataContainer<T> extends ArrayList<T>
|
||||
{
|
||||
|
||||
private static final long serialVersionUID = -9022506488647444546L;
|
||||
|
||||
public DataContainer() {
|
||||
public DataContainer()
|
||||
{
|
||||
this(16);
|
||||
}
|
||||
|
||||
public DataContainer(int cap) {
|
||||
public DataContainer(int cap)
|
||||
{
|
||||
super(cap);
|
||||
}
|
||||
|
||||
public DataContainer(Collection<T> data) {
|
||||
public DataContainer(Collection<T> data)
|
||||
{
|
||||
addAll(data);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,12 +24,14 @@ import java.net.URL;
|
|||
* @author Bibl (don't ban me pls)
|
||||
* @since 21 Jul 2015 00:29:11
|
||||
*/
|
||||
public class EmptyExternalResource<T> extends ExternalResource<T> {
|
||||
public class EmptyExternalResource<T> extends ExternalResource<T>
|
||||
{
|
||||
|
||||
/**
|
||||
* @param location
|
||||
*/
|
||||
public EmptyExternalResource(URL location) {
|
||||
public EmptyExternalResource(URL location)
|
||||
{
|
||||
super(location);
|
||||
}
|
||||
|
||||
|
@ -37,7 +39,8 @@ public class EmptyExternalResource<T> extends ExternalResource<T> {
|
|||
* @see the.bytecode.club.bootloader.resource.ExternalResource#load()
|
||||
*/
|
||||
@Override
|
||||
public T load() {
|
||||
public T load()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.bootloader.resource.external;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.jar.JarInfo;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.jar.JarResource;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.jar.contents.JarContents;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -27,43 +33,47 @@ import java.net.URL;
|
|||
import java.util.Enumeration;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.jar.JarInfo;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.jar.JarResource;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.jar.contents.JarContents;
|
||||
|
||||
/**
|
||||
* @author Bibl (don't ban me pls)
|
||||
* @since 19 Jul 2015 02:33:23
|
||||
*/
|
||||
public class ExternalLibrary extends ExternalResource<JarContents<ClassNode>> {
|
||||
public class ExternalLibrary extends ExternalResource<JarContents<ClassNode>>
|
||||
{
|
||||
|
||||
/**
|
||||
* @param location
|
||||
*/
|
||||
public ExternalLibrary(URL location) {
|
||||
public ExternalLibrary(URL location)
|
||||
{
|
||||
super(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param jar
|
||||
*/
|
||||
public ExternalLibrary(JarInfo jar) {
|
||||
public ExternalLibrary(JarInfo jar)
|
||||
{
|
||||
super(createJarURL(jar));
|
||||
}
|
||||
|
||||
public static URL createJarURL(JarInfo jar) {
|
||||
try {
|
||||
public static URL createJarURL(JarInfo jar)
|
||||
{
|
||||
try
|
||||
{
|
||||
return jar.formattedURL();
|
||||
} catch (MalformedURLException e) {
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] read(InputStream in) throws IOException {
|
||||
try (ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream()) {
|
||||
public static byte[] read(InputStream in) throws IOException
|
||||
{
|
||||
try (ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream())
|
||||
{
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = in.read(buffer)) != -1)
|
||||
|
@ -72,7 +82,8 @@ public class ExternalLibrary extends ExternalResource<JarContents<ClassNode>> {
|
|||
}
|
||||
}
|
||||
|
||||
protected ClassNode create(byte[] b) {
|
||||
protected ClassNode create(byte[] b)
|
||||
{
|
||||
ClassReader cr = new ClassReader(b);
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
|
@ -83,21 +94,27 @@ public class ExternalLibrary extends ExternalResource<JarContents<ClassNode>> {
|
|||
* @see the.bytecode.club.bytecodeviewer.loadermodel.ExternalResource#load()
|
||||
*/
|
||||
@Override
|
||||
public JarContents<ClassNode> load() throws IOException {
|
||||
public JarContents<ClassNode> load() throws IOException
|
||||
{
|
||||
JarContents<ClassNode> contents = new JarContents<>();
|
||||
|
||||
JarURLConnection con = (JarURLConnection) getLocation().openConnection();
|
||||
JarFile jar = con.getJarFile();
|
||||
|
||||
Enumeration<JarEntry> entries = jar.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
while (entries.hasMoreElements())
|
||||
{
|
||||
JarEntry entry = entries.nextElement();
|
||||
try (InputStream is = jar.getInputStream(entry)) {
|
||||
try (InputStream is = jar.getInputStream(entry))
|
||||
{
|
||||
byte[] bytes = read(is);
|
||||
if (entry.getName().endsWith(".class")) {
|
||||
if (entry.getName().endsWith(".class"))
|
||||
{
|
||||
ClassNode cn = create(bytes);
|
||||
contents.getClassContents().add(cn);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
JarResource resource = new JarResource(entry.getName(), bytes);
|
||||
contents.getResourceContents().add(resource);
|
||||
}
|
||||
|
|
|
@ -25,24 +25,28 @@ import java.net.URL;
|
|||
* @author Bibl (don't ban me pls)
|
||||
* @since 19 Jul 2015 02:30:30
|
||||
*/
|
||||
public abstract class ExternalResource<T> {
|
||||
public abstract class ExternalResource<T>
|
||||
{
|
||||
|
||||
private final URL location;
|
||||
|
||||
public ExternalResource(URL location) {
|
||||
public ExternalResource(URL location)
|
||||
{
|
||||
if (location == null)
|
||||
throw new IllegalArgumentException();
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public URL getLocation() {
|
||||
public URL getLocation()
|
||||
{
|
||||
return location;
|
||||
}
|
||||
|
||||
public abstract T load() throws IOException;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + location.hashCode();
|
||||
|
@ -50,7 +54,8 @@ public abstract class ExternalResource<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
|
@ -62,7 +67,8 @@ public abstract class ExternalResource<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public String toString()
|
||||
{
|
||||
return "Library @" + location.toExternalForm();
|
||||
}
|
||||
}
|
|
@ -29,7 +29,8 @@ import java.net.URL;
|
|||
* @author Bibl
|
||||
* @since 19 Jul 2013
|
||||
*/
|
||||
public class JarInfo {
|
||||
public class JarInfo
|
||||
{
|
||||
|
||||
private final String path;
|
||||
private final JarType type;
|
||||
|
@ -39,7 +40,8 @@ public class JarInfo {
|
|||
*
|
||||
* @param path Path to jar.
|
||||
*/
|
||||
public JarInfo(File path) {
|
||||
public JarInfo(File path)
|
||||
{
|
||||
this(path.getAbsolutePath(), JarType.FILE);
|
||||
}
|
||||
|
||||
|
@ -49,7 +51,8 @@ public class JarInfo {
|
|||
* @param path Path to jar.
|
||||
* @param type Type of jar.
|
||||
*/
|
||||
public JarInfo(String path, JarType type) {
|
||||
public JarInfo(String path, JarType type)
|
||||
{
|
||||
this.path = path;
|
||||
this.type = type;
|
||||
}
|
||||
|
@ -59,18 +62,21 @@ public class JarInfo {
|
|||
*
|
||||
* @param url URL to jar.
|
||||
*/
|
||||
public JarInfo(URL url) {
|
||||
public JarInfo(URL url)
|
||||
{
|
||||
this(url.toExternalForm(), JarType.WEB);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Real path to JarFile.
|
||||
*/
|
||||
public final String getPath() {
|
||||
public final String getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
public final JarType getType() {
|
||||
public final JarType getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -80,9 +86,11 @@ public class JarInfo {
|
|||
* @return The formatted url.
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public URL formattedURL() throws MalformedURLException {
|
||||
public URL formattedURL() throws MalformedURLException
|
||||
{
|
||||
StringBuilder sb = new StringBuilder().append("jar:").append(type.prefix()).append(path);
|
||||
if (type.equals(JarType.FILE) && !path.endsWith(".jar")) {
|
||||
if (type.equals(JarType.FILE) && !path.endsWith(".jar"))
|
||||
{
|
||||
File file = new File(path);
|
||||
if (!file.exists())
|
||||
sb.append(".jar");
|
||||
|
@ -92,7 +100,8 @@ public class JarInfo {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = (prime * result) + ((path == null) ? 0 : path.hashCode());
|
||||
|
@ -101,7 +110,8 @@ public class JarInfo {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
|
@ -109,10 +119,12 @@ public class JarInfo {
|
|||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
JarInfo other = (JarInfo) obj;
|
||||
if (path == null) {
|
||||
if (path == null)
|
||||
{
|
||||
if (other.path != null)
|
||||
return false;
|
||||
} else if (!path.equals(other.path))
|
||||
}
|
||||
else if (!path.equals(other.path))
|
||||
return false;
|
||||
return type == other.type;
|
||||
}
|
||||
|
|
|
@ -24,26 +24,31 @@ import java.util.Arrays;
|
|||
* @author Bibl (don't ban me pls)
|
||||
* @since 19 Jul 2013
|
||||
*/
|
||||
public class JarResource {
|
||||
public class JarResource
|
||||
{
|
||||
|
||||
private final String name;
|
||||
private final byte[] data;
|
||||
|
||||
public JarResource(String name, byte[] data) {
|
||||
public JarResource(String name, byte[] data)
|
||||
{
|
||||
this.name = name;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
public byte[] getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = (prime * result) + Arrays.hashCode(data);
|
||||
|
@ -52,7 +57,8 @@ public class JarResource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
|
@ -62,8 +68,11 @@ public class JarResource {
|
|||
JarResource other = (JarResource) obj;
|
||||
if (!Arrays.equals(data, other.data))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (name == null)
|
||||
{
|
||||
return other.name == null;
|
||||
} else return name.equals(other.name);
|
||||
}
|
||||
else
|
||||
return name.equals(other.name);
|
||||
}
|
||||
}
|
|
@ -24,7 +24,8 @@ package the.bytecode.club.bytecodeviewer.bootloader.resource.jar;
|
|||
* @author Bibl
|
||||
* @since 19 Jul 2013
|
||||
*/
|
||||
public enum JarType {
|
||||
public enum JarType
|
||||
{
|
||||
|
||||
/**
|
||||
* Local file
|
||||
|
@ -37,14 +38,16 @@ public enum JarType {
|
|||
|
||||
private final String prefix;
|
||||
|
||||
JarType(String prefix) {
|
||||
JarType(String prefix)
|
||||
{
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the prefix for the JarURLConnection.
|
||||
**/
|
||||
public String prefix() {
|
||||
public String prefix()
|
||||
{
|
||||
return prefix;
|
||||
}
|
||||
}
|
|
@ -18,49 +18,52 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.bootloader.resource.jar.contents;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.DataContainer;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.jar.JarResource;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Bibl (don't ban me pls)
|
||||
* @since 19 Jul 2013
|
||||
*/
|
||||
public class JarContents<C extends ClassNode> {
|
||||
public class JarContents<C extends ClassNode>
|
||||
{
|
||||
|
||||
private final DataContainer<C> classContents;
|
||||
private final DataContainer<JarResource> resourceContents;
|
||||
|
||||
public JarContents() {
|
||||
public JarContents()
|
||||
{
|
||||
classContents = new ClassNodeContainer<>();
|
||||
resourceContents = new ResourceContainer();
|
||||
}
|
||||
|
||||
public JarContents(DataContainer<C> classContents, DataContainer<JarResource> resourceContents) {
|
||||
public JarContents(DataContainer<C> classContents, DataContainer<JarResource> resourceContents)
|
||||
{
|
||||
this.classContents = classContents == null ? new ClassNodeContainer<>() : classContents;
|
||||
this.resourceContents = resourceContents == null ? new ResourceContainer() : resourceContents;
|
||||
}
|
||||
|
||||
public final DataContainer<C> getClassContents() {
|
||||
public final DataContainer<C> getClassContents()
|
||||
{
|
||||
return classContents;
|
||||
}
|
||||
|
||||
public final DataContainer<JarResource> getResourceContents() {
|
||||
public final DataContainer<JarResource> getResourceContents()
|
||||
{
|
||||
return resourceContents;
|
||||
}
|
||||
|
||||
public void merge(JarContents<C> contents) {
|
||||
public void merge(JarContents<C> contents)
|
||||
{
|
||||
classContents.addAll(contents.classContents);
|
||||
resourceContents.addAll(contents.resourceContents);
|
||||
}
|
||||
|
||||
public JarContents<C> add(JarContents<C> contents) {
|
||||
public JarContents<C> add(JarContents<C> contents)
|
||||
{
|
||||
List<C> c1 = classContents;
|
||||
List<C> c2 = contents.classContents;
|
||||
|
||||
|
@ -78,53 +81,66 @@ public class JarContents<C extends ClassNode> {
|
|||
return new JarContents<>(new ClassNodeContainer<>(c3), new ResourceContainer(r3));
|
||||
}
|
||||
|
||||
public static class ClassNodeContainer<C extends ClassNode> extends DataContainer<C> {
|
||||
public static class ClassNodeContainer<C extends ClassNode> extends DataContainer<C>
|
||||
{
|
||||
private static final long serialVersionUID = -6169578803641192235L;
|
||||
|
||||
private Map<String, C> lastMap = new HashMap<>();
|
||||
private boolean invalidated;
|
||||
|
||||
public ClassNodeContainer() {
|
||||
public ClassNodeContainer()
|
||||
{
|
||||
this(16);
|
||||
}
|
||||
|
||||
public ClassNodeContainer(int cap) {
|
||||
public ClassNodeContainer(int cap)
|
||||
{
|
||||
super(cap);
|
||||
}
|
||||
|
||||
public ClassNodeContainer(Collection<C> data) {
|
||||
public ClassNodeContainer(Collection<C> data)
|
||||
{
|
||||
super(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(C c) {
|
||||
public boolean add(C c)
|
||||
{
|
||||
invalidated = true;
|
||||
return super.add(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends C> c) {
|
||||
public boolean addAll(Collection<? extends C> c)
|
||||
{
|
||||
invalidated = true;
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object c) {
|
||||
public boolean remove(Object c)
|
||||
{
|
||||
invalidated = true;
|
||||
return super.remove(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, C> namedMap() {
|
||||
if (invalidated) {
|
||||
public Map<String, C> namedMap()
|
||||
{
|
||||
if (invalidated)
|
||||
{
|
||||
invalidated = false;
|
||||
Map<String, C> nodeMap = new HashMap<>();
|
||||
Iterator<C> it = iterator();
|
||||
while (it.hasNext()) {
|
||||
while (it.hasNext())
|
||||
{
|
||||
C cn = it.next();
|
||||
if (nodeMap.containsKey(cn.name)) {
|
||||
if (nodeMap.containsKey(cn.name))
|
||||
{
|
||||
it.remove();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeMap.put(cn.name, cn);
|
||||
}
|
||||
}
|
||||
|
@ -134,25 +150,31 @@ public class JarContents<C extends ClassNode> {
|
|||
}
|
||||
}
|
||||
|
||||
public static class ResourceContainer extends DataContainer<JarResource> {
|
||||
public static class ResourceContainer extends DataContainer<JarResource>
|
||||
{
|
||||
private static final long serialVersionUID = -6169578803641192235L;
|
||||
|
||||
public ResourceContainer() {
|
||||
public ResourceContainer()
|
||||
{
|
||||
this(16);
|
||||
}
|
||||
|
||||
public ResourceContainer(int cap) {
|
||||
public ResourceContainer(int cap)
|
||||
{
|
||||
super(cap);
|
||||
}
|
||||
|
||||
public ResourceContainer(List<JarResource> data) {
|
||||
public ResourceContainer(List<JarResource> data)
|
||||
{
|
||||
addAll(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, JarResource> namedMap() {
|
||||
public Map<String, JarResource> namedMap()
|
||||
{
|
||||
Map<String, JarResource> map = new HashMap<>();
|
||||
for (JarResource resource : this) {
|
||||
for (JarResource resource : this)
|
||||
{
|
||||
map.put(resource.getName(), resource);
|
||||
}
|
||||
return map;
|
||||
|
|
|
@ -18,31 +18,35 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.bootloader.resource.jar.contents;
|
||||
|
||||
import java.net.URL;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.DataContainer;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.jar.JarResource;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author Bibl (don't ban me pls)
|
||||
* @since 19 Jul 2013
|
||||
*/
|
||||
public class LocateableJarContents<C extends ClassNode> extends JarContents<C> {
|
||||
public class LocateableJarContents<C extends ClassNode> extends JarContents<C>
|
||||
{
|
||||
|
||||
private final URL[] jarUrls;
|
||||
|
||||
public LocateableJarContents(URL... jarUrls) {
|
||||
public LocateableJarContents(URL... jarUrls)
|
||||
{
|
||||
super();
|
||||
this.jarUrls = jarUrls;
|
||||
}
|
||||
|
||||
public LocateableJarContents(DataContainer<C> classContents, DataContainer<JarResource> resourceContents,
|
||||
URL... jarUrls) {
|
||||
public LocateableJarContents(DataContainer<C> classContents, DataContainer<JarResource> resourceContents, URL... jarUrls)
|
||||
{
|
||||
super(classContents, resourceContents);
|
||||
this.jarUrls = jarUrls;
|
||||
}
|
||||
|
||||
public URL[] getJarUrls() {
|
||||
public URL[] getJarUrls()
|
||||
{
|
||||
return jarUrls;
|
||||
}
|
||||
}
|
|
@ -29,14 +29,15 @@ import the.bytecode.club.bytecodeviewer.compilers.impl.SmaliAssembler;
|
|||
*/
|
||||
public enum Compiler
|
||||
{
|
||||
KRAKATAU_ASSEMBLER(new KrakatauAssembler()),
|
||||
SMALI_ASSEMBLER(new SmaliAssembler()),
|
||||
JAVA_COMPILER(new JavaCompiler()),
|
||||
KRAKATAU_ASSEMBLER(new KrakatauAssembler()), SMALI_ASSEMBLER(new SmaliAssembler()), JAVA_COMPILER(new JavaCompiler()),
|
||||
;
|
||||
|
||||
private final InternalCompiler compiler;
|
||||
|
||||
Compiler(InternalCompiler compiler) {this.compiler = compiler;}
|
||||
Compiler(InternalCompiler compiler)
|
||||
{
|
||||
this.compiler = compiler;
|
||||
}
|
||||
|
||||
public InternalCompiler getCompiler()
|
||||
{
|
||||
|
|
|
@ -18,11 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.compilers.impl;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import me.konloch.kontainer.io.DiskWriter;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||
|
@ -33,9 +28,9 @@ import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
|||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.SleepUtil;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
||||
import java.io.*;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
* Java Compiler
|
||||
|
@ -58,12 +53,14 @@ public class JavaCompiler extends InternalCompiler
|
|||
tempD.mkdirs();
|
||||
new File(fileStart2).mkdirs();
|
||||
|
||||
if (Configuration.javac.isEmpty() || !new File(Configuration.javac).exists()) {
|
||||
if (Configuration.javac.isEmpty() || !new File(Configuration.javac).exists())
|
||||
{
|
||||
BytecodeViewer.showMessage("You need to set your Javac path, this requires the JDK to be downloaded." + nl + "(C:/Program Files/Java/JDK_xx/bin/javac.exe)");
|
||||
ExternalResources.getSingleton().selectJavac();
|
||||
}
|
||||
|
||||
if (Configuration.javac.isEmpty() || !new File(Configuration.javac).exists()) {
|
||||
if (Configuration.javac.isEmpty() || !new File(Configuration.javac).exists())
|
||||
{
|
||||
BytecodeViewer.showMessage("You need to set Javac!");
|
||||
return null;
|
||||
}
|
||||
|
@ -72,25 +69,18 @@ public class JavaCompiler extends InternalCompiler
|
|||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), cp.getAbsolutePath());
|
||||
|
||||
boolean cont = true;
|
||||
try {
|
||||
try
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
ProcessBuilder pb;
|
||||
|
||||
if (Configuration.library.isEmpty()) {
|
||||
pb = new ProcessBuilder(
|
||||
Configuration.javac,
|
||||
"-d", fileStart2,
|
||||
"-classpath", cp.getAbsolutePath(),
|
||||
java.getAbsolutePath()
|
||||
);
|
||||
} else {
|
||||
pb = new ProcessBuilder(
|
||||
Configuration.javac,
|
||||
"-d", fileStart2,
|
||||
"-classpath",
|
||||
cp.getAbsolutePath() + System.getProperty("path.separator") + Configuration.library,
|
||||
java.getAbsolutePath()
|
||||
);
|
||||
if (Configuration.library.isEmpty())
|
||||
{
|
||||
pb = new ProcessBuilder(Configuration.javac, "-d", fileStart2, "-classpath", cp.getAbsolutePath(), java.getAbsolutePath());
|
||||
}
|
||||
else
|
||||
{
|
||||
pb = new ProcessBuilder(Configuration.javac, "-d", fileStart2, "-classpath", cp.getAbsolutePath() + System.getProperty("path.separator") + Configuration.library, java.getAbsolutePath());
|
||||
}
|
||||
|
||||
Process process = pb.start();
|
||||
|
@ -112,18 +102,16 @@ public class JavaCompiler extends InternalCompiler
|
|||
int exitValue = process.waitFor();
|
||||
|
||||
//Read out dir output
|
||||
try (InputStream is = process.getInputStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr)) {
|
||||
try (InputStream is = process.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
log.append(nl).append(line);
|
||||
}
|
||||
|
||||
log.append(nl).append(nl).append(TranslatedStrings.ERROR2).append(nl).append(nl);
|
||||
try (InputStream is = process.getErrorStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr)) {
|
||||
try (InputStream is = process.getErrorStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
log.append(nl).append(line);
|
||||
|
@ -134,7 +122,9 @@ public class JavaCompiler extends InternalCompiler
|
|||
|
||||
if (!clazz.exists())
|
||||
throw new Exception(log.toString());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
cont = false;
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -142,9 +132,12 @@ public class JavaCompiler extends InternalCompiler
|
|||
cp.delete();
|
||||
|
||||
if (cont)
|
||||
try {
|
||||
try
|
||||
{
|
||||
return org.apache.commons.io.FileUtils.readFileToByteArray(clazz);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
//BytecodeViewer.handleException(e);
|
||||
}
|
||||
|
|
|
@ -18,11 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.compilers.impl;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Objects;
|
||||
import me.konloch.kontainer.io.DiskWriter;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
@ -35,9 +30,13 @@ import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
|||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.krakatauWorkingDirectory;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Objects;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
* Krakatau Java assembler, requires Python 2.7
|
||||
|
@ -49,7 +48,7 @@ public class KrakatauAssembler extends InternalCompiler
|
|||
@Override
|
||||
public byte[] compile(String contents, String fullyQualifiedName)
|
||||
{
|
||||
if(!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
if (!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
return null;
|
||||
|
||||
File tempD = new File(Constants.tempDirectory + fs + MiscUtils.randomString(32) + fs);
|
||||
|
@ -69,34 +68,26 @@ public class KrakatauAssembler extends InternalCompiler
|
|||
try
|
||||
{
|
||||
String[] pythonCommands = new String[]{Configuration.python2};
|
||||
if(Configuration.python2Extra)
|
||||
if (Configuration.python2Extra)
|
||||
pythonCommands = ArrayUtils.addAll(pythonCommands, "-2");
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
|
||||
pythonCommands,
|
||||
"-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "assemble.py",
|
||||
"-out",
|
||||
tempDirectory.getAbsolutePath(),
|
||||
tempJ.getAbsolutePath()
|
||||
));
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(pythonCommands, "-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "assemble.py", "-out", tempDirectory.getAbsolutePath(), tempJ.getAbsolutePath()));
|
||||
|
||||
Process process = pb.start();
|
||||
BytecodeViewer.createdProcesses.add(process);
|
||||
|
||||
//Read out dir output
|
||||
try (InputStream is = process.getInputStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr)) {
|
||||
try (InputStream is = process.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
log.append(nl).append(line);
|
||||
}
|
||||
|
||||
log.append(nl).append(nl).append(TranslatedStrings.ERROR2).append(nl).append(nl);
|
||||
try (InputStream is = process.getErrorStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr)) {
|
||||
try (InputStream is = process.getErrorStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
log.append(nl).append(line);
|
||||
|
@ -106,12 +97,13 @@ public class KrakatauAssembler extends InternalCompiler
|
|||
log.append(nl).append(nl).append(TranslatedStrings.EXIT_VALUE_IS).append(" ").append(exitValue);
|
||||
System.err.println(log);
|
||||
|
||||
byte[] b = FileUtils.readFileToByteArray(Objects.requireNonNull(
|
||||
ExternalResources.getSingleton().findFile(tempDirectory, ".class")));
|
||||
byte[] b = FileUtils.readFileToByteArray(Objects.requireNonNull(ExternalResources.getSingleton().findFile(tempDirectory, ".class")));
|
||||
tempDirectory.delete();
|
||||
tempJar.delete();
|
||||
return b;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
//BytecodeViewer.handleException(log.toString());
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.compilers.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Objects;
|
||||
import me.konloch.kontainer.io.DiskWriter;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
@ -29,6 +27,9 @@ import the.bytecode.club.bytecodeviewer.util.Enjarify;
|
|||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.ZipUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Objects;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
||||
|
||||
|
@ -54,17 +55,22 @@ public class SmaliAssembler extends InternalCompiler
|
|||
File tempJar = new File(fileStart + fileNumber + ".jar");
|
||||
File tempJarFolder = new File(fileStart + fileNumber + "-jar" + fs);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
DiskWriter.replaceFile(tempSmali.getAbsolutePath(), contents, false);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
//BytecodeViewer.handleException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
com.googlecode.d2j.smali.SmaliCmd.main(tempSmaliFolder.getAbsolutePath(),
|
||||
"-o", tempDex.getAbsolutePath());
|
||||
} catch (Exception e) {
|
||||
try
|
||||
{
|
||||
com.googlecode.d2j.smali.SmaliCmd.main(tempSmaliFolder.getAbsolutePath(), "-o", tempDex.getAbsolutePath());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
//BytecodeViewer.handleException(e);
|
||||
}
|
||||
|
@ -77,14 +83,16 @@ public class SmaliAssembler extends InternalCompiler
|
|||
|
||||
System.out.println("Temporary dex: " + tempDex.getAbsolutePath());
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
System.out.println("Unzipping to " + tempJarFolder.getAbsolutePath());
|
||||
ZipUtils.unzipFilesToPath(tempJar.getAbsolutePath(), tempJarFolder.getAbsolutePath());
|
||||
|
||||
File outputClass = null;
|
||||
boolean found = false;
|
||||
File current = tempJarFolder;
|
||||
try {
|
||||
try
|
||||
{
|
||||
while (!found)
|
||||
{
|
||||
File f = Objects.requireNonNull(current.listFiles())[0];
|
||||
|
@ -100,8 +108,13 @@ public class SmaliAssembler extends InternalCompiler
|
|||
System.out.println("Saved as: " + outputClass.getAbsolutePath());
|
||||
|
||||
return FileUtils.readFileToByteArray(outputClass);
|
||||
} catch (java.lang.NullPointerException ignored) { }
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (java.lang.NullPointerException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
//BytecodeViewer.handleException(e);
|
||||
}
|
||||
|
|
|
@ -29,20 +29,7 @@ public enum Decompiler
|
|||
{
|
||||
//TODO WARNING: do not change the decompiler order, when adding a new decompiler just add it to the end
|
||||
// enum ordinal is used for settings serialization instead of the enum name
|
||||
NONE("None", "", null),
|
||||
PROCYON_DECOMPILER("Procyon Decompiler", "proycon", new ProcyonDecompiler()),
|
||||
CFR_DECOMPILER("CFR Decompiler", "cfr", new CFRDecompiler()),
|
||||
FERNFLOWER_DECOMPILER("FernFlower Decompiler", "fernflower", new FernFlowerDecompiler()),
|
||||
BYTECODE_DISASSEMBLER("Bytecode Disassembler", "bcvbd", new BytecodeDisassembler()),
|
||||
HEXCODE_VIEWER("Hexcode Viewer", "bcvhex", null),
|
||||
SMALI_DISASSEMBLER("Smali Disassembler", "smali", new SmaliDisassembler()),
|
||||
KRAKATAU_DECOMPILER("Krakatau Decompiler", "krakatau", new KrakatauDecompiler()),
|
||||
KRAKATAU_DISASSEMBLER("Krakatau Disassembler", "krakataud", new KrakatauDisassembler()),
|
||||
JD_DECOMPILER("JD-GUI Decompiler", "jdgui", new JDGUIDecompiler()),
|
||||
JADX_DECOMPILER("JADX Decompiler", "jadx", new JADXDecompiler()),
|
||||
ASM_TEXTIFY_DISASSEMBLER("ASM Disassembler", "asm", new ASMTextifierDisassembler()),
|
||||
ASMIFIER_DECOMPILER("ASMifier Generator", "asmifier", new ASMifierGenerator()),
|
||||
JAVAP_DISASSEMBLER("Javap Disassembler", "javap", new JavapDisassembler()),
|
||||
NONE("None", "", null), PROCYON_DECOMPILER("Procyon Decompiler", "proycon", new ProcyonDecompiler()), CFR_DECOMPILER("CFR Decompiler", "cfr", new CFRDecompiler()), FERNFLOWER_DECOMPILER("FernFlower Decompiler", "fernflower", new FernFlowerDecompiler()), BYTECODE_DISASSEMBLER("Bytecode Disassembler", "bcvbd", new BytecodeDisassembler()), HEXCODE_VIEWER("Hexcode Viewer", "bcvhex", null), SMALI_DISASSEMBLER("Smali Disassembler", "smali", new SmaliDisassembler()), KRAKATAU_DECOMPILER("Krakatau Decompiler", "krakatau", new KrakatauDecompiler()), KRAKATAU_DISASSEMBLER("Krakatau Disassembler", "krakataud", new KrakatauDisassembler()), JD_DECOMPILER("JD-GUI Decompiler", "jdgui", new JDGUIDecompiler()), JADX_DECOMPILER("JADX Decompiler", "jadx", new JADXDecompiler()), ASM_TEXTIFY_DISASSEMBLER("ASM Disassembler", "asm", new ASMTextifierDisassembler()), ASMIFIER_DECOMPILER("ASMifier Generator", "asmifier", new ASMifierGenerator()), JAVAP_DISASSEMBLER("Javap Disassembler", "javap", new JavapDisassembler()),
|
||||
;
|
||||
|
||||
private final String decompilerName;
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.objectweb.asm.Attribute;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
@ -28,6 +26,9 @@ import org.objectweb.asm.tree.InnerClassNode;
|
|||
import org.objectweb.asm.tree.MethodNode;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
|
||||
/**
|
||||
|
@ -37,24 +38,26 @@ import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
|||
|
||||
public class ClassNodeDecompiler
|
||||
{
|
||||
public static PrefixedStringBuilder decompile(
|
||||
PrefixedStringBuilder sb, List<String> decompiledClasses,
|
||||
ClassNode cn) {
|
||||
public static PrefixedStringBuilder decompile(PrefixedStringBuilder sb, List<String> decompiledClasses, ClassNode cn)
|
||||
{
|
||||
List<String> unableToDecompile = new ArrayList<>();
|
||||
decompiledClasses.add(cn.name);
|
||||
sb.append(getAccessString(cn.access));
|
||||
sb.append(" ");
|
||||
sb.append(cn.name);
|
||||
if (cn.superName != null && !cn.superName.equals("java/lang/Object")) {
|
||||
if (cn.superName != null && !cn.superName.equals("java/lang/Object"))
|
||||
{
|
||||
sb.append(" extends ");
|
||||
sb.append(cn.superName);
|
||||
}
|
||||
|
||||
int amountOfInterfaces = cn.interfaces.size();
|
||||
if (amountOfInterfaces > 0) {
|
||||
if (amountOfInterfaces > 0)
|
||||
{
|
||||
sb.append(" implements ");
|
||||
sb.append(cn.interfaces.get(0));
|
||||
for (int i = 1; i < amountOfInterfaces; i++) {
|
||||
for (int i = 1; i < amountOfInterfaces; i++)
|
||||
{
|
||||
sb.append(", ");
|
||||
sb.append(cn.interfaces.get(i));
|
||||
}
|
||||
|
@ -65,66 +68,80 @@ public class ClassNodeDecompiler
|
|||
sb.append("<ClassVersion=" + cn.version + ">");
|
||||
sb.append(nl);
|
||||
|
||||
if (cn.sourceDebug != null) {
|
||||
if (cn.sourceDebug != null)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append("<SourceDebug=" + cn.sourceDebug + ">");
|
||||
sb.append(nl);
|
||||
}
|
||||
|
||||
if (cn.sourceFile != null) {
|
||||
if (cn.sourceFile != null)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append("<SourceFile=" + cn.sourceFile + ">");
|
||||
sb.append(nl);
|
||||
}
|
||||
|
||||
if (cn.signature != null) {
|
||||
if (cn.signature != null)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append("<Sig=" + cn.signature + ">");
|
||||
}
|
||||
|
||||
for (FieldNode fn : cn.fields) {
|
||||
for (FieldNode fn : cn.fields)
|
||||
{
|
||||
sb.append(nl);
|
||||
sb.append(" ");
|
||||
FieldNodeDecompiler.decompile(sb, fn);
|
||||
}
|
||||
if (cn.fields.size() > 0) {
|
||||
if (cn.fields.size() > 0)
|
||||
{
|
||||
sb.append(nl);
|
||||
}
|
||||
for (MethodNode mn : cn.methods) {
|
||||
for (MethodNode mn : cn.methods)
|
||||
{
|
||||
sb.append(nl);
|
||||
MethodNodeDecompiler.decompile(sb, mn, cn);
|
||||
}
|
||||
|
||||
for (InnerClassNode o : cn.innerClasses) {
|
||||
for (InnerClassNode o : cn.innerClasses)
|
||||
{
|
||||
String innerClassName = o.name;
|
||||
if ((innerClassName != null)
|
||||
&& !decompiledClasses.contains(innerClassName)) {
|
||||
if ((innerClassName != null) && !decompiledClasses.contains(innerClassName))
|
||||
{
|
||||
decompiledClasses.add(innerClassName);
|
||||
ClassNode cn1 = BytecodeViewer.blindlySearchForClassNode(innerClassName);
|
||||
if (cn1 != null) {
|
||||
if (cn1 != null)
|
||||
{
|
||||
sb.appendPrefix(" ");
|
||||
sb.append(nl + nl);
|
||||
sb = decompile(sb, decompiledClasses, cn1);
|
||||
sb.trimPrefix(5);
|
||||
sb.append(nl);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
unableToDecompile.add(innerClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!unableToDecompile.isEmpty()) {
|
||||
if (!unableToDecompile.isEmpty())
|
||||
{
|
||||
sb.append("// The following inner classes couldn't be decompiled: ");
|
||||
for (String s : unableToDecompile) {
|
||||
for (String s : unableToDecompile)
|
||||
{
|
||||
sb.append(s);
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(nl);
|
||||
}
|
||||
|
||||
if (cn.attrs != null) {
|
||||
if (cn.attrs != null)
|
||||
{
|
||||
sb.append(nl);
|
||||
for (Attribute attr : cn.attrs) {
|
||||
for (Attribute attr : cn.attrs)
|
||||
{
|
||||
//TODO: finish attributes
|
||||
sb.append(attr.type + ": ");// + attr.content.toString());
|
||||
}
|
||||
|
@ -137,7 +154,8 @@ public class ClassNodeDecompiler
|
|||
return sb;
|
||||
}
|
||||
|
||||
public static String getAccessString(int access) {
|
||||
public static String getAccessString(int access)
|
||||
{
|
||||
List<String> tokens = new ArrayList<>();
|
||||
if ((access & Opcodes.ACC_PUBLIC) != 0)
|
||||
tokens.add("public");
|
||||
|
@ -159,13 +177,13 @@ public class ClassNodeDecompiler
|
|||
tokens.add("enum");
|
||||
if ((access & Opcodes.ACC_ANNOTATION) != 0)
|
||||
tokens.add("annotation");
|
||||
if (!tokens.contains("interface") && !tokens.contains("enum")
|
||||
&& !tokens.contains("annotation"))
|
||||
if (!tokens.contains("interface") && !tokens.contains("enum") && !tokens.contains("annotation"))
|
||||
tokens.add("class");
|
||||
|
||||
// hackery delimeters
|
||||
StringBuilder sb = new StringBuilder(tokens.get(0));
|
||||
for (int i = 1; i < tokens.size(); i++) {
|
||||
for (int i = 1; i < tokens.size(); i++)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(tokens.get(i));
|
||||
}
|
||||
|
|
|
@ -18,21 +18,23 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
* @author Bibl
|
||||
*/
|
||||
|
||||
public class FieldNodeDecompiler {
|
||||
public class FieldNodeDecompiler
|
||||
{
|
||||
|
||||
public static PrefixedStringBuilder decompile(PrefixedStringBuilder sb,
|
||||
FieldNode f) {
|
||||
public static PrefixedStringBuilder decompile(PrefixedStringBuilder sb, FieldNode f)
|
||||
{
|
||||
String s = getAccessString(f.access);
|
||||
sb.append(s);
|
||||
if (s.length() > 0)
|
||||
|
@ -40,13 +42,17 @@ public class FieldNodeDecompiler {
|
|||
sb.append(Type.getType(f.desc).getClassName());
|
||||
sb.append(" ");
|
||||
sb.append(f.name);
|
||||
if (f.value != null) {
|
||||
if (f.value != null)
|
||||
{
|
||||
sb.append(" = ");
|
||||
if (f.value instanceof String) {
|
||||
if (f.value instanceof String)
|
||||
{
|
||||
sb.append("\"");
|
||||
sb.append(f.value);
|
||||
sb.append("\"");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(f.value);
|
||||
sb.append(" (");
|
||||
sb.append(f.value.getClass().getCanonicalName());
|
||||
|
@ -57,7 +63,8 @@ public class FieldNodeDecompiler {
|
|||
return sb;
|
||||
}
|
||||
|
||||
private static String getAccessString(int access) {
|
||||
private static String getAccessString(int access)
|
||||
{
|
||||
List<String> tokens = new ArrayList<>();
|
||||
if ((access & Opcodes.ACC_PUBLIC) != 0)
|
||||
tokens.add("public");
|
||||
|
@ -79,7 +86,8 @@ public class FieldNodeDecompiler {
|
|||
return "";
|
||||
// hackery delimeters
|
||||
StringBuilder sb = new StringBuilder(tokens.get(0));
|
||||
for (int i = 1; i < tokens.size(); i++) {
|
||||
for (int i = 1; i < tokens.size(); i++)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(tokens.get(i));
|
||||
}
|
||||
|
|
|
@ -20,35 +20,19 @@ package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
|||
|
||||
import eu.bibl.banalysis.filter.InstructionFilter;
|
||||
import eu.bibl.banalysis.filter.OpcodeFilter;
|
||||
import eu.bibl.banalysis.filter.insn.FieldInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.IincInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.InsnInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.JumpInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.LdcInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.MethodInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.MultiANewArrayInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.TypeInstructionFilter;
|
||||
import eu.bibl.banalysis.filter.insn.VarInstructionFilter;
|
||||
import java.util.Arrays;
|
||||
import eu.bibl.banalysis.filter.insn.*;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.IincInsnNode;
|
||||
import org.objectweb.asm.tree.InsnNode;
|
||||
import org.objectweb.asm.tree.JumpInsnNode;
|
||||
import org.objectweb.asm.tree.LabelNode;
|
||||
import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MultiANewArrayInsnNode;
|
||||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
import org.objectweb.asm.tree.VarInsnNode;
|
||||
import org.objectweb.asm.tree.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Pattern filter holder and stepper.
|
||||
*
|
||||
* @author Bibl
|
||||
*/
|
||||
public class InstructionPattern implements Opcodes {
|
||||
public class InstructionPattern implements Opcodes
|
||||
{
|
||||
|
||||
/**
|
||||
* Last instruction-match position pointer
|
||||
|
@ -68,7 +52,8 @@ public class InstructionPattern implements Opcodes {
|
|||
*
|
||||
* @param insns {@link AbstractInsnNode} pattern array.
|
||||
*/
|
||||
public InstructionPattern(AbstractInsnNode[] insns) {
|
||||
public InstructionPattern(AbstractInsnNode[] insns)
|
||||
{
|
||||
filters = translate(insns);
|
||||
lastMatch = new AbstractInsnNode[insns.length];
|
||||
}
|
||||
|
@ -78,10 +63,12 @@ public class InstructionPattern implements Opcodes {
|
|||
*
|
||||
* @param opcodes Opcodes to convert to {@link OpcodeFilter}s.
|
||||
*/
|
||||
public InstructionPattern(int[] opcodes) {
|
||||
public InstructionPattern(int[] opcodes)
|
||||
{
|
||||
filters = new InstructionFilter[opcodes.length];
|
||||
lastMatch = new AbstractInsnNode[opcodes.length];
|
||||
for (int i = 0; i < opcodes.length; i++) {
|
||||
for (int i = 0; i < opcodes.length; i++)
|
||||
{
|
||||
filters[i] = new OpcodeFilter(opcodes[i]);
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +78,8 @@ public class InstructionPattern implements Opcodes {
|
|||
*
|
||||
* @param filters User-defined {@link InstructionFilter}s.
|
||||
*/
|
||||
public InstructionPattern(InstructionFilter[] filters) {
|
||||
public InstructionPattern(InstructionFilter[] filters)
|
||||
{
|
||||
this.filters = filters;
|
||||
lastMatch = new AbstractInsnNode[filters.length];
|
||||
}
|
||||
|
@ -103,18 +91,23 @@ public class InstructionPattern implements Opcodes {
|
|||
* @param ain {@link AbstractInsnNode} to check.
|
||||
* @return True if this instruction successfully completed the pattern.
|
||||
*/
|
||||
public boolean accept(AbstractInsnNode ain) {
|
||||
public boolean accept(AbstractInsnNode ain)
|
||||
{
|
||||
if (pointer >= filters.length)
|
||||
reset();
|
||||
|
||||
InstructionFilter filter = filters[pointer];
|
||||
if (filter.accept(ain)) {
|
||||
if (filter.accept(ain))
|
||||
{
|
||||
lastMatch[pointer] = ain;
|
||||
if (pointer >= (filters.length - 1)) {
|
||||
if (pointer >= (filters.length - 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
pointer++;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
reset();
|
||||
}
|
||||
return false;
|
||||
|
@ -124,14 +117,16 @@ public class InstructionPattern implements Opcodes {
|
|||
* @return Last pattern sequence match equivilent from the inputted
|
||||
* {@link AbstractInsnNode}s.
|
||||
*/
|
||||
public AbstractInsnNode[] getLastMatch() {
|
||||
public AbstractInsnNode[] getLastMatch()
|
||||
{
|
||||
return lastMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the instruction pointer and clears the last match cache data.
|
||||
*/
|
||||
public void resetMatch() {
|
||||
public void resetMatch()
|
||||
{
|
||||
reset();
|
||||
AbstractInsnNode[] match = lastMatch;
|
||||
lastMatch = new AbstractInsnNode[match.length];
|
||||
|
@ -140,7 +135,8 @@ public class InstructionPattern implements Opcodes {
|
|||
/**
|
||||
* Sets the current instruction pointer to 0 (start of pattern).
|
||||
*/
|
||||
public void reset() {
|
||||
public void reset()
|
||||
{
|
||||
pointer = 0;
|
||||
}
|
||||
|
||||
|
@ -151,9 +147,11 @@ public class InstructionPattern implements Opcodes {
|
|||
* @param ains {@link AbstractInsnNode}s to convert.
|
||||
* @return Array of {@link InstructionFilter}s.
|
||||
*/
|
||||
public static InstructionFilter[] translate(AbstractInsnNode[] ains) {
|
||||
public static InstructionFilter[] translate(AbstractInsnNode[] ains)
|
||||
{
|
||||
InstructionFilter[] filters = new InstructionFilter[ains.length];
|
||||
for (int i = 0; i < ains.length; i++) {
|
||||
for (int i = 0; i < ains.length; i++)
|
||||
{
|
||||
filters[i] = translate(ains[i]);
|
||||
}
|
||||
return filters;
|
||||
|
@ -166,52 +164,64 @@ public class InstructionPattern implements Opcodes {
|
|||
* @param ain Instruction to convert.
|
||||
* @return A filter an an equivilent to the inputted instruction.
|
||||
*/
|
||||
public static InstructionFilter translate(AbstractInsnNode ain) {
|
||||
if (ain instanceof LdcInsnNode) {
|
||||
public static InstructionFilter translate(AbstractInsnNode ain)
|
||||
{
|
||||
if (ain instanceof LdcInsnNode)
|
||||
{
|
||||
return new LdcInstructionFilter(((LdcInsnNode) ain).cst);
|
||||
} else if (ain instanceof TypeInsnNode) {
|
||||
return new TypeInstructionFilter(ain.getOpcode(),
|
||||
((TypeInsnNode) ain).desc);
|
||||
} else if (ain instanceof FieldInsnNode) {
|
||||
return new FieldInstructionFilter(ain.getOpcode(),
|
||||
((FieldInsnNode) ain).owner, ((FieldInsnNode) ain).name,
|
||||
((FieldInsnNode) ain).desc);
|
||||
} else if (ain instanceof MethodInsnNode) {
|
||||
return new MethodInstructionFilter(ain.getOpcode(),
|
||||
((MethodInsnNode) ain).owner, ((MethodInsnNode) ain).name,
|
||||
((MethodInsnNode) ain).desc);
|
||||
} else if (ain instanceof VarInsnNode) {
|
||||
return new VarInstructionFilter(ain.getOpcode(),
|
||||
((VarInsnNode) ain).var);
|
||||
} else if (ain instanceof InsnNode) {
|
||||
}
|
||||
else if (ain instanceof TypeInsnNode)
|
||||
{
|
||||
return new TypeInstructionFilter(ain.getOpcode(), ((TypeInsnNode) ain).desc);
|
||||
}
|
||||
else if (ain instanceof FieldInsnNode)
|
||||
{
|
||||
return new FieldInstructionFilter(ain.getOpcode(), ((FieldInsnNode) ain).owner, ((FieldInsnNode) ain).name, ((FieldInsnNode) ain).desc);
|
||||
}
|
||||
else if (ain instanceof MethodInsnNode)
|
||||
{
|
||||
return new MethodInstructionFilter(ain.getOpcode(), ((MethodInsnNode) ain).owner, ((MethodInsnNode) ain).name, ((MethodInsnNode) ain).desc);
|
||||
}
|
||||
else if (ain instanceof VarInsnNode)
|
||||
{
|
||||
return new VarInstructionFilter(ain.getOpcode(), ((VarInsnNode) ain).var);
|
||||
}
|
||||
else if (ain instanceof InsnNode)
|
||||
{
|
||||
return new InsnInstructionFilter(ain.getOpcode());
|
||||
} else if (ain instanceof IincInsnNode) {
|
||||
return new IincInstructionFilter(((IincInsnNode) ain).incr,
|
||||
((IincInsnNode) ain).var);
|
||||
} else if (ain instanceof JumpInsnNode) {
|
||||
}
|
||||
else if (ain instanceof IincInsnNode)
|
||||
{
|
||||
return new IincInstructionFilter(((IincInsnNode) ain).incr, ((IincInsnNode) ain).var);
|
||||
}
|
||||
else if (ain instanceof JumpInsnNode)
|
||||
{
|
||||
return new JumpInstructionFilter(ain.getOpcode());
|
||||
} else if (ain instanceof LabelNode) {
|
||||
}
|
||||
else if (ain instanceof LabelNode)
|
||||
{
|
||||
return InstructionFilter.ACCEPT_ALL; // TODO: Cache labels and
|
||||
// check. // TODO: That's a
|
||||
// fucking stupid idea.
|
||||
} else if (ain instanceof MultiANewArrayInsnNode) {
|
||||
return new MultiANewArrayInstructionFilter(
|
||||
((MultiANewArrayInsnNode) ain).desc,
|
||||
((MultiANewArrayInsnNode) ain).dims);
|
||||
} else {
|
||||
}
|
||||
else if (ain instanceof MultiANewArrayInsnNode)
|
||||
{
|
||||
return new MultiANewArrayInstructionFilter(((MultiANewArrayInsnNode) ain).desc, ((MultiANewArrayInsnNode) ain).dims);
|
||||
}
|
||||
else
|
||||
{
|
||||
return InstructionFilter.ACCEPT_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
AbstractInsnNode[] ains = new AbstractInsnNode[]{
|
||||
new LdcInsnNode("ldc"), new VarInsnNode(ASTORE, 0),
|
||||
new LdcInsnNode("ldc")};
|
||||
InstructionPattern pattern = new InstructionPattern(
|
||||
new AbstractInsnNode[]{new LdcInsnNode("ldc"),
|
||||
new VarInsnNode(-1, -1)});
|
||||
for (AbstractInsnNode ain : ains) {
|
||||
if (pattern.accept(ain)) {
|
||||
public static void main(String[] args)
|
||||
{
|
||||
AbstractInsnNode[] ains = new AbstractInsnNode[]{new LdcInsnNode("ldc"), new VarInsnNode(ASTORE, 0), new LdcInsnNode("ldc")};
|
||||
InstructionPattern pattern = new InstructionPattern(new AbstractInsnNode[]{new LdcInsnNode("ldc"), new VarInsnNode(-1, -1)});
|
||||
for (AbstractInsnNode ain : ains)
|
||||
{
|
||||
if (pattern.accept(ain))
|
||||
{
|
||||
System.out.println(Arrays.toString(pattern.getLastMatch()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,8 @@ import java.util.stream.Collectors;
|
|||
* @author Bibl
|
||||
* @author GraxCode
|
||||
*/
|
||||
public class InstructionPrinter implements Opcodes {
|
||||
public class InstructionPrinter implements Opcodes
|
||||
{
|
||||
|
||||
/**
|
||||
* The MethodNode to print
|
||||
|
@ -54,7 +55,8 @@ public class InstructionPrinter implements Opcodes {
|
|||
private boolean firstLabel = false;
|
||||
private final List<String> info = new ArrayList<>();
|
||||
|
||||
public InstructionPrinter(MethodNode m, TypeAndName[] args) {
|
||||
public InstructionPrinter(MethodNode m, TypeAndName[] args)
|
||||
{
|
||||
this.args = args;
|
||||
mNode = m;
|
||||
labels = new HashMap<>();
|
||||
|
@ -64,24 +66,30 @@ public class InstructionPrinter implements Opcodes {
|
|||
match = false;
|
||||
}
|
||||
|
||||
public InstructionPrinter(MethodNode m, InstructionPattern pattern, TypeAndName[] args) {
|
||||
public InstructionPrinter(MethodNode m, InstructionPattern pattern, TypeAndName[] args)
|
||||
{
|
||||
this(m, args);
|
||||
InstructionSearcher searcher = new InstructionSearcher(m.instructions, pattern);
|
||||
match = searcher.search();
|
||||
if (match) {
|
||||
for (AbstractInsnNode[] ains : searcher.getMatches()) {
|
||||
if (match)
|
||||
{
|
||||
for (AbstractInsnNode[] ains : searcher.getMatches())
|
||||
{
|
||||
Collections.addAll(matchedInsns, ains);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void precalculateLabelIndexes(MethodNode m) {
|
||||
if(m == null)
|
||||
private void precalculateLabelIndexes(MethodNode m)
|
||||
{
|
||||
if (m == null)
|
||||
return;
|
||||
|
||||
int lIdx = 0;
|
||||
for (AbstractInsnNode ain : m.instructions) {
|
||||
if (ain.getType() == AbstractInsnNode.LABEL) {
|
||||
for (AbstractInsnNode ain : m.instructions)
|
||||
{
|
||||
if (ain.getType() == AbstractInsnNode.LABEL)
|
||||
{
|
||||
labels.put((LabelNode) ain, lIdx++);
|
||||
}
|
||||
}
|
||||
|
@ -92,90 +100,143 @@ public class InstructionPrinter implements Opcodes {
|
|||
*
|
||||
* @return The print as an ArrayList
|
||||
*/
|
||||
public List<String> createPrint() {
|
||||
public List<String> createPrint()
|
||||
{
|
||||
firstLabel = false;
|
||||
info.clear();
|
||||
for (AbstractInsnNode ain : mNode.instructions) {
|
||||
for (AbstractInsnNode ain : mNode.instructions)
|
||||
{
|
||||
String line = printInstruction(ain);
|
||||
if (!line.isEmpty()) {
|
||||
if (match) if (matchedInsns.contains(ain)) line = " -> " + line;
|
||||
if (!line.isEmpty())
|
||||
{
|
||||
if (match)
|
||||
if (matchedInsns.contains(ain))
|
||||
line = " -> " + line;
|
||||
|
||||
info.add(line);
|
||||
}
|
||||
}
|
||||
if (firstLabel && BytecodeViewer.viewer.appendBracketsToLabels.isSelected()) info.add("}");
|
||||
if (firstLabel && BytecodeViewer.viewer.appendBracketsToLabels.isSelected())
|
||||
info.add("}");
|
||||
return info;
|
||||
}
|
||||
|
||||
public String printInstruction(AbstractInsnNode ain) {
|
||||
public String printInstruction(AbstractInsnNode ain)
|
||||
{
|
||||
String line = "";
|
||||
if (ain instanceof VarInsnNode) {
|
||||
if (ain instanceof VarInsnNode)
|
||||
{
|
||||
line = printVarInsnNode((VarInsnNode) ain);
|
||||
} else if (ain instanceof IntInsnNode) {
|
||||
}
|
||||
else if (ain instanceof IntInsnNode)
|
||||
{
|
||||
line = printIntInsnNode((IntInsnNode) ain);
|
||||
} else if (ain instanceof FieldInsnNode) {
|
||||
}
|
||||
else if (ain instanceof FieldInsnNode)
|
||||
{
|
||||
line = printFieldInsnNode((FieldInsnNode) ain);
|
||||
} else if (ain instanceof MethodInsnNode) {
|
||||
}
|
||||
else if (ain instanceof MethodInsnNode)
|
||||
{
|
||||
line = printMethodInsnNode((MethodInsnNode) ain);
|
||||
} else if (ain instanceof LdcInsnNode) {
|
||||
}
|
||||
else if (ain instanceof LdcInsnNode)
|
||||
{
|
||||
line = printLdcInsnNode((LdcInsnNode) ain);
|
||||
} else if (ain instanceof InsnNode) {
|
||||
}
|
||||
else if (ain instanceof InsnNode)
|
||||
{
|
||||
line = printInsnNode((InsnNode) ain);
|
||||
} else if (ain instanceof JumpInsnNode) {
|
||||
}
|
||||
else if (ain instanceof JumpInsnNode)
|
||||
{
|
||||
line = printJumpInsnNode((JumpInsnNode) ain);
|
||||
} else if (ain instanceof LineNumberNode) {
|
||||
}
|
||||
else if (ain instanceof LineNumberNode)
|
||||
{
|
||||
line = printLineNumberNode((LineNumberNode) ain);
|
||||
} else if (ain instanceof LabelNode) {
|
||||
if (firstLabel && BytecodeViewer.viewer.appendBracketsToLabels.isSelected()) info.add("}");
|
||||
}
|
||||
else if (ain instanceof LabelNode)
|
||||
{
|
||||
if (firstLabel && BytecodeViewer.viewer.appendBracketsToLabels.isSelected())
|
||||
info.add("}");
|
||||
|
||||
LabelNode label = (LabelNode) ain;
|
||||
if (mNode.tryCatchBlocks != null) {
|
||||
if (mNode.tryCatchBlocks != null)
|
||||
{
|
||||
List<TryCatchBlockNode> tcbs = mNode.tryCatchBlocks;
|
||||
String starting = tcbs.stream().filter(tcb -> tcb.start == label).map(tcb -> "start TCB" + tcbs.indexOf(tcb)).collect(Collectors.joining(", "));
|
||||
String ending = tcbs.stream().filter(tcb -> tcb.end == label).map(tcb -> "end TCB" + tcbs.indexOf(tcb)).collect(Collectors.joining(", "));
|
||||
String handlers = tcbs.stream().filter(tcb -> tcb.handler == label).map(tcb -> "handle TCB" + tcbs.indexOf(tcb)).collect(Collectors.joining(", "));
|
||||
if (!ending.isEmpty()) info.add("// " + ending);
|
||||
if (!starting.isEmpty()) info.add("// " + starting);
|
||||
if (!handlers.isEmpty()) info.add("// " + handlers);
|
||||
if (!ending.isEmpty())
|
||||
info.add("// " + ending);
|
||||
if (!starting.isEmpty())
|
||||
info.add("// " + starting);
|
||||
if (!handlers.isEmpty())
|
||||
info.add("// " + handlers);
|
||||
}
|
||||
line = printLabelNode((LabelNode) ain);
|
||||
|
||||
if (BytecodeViewer.viewer.appendBracketsToLabels.isSelected()) {
|
||||
if (!firstLabel) firstLabel = true;
|
||||
if (BytecodeViewer.viewer.appendBracketsToLabels.isSelected())
|
||||
{
|
||||
if (!firstLabel)
|
||||
firstLabel = true;
|
||||
line += " {";
|
||||
}
|
||||
} else if (ain instanceof TypeInsnNode) {
|
||||
}
|
||||
else if (ain instanceof TypeInsnNode)
|
||||
{
|
||||
line = printTypeInsnNode((TypeInsnNode) ain);
|
||||
} else if (ain instanceof FrameNode) {
|
||||
}
|
||||
else if (ain instanceof FrameNode)
|
||||
{
|
||||
line = printFrameNode((FrameNode) ain);
|
||||
} else if (ain instanceof IincInsnNode) {
|
||||
}
|
||||
else if (ain instanceof IincInsnNode)
|
||||
{
|
||||
line = printIincInsnNode((IincInsnNode) ain);
|
||||
} else if (ain instanceof TableSwitchInsnNode) {
|
||||
}
|
||||
else if (ain instanceof TableSwitchInsnNode)
|
||||
{
|
||||
line = printTableSwitchInsnNode((TableSwitchInsnNode) ain);
|
||||
} else if (ain instanceof LookupSwitchInsnNode) {
|
||||
}
|
||||
else if (ain instanceof LookupSwitchInsnNode)
|
||||
{
|
||||
line = printLookupSwitchInsnNode((LookupSwitchInsnNode) ain);
|
||||
} else if (ain instanceof InvokeDynamicInsnNode) {
|
||||
}
|
||||
else if (ain instanceof InvokeDynamicInsnNode)
|
||||
{
|
||||
line = printInvokeDynamicInsNode((InvokeDynamicInsnNode) ain);
|
||||
} else if (ain instanceof MultiANewArrayInsnNode) {
|
||||
}
|
||||
else if (ain instanceof MultiANewArrayInsnNode)
|
||||
{
|
||||
line = printMultiANewArrayInsNode((MultiANewArrayInsnNode) ain);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
line += "UNADDED OPCODE: " + nameOpcode(ain.getOpcode()) + " " + ain;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
protected String printVarInsnNode(VarInsnNode vin) {
|
||||
protected String printVarInsnNode(VarInsnNode vin)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(nameOpcode(vin.getOpcode()));
|
||||
sb.append(" ");
|
||||
sb.append(vin.var);
|
||||
if (BytecodeViewer.viewer.debugHelpers.isSelected()) {
|
||||
if (vin.var == 0 && !Modifier.isStatic(mNode.access)) {
|
||||
if (BytecodeViewer.viewer.debugHelpers.isSelected())
|
||||
{
|
||||
if (vin.var == 0 && !Modifier.isStatic(mNode.access))
|
||||
{
|
||||
sb.append(" // reference to self");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
final int refIndex = vin.var - (Modifier.isStatic(mNode.access) ? 0 : 1);
|
||||
if (refIndex >= 0 && refIndex < args.length - 1) {
|
||||
if (refIndex >= 0 && refIndex < args.length - 1)
|
||||
{
|
||||
sb.append(" // reference to ").append(args[refIndex].name);
|
||||
}
|
||||
}
|
||||
|
@ -184,99 +245,129 @@ public class InstructionPrinter implements Opcodes {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
protected String printIntInsnNode(IntInsnNode iin) {
|
||||
protected String printIntInsnNode(IntInsnNode iin)
|
||||
{
|
||||
return nameOpcode(iin.getOpcode()) + " " + iin.operand;
|
||||
}
|
||||
|
||||
protected String printFieldInsnNode(FieldInsnNode fin) {
|
||||
protected String printFieldInsnNode(FieldInsnNode fin)
|
||||
{
|
||||
String desc = Type.getType(fin.desc).getClassName();
|
||||
if (desc.equals("null")) desc = fin.desc;
|
||||
if (desc.equals("null"))
|
||||
desc = fin.desc;
|
||||
return nameOpcode(fin.getOpcode()) + " " + fin.owner + "." + fin.name + ":" + desc;
|
||||
}
|
||||
|
||||
protected String printMethodInsnNode(MethodInsnNode min) {
|
||||
protected String printMethodInsnNode(MethodInsnNode min)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(nameOpcode(min.getOpcode())).append(" ").append(min.owner).append(".").append(min.name);
|
||||
|
||||
String desc = min.desc;
|
||||
try {
|
||||
if (Type.getType(min.desc) != null) desc = Type.getType(min.desc).getClassName();
|
||||
} catch (java.lang.AssertionError e) {
|
||||
try
|
||||
{
|
||||
if (Type.getType(min.desc) != null)
|
||||
desc = Type.getType(min.desc).getClassName();
|
||||
}
|
||||
catch (java.lang.AssertionError e)
|
||||
{
|
||||
//e.printStackTrace();
|
||||
} catch (java.lang.Exception e) {
|
||||
}
|
||||
catch (java.lang.Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (desc == null || desc.equals("null")) desc = min.desc;
|
||||
if (desc == null || desc.equals("null"))
|
||||
desc = min.desc;
|
||||
|
||||
sb.append(desc);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected String printLdcInsnNode(LdcInsnNode ldc) {
|
||||
protected String printLdcInsnNode(LdcInsnNode ldc)
|
||||
{
|
||||
if (ldc.cst instanceof String)
|
||||
return nameOpcode(ldc.getOpcode()) + " \"" + StringEscapeUtils.escapeJava(ldc.cst.toString()) + "\" (" + ldc.cst.getClass().getCanonicalName() + ")";
|
||||
|
||||
return nameOpcode(ldc.getOpcode()) + " " + StringEscapeUtils.escapeJava(ldc.cst.toString()) + " (" + ldc.cst.getClass().getCanonicalName() + ")";
|
||||
}
|
||||
|
||||
protected String printInsnNode(InsnNode in) {
|
||||
protected String printInsnNode(InsnNode in)
|
||||
{
|
||||
return nameOpcode(in.getOpcode());
|
||||
}
|
||||
|
||||
protected String printJumpInsnNode(JumpInsnNode jin) {
|
||||
protected String printJumpInsnNode(JumpInsnNode jin)
|
||||
{
|
||||
return nameOpcode(jin.getOpcode()) + " L" + resolveLabel(jin.label);
|
||||
}
|
||||
|
||||
protected String printLineNumberNode(LineNumberNode lnn) {
|
||||
if(BytecodeViewer.viewer.printLineNumbers.isSelected())
|
||||
protected String printLineNumberNode(LineNumberNode lnn)
|
||||
{
|
||||
if (BytecodeViewer.viewer.printLineNumbers.isSelected())
|
||||
return "// line " + lnn.line;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
protected String printLabelNode(LabelNode label) {
|
||||
protected String printLabelNode(LabelNode label)
|
||||
{
|
||||
return "L" + resolveLabel(label);
|
||||
}
|
||||
|
||||
protected String printTypeInsnNode(TypeInsnNode tin) {
|
||||
try {
|
||||
protected String printTypeInsnNode(TypeInsnNode tin)
|
||||
{
|
||||
try
|
||||
{
|
||||
String desc = tin.desc;
|
||||
try {
|
||||
if (Type.getType(tin.desc) != null) desc = Type.getType(tin.desc).getClassName();
|
||||
try
|
||||
{
|
||||
if (Type.getType(tin.desc) != null)
|
||||
desc = Type.getType(tin.desc).getClassName();
|
||||
|
||||
if (desc.equals("null")) desc = tin.desc;
|
||||
} catch (java.lang.ArrayIndexOutOfBoundsException ignored) {
|
||||
if (desc.equals("null"))
|
||||
desc = tin.desc;
|
||||
}
|
||||
catch (java.lang.ArrayIndexOutOfBoundsException ignored)
|
||||
{
|
||||
|
||||
}
|
||||
return nameOpcode(tin.getOpcode()) + " " + desc;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return nameOpcode(tin.getOpcode()) + " " + tin.desc;
|
||||
}
|
||||
}
|
||||
|
||||
protected String printIincInsnNode(IincInsnNode iin) {
|
||||
protected String printIincInsnNode(IincInsnNode iin)
|
||||
{
|
||||
return nameOpcode(iin.getOpcode()) + " " + iin.var + " " + iin.incr;
|
||||
}
|
||||
|
||||
protected String printTableSwitchInsnNode(TableSwitchInsnNode tin) {
|
||||
protected String printTableSwitchInsnNode(TableSwitchInsnNode tin)
|
||||
{
|
||||
StringBuilder line = new StringBuilder(nameOpcode(tin.getOpcode()) + " \n");
|
||||
List<?> labels = tin.labels;
|
||||
int count = 0;
|
||||
for (int i = tin.min; i < tin.max + 1; i++) {
|
||||
for (int i = tin.min; i < tin.max + 1; i++)
|
||||
{
|
||||
line.append(" val: ").append(i).append(" -> ").append("L").append(resolveLabel((LabelNode) labels.get(count++))).append("\n");
|
||||
}
|
||||
line.append(" default" + " -> L").append(resolveLabel(tin.dflt));
|
||||
return line.toString();
|
||||
}
|
||||
|
||||
protected String printLookupSwitchInsnNode(LookupSwitchInsnNode lin) {
|
||||
protected String printLookupSwitchInsnNode(LookupSwitchInsnNode lin)
|
||||
{
|
||||
StringBuilder line = new StringBuilder(nameOpcode(lin.getOpcode()) + ": \n");
|
||||
List<?> keys = lin.keys;
|
||||
List<?> labels = lin.labels;
|
||||
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
for (int i = 0; i < keys.size(); i++)
|
||||
{
|
||||
int key = (Integer) keys.get(i);
|
||||
LabelNode label = (LabelNode) labels.get(i);
|
||||
line.append(" val: ").append(key).append(" -> ").append("L").append(resolveLabel(label)).append("\n");
|
||||
|
@ -286,12 +377,15 @@ public class InstructionPrinter implements Opcodes {
|
|||
return line.toString();
|
||||
}
|
||||
|
||||
protected String printInvokeDynamicInsNode(InvokeDynamicInsnNode idin) {
|
||||
protected String printInvokeDynamicInsNode(InvokeDynamicInsnNode idin)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(nameOpcode(idin.getOpcode())).append(" ").append(idin.bsm.getOwner()).append('.').append(idin.bsm.getName()).append(idin.bsm.getDesc()).append(" : ").append(idin.name).append(idin.desc);
|
||||
|
||||
if (idin.bsmArgs != null) {
|
||||
for (Object o : idin.bsmArgs) {
|
||||
if (idin.bsmArgs != null)
|
||||
{
|
||||
for (Object o : idin.bsmArgs)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(o.toString());
|
||||
}
|
||||
|
@ -300,27 +394,35 @@ public class InstructionPrinter implements Opcodes {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
protected String printMultiANewArrayInsNode(MultiANewArrayInsnNode mana) {
|
||||
protected String printMultiANewArrayInsNode(MultiANewArrayInsnNode mana)
|
||||
{
|
||||
return nameOpcode(mana.getOpcode()) + " " + mana.dims + " : " + mana.desc;
|
||||
}
|
||||
|
||||
private String printFrameNode(FrameNode frame) {
|
||||
private String printFrameNode(FrameNode frame)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(nameFrameType(frame.type)).append(" ");
|
||||
sb.append("(Locals");
|
||||
if (frame.local != null && !frame.local.isEmpty()) {
|
||||
if (frame.local != null && !frame.local.isEmpty())
|
||||
{
|
||||
sb.append("[").append(frame.local.size()).append("]: ");
|
||||
sb.append(frame.local.stream().map(this::printFrameObject).collect(Collectors.joining(", ")));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("[0]");
|
||||
}
|
||||
sb.append(") ");
|
||||
|
||||
sb.append("(Stack");
|
||||
if (frame.stack != null && !frame.stack.isEmpty()) {
|
||||
if (frame.stack != null && !frame.stack.isEmpty())
|
||||
{
|
||||
sb.append("[").append(frame.stack.size()).append("]: ");
|
||||
sb.append(frame.stack.stream().map(this::printFrameObject).collect(Collectors.joining(", ")));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("[0]");
|
||||
}
|
||||
sb.append(") ");
|
||||
|
@ -328,10 +430,14 @@ public class InstructionPrinter implements Opcodes {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
private String printFrameObject(Object obj) {
|
||||
if (obj instanceof LabelNode) return "label [L" + resolveLabel((LabelNode) obj) + "]";
|
||||
if (obj instanceof Integer) {
|
||||
switch ((int) obj) {
|
||||
private String printFrameObject(Object obj)
|
||||
{
|
||||
if (obj instanceof LabelNode)
|
||||
return "label [L" + resolveLabel((LabelNode) obj) + "]";
|
||||
if (obj instanceof Integer)
|
||||
{
|
||||
switch ((int) obj)
|
||||
{
|
||||
case 0:
|
||||
return "top";
|
||||
case 1:
|
||||
|
@ -350,12 +456,15 @@ public class InstructionPrinter implements Opcodes {
|
|||
return "unknown";
|
||||
}
|
||||
}
|
||||
if (obj instanceof String) return obj.toString();
|
||||
if (obj instanceof String)
|
||||
return obj.toString();
|
||||
return "unknown [" + obj.toString() + "]";
|
||||
}
|
||||
|
||||
private String nameFrameType(int type) {
|
||||
switch (type) {
|
||||
private String nameFrameType(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case F_NEW:
|
||||
return " f_new";
|
||||
case F_FULL:
|
||||
|
@ -373,14 +482,19 @@ public class InstructionPrinter implements Opcodes {
|
|||
}
|
||||
}
|
||||
|
||||
protected String nameOpcode(int opcode) {
|
||||
protected String nameOpcode(int opcode)
|
||||
{
|
||||
return " " + OpcodeInfo.OPCODES.get(opcode).toLowerCase();
|
||||
}
|
||||
|
||||
protected int resolveLabel(LabelNode label) {
|
||||
if (labels.containsKey(label)) {
|
||||
protected int resolveLabel(LabelNode label)
|
||||
{
|
||||
if (labels.containsKey(label))
|
||||
{
|
||||
return labels.get(label);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/*int newLabelIndex = labels.size() + 1;
|
||||
labels.put(label, newLabelIndex);
|
||||
return newLabelIndex;*/
|
||||
|
@ -388,13 +502,18 @@ public class InstructionPrinter implements Opcodes {
|
|||
}
|
||||
}
|
||||
|
||||
public static void saveTo(File file, InstructionPrinter printer) {
|
||||
try (FileWriter fw = new FileWriter(file); BufferedWriter bw = new BufferedWriter(fw)) {
|
||||
for (String s : printer.createPrint()) {
|
||||
public static void saveTo(File file, InstructionPrinter printer)
|
||||
{
|
||||
try (FileWriter fw = new FileWriter(file); BufferedWriter bw = new BufferedWriter(fw))
|
||||
{
|
||||
for (String s : printer.createPrint())
|
||||
{
|
||||
bw.write(s);
|
||||
bw.newLine();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,44 +18,52 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.FrameNode;
|
||||
import org.objectweb.asm.tree.InsnList;
|
||||
import org.objectweb.asm.tree.LineNumberNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Bibl
|
||||
*/
|
||||
|
||||
public class InstructionSearcher implements Opcodes {
|
||||
public class InstructionSearcher implements Opcodes
|
||||
{
|
||||
|
||||
protected InsnList insns;
|
||||
protected InstructionPattern pattern;
|
||||
|
||||
protected List<AbstractInsnNode[]> matches;
|
||||
|
||||
public InstructionSearcher(InsnList insns, int[] opcodes) {
|
||||
public InstructionSearcher(InsnList insns, int[] opcodes)
|
||||
{
|
||||
this(insns, new InstructionPattern(opcodes));
|
||||
}
|
||||
|
||||
public InstructionSearcher(InsnList insns, AbstractInsnNode[] ains) {
|
||||
public InstructionSearcher(InsnList insns, AbstractInsnNode[] ains)
|
||||
{
|
||||
this(insns, new InstructionPattern(ains));
|
||||
}
|
||||
|
||||
public InstructionSearcher(InsnList insns, InstructionPattern pattern) {
|
||||
public InstructionSearcher(InsnList insns, InstructionPattern pattern)
|
||||
{
|
||||
this.insns = insns;
|
||||
this.pattern = pattern;
|
||||
matches = new ArrayList<>();
|
||||
}
|
||||
|
||||
public boolean search() {
|
||||
for (AbstractInsnNode ain : insns.toArray()) {
|
||||
public boolean search()
|
||||
{
|
||||
for (AbstractInsnNode ain : insns.toArray())
|
||||
{
|
||||
if (ain instanceof LineNumberNode || ain instanceof FrameNode)
|
||||
continue;
|
||||
if (pattern.accept(ain)) {
|
||||
if (pattern.accept(ain))
|
||||
{
|
||||
matches.add(pattern.getLastMatch());
|
||||
pattern.resetMatch();
|
||||
}
|
||||
|
@ -63,11 +71,13 @@ public class InstructionSearcher implements Opcodes {
|
|||
return size() != 0;
|
||||
}
|
||||
|
||||
public List<AbstractInsnNode[]> getMatches() {
|
||||
public List<AbstractInsnNode[]> getMatches()
|
||||
{
|
||||
return matches;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
public int size()
|
||||
{
|
||||
return matches.size();
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -18,17 +18,14 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.*;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.AnnotationNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.LocalVariableNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.TryCatchBlockNode;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
|
||||
|
@ -37,14 +34,18 @@ import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
|||
* @author Bibl
|
||||
*/
|
||||
|
||||
public class MethodNodeDecompiler {
|
||||
public class MethodNodeDecompiler
|
||||
{
|
||||
|
||||
public static PrefixedStringBuilder decompile(PrefixedStringBuilder sb,
|
||||
MethodNode m, ClassNode cn) {
|
||||
public static PrefixedStringBuilder decompile(PrefixedStringBuilder sb, MethodNode m, ClassNode cn)
|
||||
{
|
||||
String class_;
|
||||
if (cn.name.contains("/")) {
|
||||
if (cn.name.contains("/"))
|
||||
{
|
||||
class_ = cn.name.substring(cn.name.lastIndexOf("/") + 1);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
class_ = cn.name;
|
||||
}
|
||||
|
||||
|
@ -54,9 +55,12 @@ public class MethodNodeDecompiler {
|
|||
if (s.length() > 0)
|
||||
sb.append(" ");
|
||||
|
||||
if (m.name.equals("<init>")) {
|
||||
if (m.name.equals("<init>"))
|
||||
{
|
||||
sb.append(class_);
|
||||
} else if (!m.name.equals("<clinit>")) {
|
||||
}
|
||||
else if (!m.name.equals("<clinit>"))
|
||||
{
|
||||
Type returnType = Type.getReturnType(m.desc);
|
||||
sb.append(returnType.getClassName());
|
||||
sb.append(" ");
|
||||
|
@ -65,13 +69,15 @@ public class MethodNodeDecompiler {
|
|||
|
||||
TypeAndName[] args = new TypeAndName[0];
|
||||
|
||||
if (!m.name.equals("<clinit>")) {
|
||||
if (!m.name.equals("<clinit>"))
|
||||
{
|
||||
sb.append("(");
|
||||
|
||||
final Type[] argTypes = Type.getArgumentTypes(m.desc);
|
||||
args = new TypeAndName[argTypes.length];
|
||||
|
||||
for (int i = 0; i < argTypes.length; i++) {
|
||||
for (int i = 0; i < argTypes.length; i++)
|
||||
{
|
||||
final Type type = argTypes[i];
|
||||
|
||||
final TypeAndName tan = new TypeAndName();
|
||||
|
@ -82,33 +88,38 @@ public class MethodNodeDecompiler {
|
|||
|
||||
args[i] = tan;
|
||||
|
||||
sb.append(type.getClassName() + " " + argName
|
||||
+ (i < argTypes.length - 1 ? ", " : ""));
|
||||
sb.append(type.getClassName() + " " + argName + (i < argTypes.length - 1 ? ", " : ""));
|
||||
}
|
||||
|
||||
sb.append(")");
|
||||
}
|
||||
|
||||
int amountOfThrows = m.exceptions.size();
|
||||
if (amountOfThrows > 0) {
|
||||
if (amountOfThrows > 0)
|
||||
{
|
||||
sb.append(" throws ");
|
||||
sb.append(m.exceptions.get(0));// exceptions is list<string>
|
||||
for (int i = 1; i < amountOfThrows; i++) {
|
||||
for (int i = 1; i < amountOfThrows; i++)
|
||||
{
|
||||
sb.append(", ");
|
||||
sb.append(m.exceptions.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (s.contains("abstract")) {
|
||||
if (s.contains("abstract"))
|
||||
{
|
||||
sb.append(" {}");
|
||||
sb.append(" //");
|
||||
sb.append(m.desc);
|
||||
sb.append(nl);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
sb.append(" {");
|
||||
|
||||
if (BytecodeViewer.viewer.debugHelpers.isSelected()) {
|
||||
if (BytecodeViewer.viewer.debugHelpers.isSelected())
|
||||
{
|
||||
if (m.name.equals("<clinit>"))
|
||||
sb.append(" // <clinit>");
|
||||
else if (m.name.equals("<init>"))
|
||||
|
@ -120,12 +131,14 @@ public class MethodNodeDecompiler {
|
|||
|
||||
sb.append(nl);
|
||||
|
||||
if (m.signature != null) {
|
||||
if (m.signature != null)
|
||||
{
|
||||
sb.append(" <sig:").append(m.signature).append(">");
|
||||
sb.append(nl);
|
||||
}
|
||||
|
||||
if (m.annotationDefault != null) {
|
||||
if (m.annotationDefault != null)
|
||||
{
|
||||
sb.append(m.annotationDefault);
|
||||
sb.append(nl);
|
||||
}
|
||||
|
@ -134,19 +147,16 @@ public class MethodNodeDecompiler {
|
|||
|
||||
addAttrList(m.attrs, "attr", sb, insnPrinter);
|
||||
addAttrList(m.invisibleAnnotations, "invisAnno", sb, insnPrinter);
|
||||
addAttrList(m.invisibleAnnotations, "invisLocalVarAnno", sb,
|
||||
insnPrinter);
|
||||
addAttrList(m.invisibleTypeAnnotations, "invisTypeAnno", sb,
|
||||
insnPrinter);
|
||||
addAttrList(m.invisibleAnnotations, "invisLocalVarAnno", sb, insnPrinter);
|
||||
addAttrList(m.invisibleTypeAnnotations, "invisTypeAnno", sb, insnPrinter);
|
||||
addAttrList(m.localVariables, "localVar", sb, insnPrinter);
|
||||
addAttrList(m.visibleAnnotations, "visAnno", sb, insnPrinter);
|
||||
addAttrList(m.visibleLocalVariableAnnotations, "visLocalVarAnno",
|
||||
sb, insnPrinter);
|
||||
addAttrList(m.visibleTypeAnnotations, "visTypeAnno", sb,
|
||||
insnPrinter);
|
||||
addAttrList(m.visibleLocalVariableAnnotations, "visLocalVarAnno", sb, insnPrinter);
|
||||
addAttrList(m.visibleTypeAnnotations, "visTypeAnno", sb, insnPrinter);
|
||||
|
||||
List<TryCatchBlockNode> tryCatchBlocks = m.tryCatchBlocks;
|
||||
for (int i = 0; i < tryCatchBlocks.size(); i++) {
|
||||
for (int i = 0; i < tryCatchBlocks.size(); i++)
|
||||
{
|
||||
TryCatchBlockNode o = tryCatchBlocks.get(i);
|
||||
sb.append(" ");
|
||||
sb.append("TryCatch").append(i).append(": L");
|
||||
|
@ -162,7 +172,8 @@ public class MethodNodeDecompiler {
|
|||
sb.append("Type is null.");
|
||||
sb.append(nl);
|
||||
}
|
||||
for (String insn : insnPrinter.createPrint()) {
|
||||
for (String insn : insnPrinter.createPrint())
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(insn);
|
||||
sb.append(nl);
|
||||
|
@ -172,12 +183,14 @@ public class MethodNodeDecompiler {
|
|||
return sb;
|
||||
}
|
||||
|
||||
private static void addAttrList(List<?> list, String name,
|
||||
PrefixedStringBuilder sb, InstructionPrinter insnPrinter) {
|
||||
private static void addAttrList(List<?> list, String name, PrefixedStringBuilder sb, InstructionPrinter insnPrinter)
|
||||
{
|
||||
if (list == null)
|
||||
return;
|
||||
if (list.size() > 0) {
|
||||
for (Object o : list) {
|
||||
if (list.size() > 0)
|
||||
{
|
||||
for (Object o : list)
|
||||
{
|
||||
sb.append(" <");
|
||||
sb.append(name);
|
||||
sb.append(":");
|
||||
|
@ -189,22 +202,26 @@ public class MethodNodeDecompiler {
|
|||
}
|
||||
}
|
||||
|
||||
private static String printAttr(Object o, InstructionPrinter insnPrinter) {
|
||||
if (o instanceof LocalVariableNode) {
|
||||
private static String printAttr(Object o, InstructionPrinter insnPrinter)
|
||||
{
|
||||
if (o instanceof LocalVariableNode)
|
||||
{
|
||||
LocalVariableNode lvn = (LocalVariableNode) o;
|
||||
return "index=" + lvn.index + " , name=" + lvn.name + " , desc="
|
||||
+ lvn.desc + ", sig=" + lvn.signature + ", start=L"
|
||||
+ insnPrinter.resolveLabel(lvn.start) + ", end=L"
|
||||
+ insnPrinter.resolveLabel(lvn.end);
|
||||
} else if (o instanceof AnnotationNode) {
|
||||
return "index=" + lvn.index + " , name=" + lvn.name + " , desc=" + lvn.desc + ", sig=" + lvn.signature + ", start=L" + insnPrinter.resolveLabel(lvn.start) + ", end=L" + insnPrinter.resolveLabel(lvn.end);
|
||||
}
|
||||
else if (o instanceof AnnotationNode)
|
||||
{
|
||||
AnnotationNode an = (AnnotationNode) o;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("desc = ");
|
||||
sb.append(an.desc);
|
||||
sb.append(" , values = ");
|
||||
if (an.values != null) {
|
||||
if (an.values != null)
|
||||
{
|
||||
sb.append(Arrays.toString(an.values.toArray()));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("[]");
|
||||
}
|
||||
return sb.toString();
|
||||
|
@ -214,7 +231,8 @@ public class MethodNodeDecompiler {
|
|||
return o.toString();
|
||||
}
|
||||
|
||||
private static String getAccessString(int access) {
|
||||
private static String getAccessString(int access)
|
||||
{
|
||||
// public, protected, private, abstract, static,
|
||||
// final, synchronized, native & strictfp are permitted
|
||||
List<String> tokens = new ArrayList<>();
|
||||
|
@ -246,7 +264,8 @@ public class MethodNodeDecompiler {
|
|||
return "";
|
||||
// hackery delimeters
|
||||
StringBuilder sb = new StringBuilder(tokens.get(0));
|
||||
for (int i = 1; i < tokens.size(); i++) {
|
||||
for (int i = 1; i < tokens.size(); i++)
|
||||
{
|
||||
sb.append(" ");
|
||||
sb.append(tokens.get(i));
|
||||
}
|
||||
|
|
|
@ -22,16 +22,19 @@ package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
|
|||
* @author Bibl
|
||||
*/
|
||||
|
||||
public class PrefixedStringBuilder {
|
||||
public class PrefixedStringBuilder
|
||||
{
|
||||
|
||||
protected StringBuilder sb;
|
||||
protected String prefix;
|
||||
|
||||
public PrefixedStringBuilder() {
|
||||
public PrefixedStringBuilder()
|
||||
{
|
||||
sb = new StringBuilder();
|
||||
}
|
||||
|
||||
public PrefixedStringBuilder append(String s) {
|
||||
public PrefixedStringBuilder append(String s)
|
||||
{
|
||||
sb.append(s);
|
||||
if (s.contains("\n") && (prefix != null) && (prefix.length() > 0))// insert
|
||||
// the
|
||||
|
@ -45,15 +48,18 @@ public class PrefixedStringBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public PrefixedStringBuilder append(Object o) {
|
||||
public PrefixedStringBuilder append(Object o)
|
||||
{
|
||||
return append(o.toString());
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
public void setPrefix(String prefix)
|
||||
{
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public void trimPrefix(int amount) {
|
||||
public void trimPrefix(int amount)
|
||||
{
|
||||
if (prefix == null)
|
||||
return;
|
||||
if (prefix.length() < amount)
|
||||
|
@ -61,18 +67,21 @@ public class PrefixedStringBuilder {
|
|||
prefix = prefix.substring(0, prefix.length() - amount);
|
||||
}
|
||||
|
||||
public void appendPrefix(String s) {
|
||||
public void appendPrefix(String s)
|
||||
{
|
||||
if (prefix == null)
|
||||
prefix = "";
|
||||
prefix += s;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
public String getPrefix()
|
||||
{
|
||||
return prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public String toString()
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -27,7 +27,8 @@ import org.objectweb.asm.Type;
|
|||
* @author Waterwolf
|
||||
* @since 10/02/2011
|
||||
*/
|
||||
public class TypeAndName {
|
||||
public class TypeAndName
|
||||
{
|
||||
public Type type = null;
|
||||
public String name = null;
|
||||
}
|
|
@ -18,13 +18,14 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.util.Textifier;
|
||||
import org.objectweb.asm.util.TraceClassVisitor;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* Objectweb ASM Textifier output
|
||||
*
|
||||
|
@ -33,14 +34,16 @@ import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
|||
public class ASMTextifierDisassembler extends InternalDecompiler
|
||||
{
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b) {
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
{
|
||||
StringWriter writer = new StringWriter();
|
||||
cn.accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(writer)));
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName) {
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
|||
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.util.ASMifier;
|
||||
import org.objectweb.asm.util.Textifier;
|
||||
import org.objectweb.asm.util.TraceClassVisitor;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
||||
|
||||
|
@ -35,13 +34,15 @@ import java.io.StringWriter;
|
|||
public class ASMifierGenerator extends InternalDecompiler
|
||||
{
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b) {
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
{
|
||||
StringWriter writer = new StringWriter();
|
||||
cn.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(writer)));
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName) {
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,13 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.bytecode.ClassNodeDecompiler;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.bytecode.PrefixedStringBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
* @since 7/3/2021
|
||||
|
@ -31,12 +32,13 @@ import the.bytecode.club.bytecodeviewer.decompilers.bytecode.PrefixedStringBuild
|
|||
public class BytecodeDisassembler extends InternalDecompiler
|
||||
{
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b) {
|
||||
return ClassNodeDecompiler.decompile(new PrefixedStringBuilder(),
|
||||
new ArrayList<>(), cn).toString();
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
{
|
||||
return ClassNodeDecompiler.decompile(new PrefixedStringBuilder(), new ArrayList<>(), cn).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName) {
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,27 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.benf.cfr.reader.api.CfrDriver;
|
||||
import org.benf.cfr.reader.api.ClassFileSource;
|
||||
|
@ -55,6 +34,15 @@ import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
|||
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
|
||||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.CFR;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.ERROR;
|
||||
|
@ -65,17 +53,21 @@ import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.ERR
|
|||
* @author GraxCode
|
||||
* Taken mostly out of Threadtear.
|
||||
*/
|
||||
public class CFRDecompiler extends InternalDecompiler {
|
||||
public class CFRDecompiler extends InternalDecompiler
|
||||
{
|
||||
|
||||
private static final String CLASS_SUFFIX = ".class";
|
||||
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] content) {
|
||||
public String decompileClassNode(ClassNode cn, byte[] content)
|
||||
{
|
||||
return decompile(cn, cn.name, content);
|
||||
}
|
||||
|
||||
private String decompile(ClassNode cn, String name, byte[] content) {
|
||||
try {
|
||||
private String decompile(ClassNode cn, String name, byte[] content)
|
||||
{
|
||||
try
|
||||
{
|
||||
String classPath = name + (name.endsWith(CLASS_SUFFIX) ? "" : CLASS_SUFFIX);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
@ -83,79 +75,93 @@ public class CFRDecompiler extends InternalDecompiler {
|
|||
|
||||
Options options = generateOptions();
|
||||
ClassFileSource source = new BCVDataSource(options, cn, classPath, content);
|
||||
CfrDriver driver = new CfrDriver.Builder()
|
||||
.withClassFileSource(source)
|
||||
.withBuiltOptions(options)
|
||||
.withOutputSink(new BCVOutputSinkFactory(dumpDecompiled))
|
||||
.build();
|
||||
CfrDriver driver = new CfrDriver.Builder().withClassFileSource(source).withBuiltOptions(options).withOutputSink(new BCVOutputSinkFactory(dumpDecompiled)).build();
|
||||
driver.analyse(Collections.singletonList(name));
|
||||
|
||||
return builder.toString();
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace();
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
t.printStackTrace(pw);
|
||||
return CFR + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO +
|
||||
nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR +
|
||||
nl + nl + sw;
|
||||
return CFR + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR + nl + nl + sw;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decompileToZip(String sourceJar, String outJar) {
|
||||
try (JarFile jfile = new JarFile(new File(sourceJar));
|
||||
FileOutputStream dest = new FileOutputStream(outJar);
|
||||
BufferedOutputStream buffDest = new BufferedOutputStream(dest);
|
||||
ZipOutputStream out = new ZipOutputStream(buffDest)) {
|
||||
public void decompileToZip(String sourceJar, String outJar)
|
||||
{
|
||||
try (JarFile jfile = new JarFile(new File(sourceJar)); FileOutputStream dest = new FileOutputStream(outJar); BufferedOutputStream buffDest = new BufferedOutputStream(dest); ZipOutputStream out = new ZipOutputStream(buffDest))
|
||||
{
|
||||
byte[] data = new byte[1024];
|
||||
|
||||
Enumeration<JarEntry> ent = jfile.entries();
|
||||
Set<JarEntry> history = new HashSet<>();
|
||||
while (ent.hasMoreElements()) {
|
||||
while (ent.hasMoreElements())
|
||||
{
|
||||
JarEntry entry = ent.nextElement();
|
||||
if (entry.getName().endsWith(CLASS_SUFFIX)) {
|
||||
if (entry.getName().endsWith(CLASS_SUFFIX))
|
||||
{
|
||||
JarEntry etn = new JarEntry(entry.getName().replace(CLASS_SUFFIX, ".java"));
|
||||
if (history.add(etn)) {
|
||||
if (history.add(etn))
|
||||
{
|
||||
out.putNextEntry(etn);
|
||||
try {
|
||||
IOUtils.write(decompile(null, entry.getName(),
|
||||
IOUtils.toByteArray(jfile.getInputStream(entry))),
|
||||
out, StandardCharsets.UTF_8);
|
||||
} finally {
|
||||
try
|
||||
{
|
||||
IOUtils.write(decompile(null, entry.getName(), IOUtils.toByteArray(jfile.getInputStream(entry))), out, StandardCharsets.UTF_8);
|
||||
}
|
||||
finally
|
||||
{
|
||||
out.closeEntry();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
JarEntry etn = new JarEntry(entry.getName());
|
||||
if (history.add(etn)) continue;
|
||||
if (history.add(etn))
|
||||
continue;
|
||||
history.add(etn);
|
||||
out.putNextEntry(etn);
|
||||
try (InputStream in = jfile.getInputStream(entry)) {
|
||||
if (in != null) {
|
||||
try (InputStream in = jfile.getInputStream(entry))
|
||||
{
|
||||
if (in != null)
|
||||
{
|
||||
int count;
|
||||
while ((count = in.read(data, 0, 1024)) != -1) {
|
||||
while ((count = in.read(data, 0, 1024)) != -1)
|
||||
{
|
||||
out.write(data, 0, count);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
}
|
||||
finally
|
||||
{
|
||||
out.closeEntry();
|
||||
}
|
||||
} catch (ZipException ze) {
|
||||
}
|
||||
catch (ZipException ze)
|
||||
{
|
||||
// some jars contain duplicate pom.xml entries: ignore it
|
||||
if (!ze.getMessage().contains("duplicate")) {
|
||||
if (!ze.getMessage().contains("duplicate"))
|
||||
{
|
||||
throw ze;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (StackOverflowError | Exception e) {
|
||||
}
|
||||
catch (StackOverflowError | Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Options generateOptions() {
|
||||
public Options generateOptions()
|
||||
{
|
||||
Map<String, String> options = new HashMap<>();
|
||||
options.put("decodeenumswitch", String.valueOf(BytecodeViewer.viewer.decodeEnumSwitch.isSelected()));
|
||||
options.put("sugarenums", String.valueOf(BytecodeViewer.viewer.sugarEnums.isSelected()));
|
||||
|
@ -164,8 +170,7 @@ public class CFRDecompiler extends InternalDecompiler {
|
|||
options.put("collectioniter", String.valueOf(BytecodeViewer.viewer.collectioniter.isSelected()));
|
||||
options.put("innerclasses", String.valueOf(BytecodeViewer.viewer.innerClasses.isSelected()));
|
||||
options.put("removeboilerplate", String.valueOf(BytecodeViewer.viewer.removeBoilerPlate.isSelected()));
|
||||
options.put("removeinnerclasssynthetics",
|
||||
String.valueOf(BytecodeViewer.viewer.removeInnerClassSynthetics.isSelected()));
|
||||
options.put("removeinnerclasssynthetics", String.valueOf(BytecodeViewer.viewer.removeInnerClassSynthetics.isSelected()));
|
||||
options.put("decodelambdas", String.valueOf(BytecodeViewer.viewer.decodeLambdas.isSelected()));
|
||||
options.put("hidebridgemethods", String.valueOf(BytecodeViewer.viewer.hideBridgeMethods.isSelected()));
|
||||
options.put("liftconstructorinit", String.valueOf(BytecodeViewer.viewer.liftConstructorInit.isSelected()));
|
||||
|
@ -201,51 +206,61 @@ public class CFRDecompiler extends InternalDecompiler {
|
|||
return new OptionsImpl(options);
|
||||
}
|
||||
|
||||
private static class BCVDataSource extends ClassFileSourceImpl {
|
||||
private static class BCVDataSource extends ClassFileSourceImpl
|
||||
{
|
||||
|
||||
private final ResourceContainer container;
|
||||
private final String classFilePath;
|
||||
private final byte[] content;
|
||||
|
||||
private BCVDataSource(Options options, ClassNode cn, String classFilePath, byte[] content) {
|
||||
private BCVDataSource(Options options, ClassNode cn, String classFilePath, byte[] content)
|
||||
{
|
||||
super(options);
|
||||
this.container = BytecodeViewer.getResourceContainers().stream()
|
||||
.filter(rc -> rc.resourceClasses.containsValue(cn))
|
||||
.findFirst().orElse(null);
|
||||
this.container = BytecodeViewer.getResourceContainers().stream().filter(rc -> rc.resourceClasses.containsValue(cn)).findFirst().orElse(null);
|
||||
this.classFilePath = classFilePath;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<byte[], String> getClassFileContent(String classFilePath) throws IOException {
|
||||
if (classFilePath.equals(this.classFilePath) && content != null) return Pair.make(content, classFilePath);
|
||||
if (container == null) return super.getClassFileContent(classFilePath);
|
||||
public Pair<byte[], String> getClassFileContent(String classFilePath) throws IOException
|
||||
{
|
||||
if (classFilePath.equals(this.classFilePath) && content != null)
|
||||
return Pair.make(content, classFilePath);
|
||||
if (container == null)
|
||||
return super.getClassFileContent(classFilePath);
|
||||
byte[] data = container.resourceClassBytes.get(classFilePath);
|
||||
if (data == null) return super.getClassFileContent(classFilePath);
|
||||
if (data == null)
|
||||
return super.getClassFileContent(classFilePath);
|
||||
return Pair.make(data, classFilePath);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class BCVOutputSinkFactory implements OutputSinkFactory {
|
||||
private static class BCVOutputSinkFactory implements OutputSinkFactory
|
||||
{
|
||||
|
||||
private final Consumer<SinkReturns.Decompiled> dumpDecompiled;
|
||||
|
||||
private BCVOutputSinkFactory(Consumer<SinkReturns.Decompiled> dumpDecompiled) {
|
||||
private BCVOutputSinkFactory(Consumer<SinkReturns.Decompiled> dumpDecompiled)
|
||||
{
|
||||
this.dumpDecompiled = dumpDecompiled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SinkClass> getSupportedSinks(SinkType sinkType, Collection<SinkClass> available) {
|
||||
public List<SinkClass> getSupportedSinks(SinkType sinkType, Collection<SinkClass> available)
|
||||
{
|
||||
return Collections.singletonList(SinkClass.DECOMPILED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Sink<T> getSink(SinkType sinkType, SinkClass sinkClass) {
|
||||
if (sinkType == SinkType.JAVA && sinkClass == SinkClass.DECOMPILED) {
|
||||
public <T> Sink<T> getSink(SinkType sinkType, SinkClass sinkClass)
|
||||
{
|
||||
if (sinkType == SinkType.JAVA && sinkClass == SinkClass.DECOMPILED)
|
||||
{
|
||||
return x -> dumpDecompiled.accept((SinkReturns.Decompiled) x);
|
||||
}
|
||||
return ignore -> {
|
||||
return ignore ->
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import me.konloch.kontainer.io.DiskReader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
@ -31,10 +26,9 @@ import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
|||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.LAUNCH_DECOMPILERS_IN_NEW_PROCESS;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
||||
import java.io.*;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.ERROR;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.FERNFLOWER;
|
||||
|
||||
|
@ -55,9 +49,13 @@ public class FernFlowerDecompiler extends InternalDecompiler
|
|||
File f = new File(tempDirectory + fs + "temp" + fs);
|
||||
f.mkdir();
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.main(generateMainMethod(tempZip.getAbsolutePath(), tempDirectory + "./temp/"));
|
||||
} catch (StackOverflowError | Exception ignored) { }
|
||||
}
|
||||
catch (StackOverflowError | Exception ignored)
|
||||
{
|
||||
}
|
||||
|
||||
File tempZip2 = new File(tempDirectory + fs + "temp" + fs + tempZip.getName());
|
||||
if (tempZip2.exists())
|
||||
|
@ -74,9 +72,12 @@ public class FernFlowerDecompiler extends InternalDecompiler
|
|||
final File tempClass = new File(start + ".class");
|
||||
|
||||
String exception = "";
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass)) {
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass))
|
||||
{
|
||||
fos.write(b);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
StringWriter exceptionWriter = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(exceptionWriter));
|
||||
e.printStackTrace();
|
||||
|
@ -105,10 +106,12 @@ public class FernFlowerDecompiler extends InternalDecompiler
|
|||
}
|
||||
else
|
||||
{
|
||||
try {
|
||||
org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.main(
|
||||
generateMainMethod(tempClass.getAbsolutePath(), new File(tempDirectory).getAbsolutePath()));
|
||||
} catch (Throwable e) {
|
||||
try
|
||||
{
|
||||
org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.main(generateMainMethod(tempClass.getAbsolutePath(), new File(tempDirectory).getAbsolutePath()));
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
StringWriter exceptionWriter = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(exceptionWriter));
|
||||
e.printStackTrace();
|
||||
|
@ -119,20 +122,25 @@ public class FernFlowerDecompiler extends InternalDecompiler
|
|||
tempClass.delete();
|
||||
|
||||
String javaDir = start;
|
||||
if (BytecodeViewer.viewer.ren.isSelected()) {
|
||||
if (BytecodeViewer.viewer.ren.isSelected())
|
||||
{
|
||||
javaDir = tempDirectory + "class_0";
|
||||
}
|
||||
|
||||
final File outputJava = new File(javaDir + ".java");
|
||||
if (outputJava.exists()) {
|
||||
if (outputJava.exists())
|
||||
{
|
||||
String s;
|
||||
try {
|
||||
try
|
||||
{
|
||||
s = DiskReader.loadAsString(outputJava.getAbsolutePath());
|
||||
|
||||
outputJava.delete();
|
||||
|
||||
return s;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringWriter exceptionWriter = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(exceptionWriter));
|
||||
e.printStackTrace();
|
||||
|
@ -141,39 +149,22 @@ public class FernFlowerDecompiler extends InternalDecompiler
|
|||
}
|
||||
}
|
||||
|
||||
return FERNFLOWER + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO +
|
||||
nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR +
|
||||
nl + nl + exception;
|
||||
return FERNFLOWER + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR + nl + nl + exception;
|
||||
}
|
||||
|
||||
private String[] generateMainMethod(String className, String folder) {
|
||||
return new String[]{
|
||||
"-rbr=" + r(BytecodeViewer.viewer.rbr.isSelected()),
|
||||
"-rsy=" + r(BytecodeViewer.viewer.rsy.isSelected()),
|
||||
"-din=" + r(BytecodeViewer.viewer.din.isSelected()),
|
||||
"-dc4=" + r(BytecodeViewer.viewer.dc4.isSelected()),
|
||||
"-das=" + r(BytecodeViewer.viewer.das.isSelected()),
|
||||
"-hes=" + r(BytecodeViewer.viewer.hes.isSelected()),
|
||||
"-hdc=" + r(BytecodeViewer.viewer.hdc.isSelected()),
|
||||
"-dgs=" + r(BytecodeViewer.viewer.dgs.isSelected()),
|
||||
"-ner=" + r(BytecodeViewer.viewer.ner.isSelected()),
|
||||
"-den=" + r(BytecodeViewer.viewer.den.isSelected()),
|
||||
"-rgn=" + r(BytecodeViewer.viewer.rgn.isSelected()),
|
||||
"-bto=" + r(BytecodeViewer.viewer.bto.isSelected()),
|
||||
"-nns=" + r(BytecodeViewer.viewer.nns.isSelected()),
|
||||
"-uto=" + r(BytecodeViewer.viewer.uto.isSelected()),
|
||||
"-udv=" + r(BytecodeViewer.viewer.udv.isSelected()),
|
||||
"-rer=" + r(BytecodeViewer.viewer.rer.isSelected()),
|
||||
"-fdi=" + r(BytecodeViewer.viewer.fdi.isSelected()),
|
||||
"-asc=" + r(BytecodeViewer.viewer.asc.isSelected()),
|
||||
"-ren=" + r(BytecodeViewer.viewer.ren.isSelected()), className,
|
||||
folder};
|
||||
private String[] generateMainMethod(String className, String folder)
|
||||
{
|
||||
return new String[]{"-rbr=" + r(BytecodeViewer.viewer.rbr.isSelected()), "-rsy=" + r(BytecodeViewer.viewer.rsy.isSelected()), "-din=" + r(BytecodeViewer.viewer.din.isSelected()), "-dc4=" + r(BytecodeViewer.viewer.dc4.isSelected()), "-das=" + r(BytecodeViewer.viewer.das.isSelected()), "-hes=" + r(BytecodeViewer.viewer.hes.isSelected()), "-hdc=" + r(BytecodeViewer.viewer.hdc.isSelected()), "-dgs=" + r(BytecodeViewer.viewer.dgs.isSelected()), "-ner=" + r(BytecodeViewer.viewer.ner.isSelected()), "-den=" + r(BytecodeViewer.viewer.den.isSelected()), "-rgn=" + r(BytecodeViewer.viewer.rgn.isSelected()), "-bto=" + r(BytecodeViewer.viewer.bto.isSelected()), "-nns=" + r(BytecodeViewer.viewer.nns.isSelected()), "-uto=" + r(BytecodeViewer.viewer.uto.isSelected()), "-udv=" + r(BytecodeViewer.viewer.udv.isSelected()), "-rer=" + r(BytecodeViewer.viewer.rer.isSelected()), "-fdi=" + r(BytecodeViewer.viewer.fdi.isSelected()), "-asc=" + r(BytecodeViewer.viewer.asc.isSelected()), "-ren=" + r(BytecodeViewer.viewer.ren.isSelected()), className, folder};
|
||||
}
|
||||
|
||||
private String r(boolean b) {
|
||||
if (b) {
|
||||
private String r(boolean b)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
return "1";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,12 +20,6 @@ package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
|||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.JadxDecompiler;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Random;
|
||||
import me.konloch.kontainer.io.DiskReader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
@ -34,9 +28,10 @@ import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
|||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
||||
import java.io.*;
|
||||
import java.util.Random;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.ERROR;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.JADX;
|
||||
|
||||
|
@ -50,22 +45,27 @@ public class JADXDecompiler extends InternalDecompiler
|
|||
private final Random r = new Random();
|
||||
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b) {
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
{
|
||||
String fileStart = tempDirectory + fs;
|
||||
|
||||
String exception = "";
|
||||
final File tempClass = new File(MiscUtils.getUniqueName(fileStart, ".class") + ".class");
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass)) {
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass))
|
||||
{
|
||||
fos.write(b);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
|
||||
File fuckery = new File(fuckery(fileStart));
|
||||
fuckery.mkdirs();
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
JadxArgs args = new JadxArgs();
|
||||
args.setInputFile(tempClass);
|
||||
args.setOutDir(fuckery);
|
||||
|
@ -75,7 +75,9 @@ public class JADXDecompiler extends InternalDecompiler
|
|||
JadxDecompiler jadx = new JadxDecompiler(args);
|
||||
jadx.load();
|
||||
jadx.saveSources();
|
||||
} catch (StackOverflowError | Exception e) {
|
||||
}
|
||||
catch (StackOverflowError | Exception e)
|
||||
{
|
||||
StringWriter exceptionWriter = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(exceptionWriter));
|
||||
e.printStackTrace();
|
||||
|
@ -87,12 +89,10 @@ public class JADXDecompiler extends InternalDecompiler
|
|||
if (fuckery.exists())
|
||||
return findFile(MiscUtils.listFiles(fuckery));
|
||||
|
||||
if(exception.isEmpty())
|
||||
if (exception.isEmpty())
|
||||
exception = "Decompiled source file not found!";
|
||||
|
||||
return JADX + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO +
|
||||
nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR +
|
||||
nl + nl + exception;
|
||||
return JADX + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR + nl + nl + exception;
|
||||
}
|
||||
|
||||
//TODO remove
|
||||
|
@ -109,32 +109,37 @@ public class JADXDecompiler extends InternalDecompiler
|
|||
return null;
|
||||
}
|
||||
|
||||
public String findFile(File[] fA) {
|
||||
for (File f : fA) {
|
||||
public String findFile(File[] fA)
|
||||
{
|
||||
for (File f : fA)
|
||||
{
|
||||
if (f.isDirectory())
|
||||
return findFile(MiscUtils.listFiles(f));
|
||||
else {
|
||||
else
|
||||
{
|
||||
String s;
|
||||
try {
|
||||
try
|
||||
{
|
||||
s = DiskReader.loadAsString(f.getAbsolutePath());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
String exception = ExceptionUI.SEND_STACKTRACE_TO_NL + sw;
|
||||
|
||||
return JADX + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO +
|
||||
nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR +
|
||||
nl + nl + exception;
|
||||
return JADX + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR + nl + nl + exception;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
return "JADX error!" +
|
||||
nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR;
|
||||
return "JADX error!" + nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName) { }
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import me.konloch.kontainer.io.DiskReader;
|
||||
import org.jd.core.v1.ClassFileToJavaSourceDecompiler;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
@ -38,6 +32,8 @@ import the.bytecode.club.bytecodeviewer.decompilers.jdgui.PlainTextPrinter;
|
|||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.ERROR;
|
||||
|
@ -54,28 +50,35 @@ public class JDGUIDecompiler extends InternalDecompiler
|
|||
{
|
||||
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b) {
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
{
|
||||
String exception;
|
||||
try {
|
||||
try
|
||||
{
|
||||
final File tempDirectory = new File(Constants.tempDirectory + fs + MiscUtils.randomString(32) + fs);
|
||||
tempDirectory.mkdir();
|
||||
|
||||
final File tempClass = new File(tempDirectory.getAbsolutePath() + fs + cn.name + ".class");
|
||||
final File tempJava = new File(tempDirectory.getAbsolutePath() + fs + cn.name + ".java");
|
||||
|
||||
if (cn.name.contains("/")) {
|
||||
if (cn.name.contains("/"))
|
||||
{
|
||||
String[] raw = cn.name.split("/");
|
||||
String path = tempDirectory.getAbsolutePath() + fs;
|
||||
for (int i = 0; i < raw.length - 1; i++) {
|
||||
for (int i = 0; i < raw.length - 1; i++)
|
||||
{
|
||||
path += raw[i] + fs;
|
||||
File f = new File(path);
|
||||
f.mkdir();
|
||||
}
|
||||
}
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass)) {
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass))
|
||||
{
|
||||
fos.write(b);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
|
||||
|
@ -84,14 +87,17 @@ public class JDGUIDecompiler extends InternalDecompiler
|
|||
String directoryPath = JDGUIClassFileUtil.ExtractDirectoryPath(pathToClass);
|
||||
String internalPath = JDGUIClassFileUtil.ExtractInternalPath(directoryPath, pathToClass);
|
||||
|
||||
CommonPreferences preferences = new CommonPreferences() {
|
||||
CommonPreferences preferences = new CommonPreferences()
|
||||
{
|
||||
@Override
|
||||
public boolean isShowLineNumbers() {
|
||||
public boolean isShowLineNumbers()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMergeEmptyLines() {
|
||||
public boolean isMergeEmptyLines()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -102,13 +108,15 @@ public class JDGUIDecompiler extends InternalDecompiler
|
|||
//HtmlPrinter printer = new HtmlPrinter(ps);
|
||||
org.jd.core.v1.api.Decompiler decompiler = new ClassFileToJavaSourceDecompiler();
|
||||
|
||||
try (PrintStream ps = new PrintStream(tempJava.getAbsolutePath());
|
||||
PlainTextPrinter printer = new PlainTextPrinter(preferences, ps)) {
|
||||
try (PrintStream ps = new PrintStream(tempJava.getAbsolutePath()); PlainTextPrinter printer = new PlainTextPrinter(preferences, ps))
|
||||
{
|
||||
decompiler.decompile(loader, printer, internalPath, preferences.getPreferences());
|
||||
}
|
||||
|
||||
return DiskReader.loadAsString(tempJava.getAbsolutePath());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
|
@ -116,12 +124,11 @@ public class JDGUIDecompiler extends InternalDecompiler
|
|||
exception = ExceptionUI.SEND_STACKTRACE_TO_NL + sw;
|
||||
}
|
||||
|
||||
return JDGUI + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO +
|
||||
nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR +
|
||||
nl + nl + exception;
|
||||
return JDGUI + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR + nl + nl + exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName) {
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import me.konloch.kontainer.io.DiskWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
@ -33,12 +29,17 @@ import the.bytecode.club.bytecodeviewer.resources.ExternalResources;
|
|||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.api.ExceptionUI.SEND_STACKTRACE_TO;
|
||||
|
||||
/**
|
||||
* Javap disassembler
|
||||
*
|
||||
* <p>
|
||||
* https://github.com/Konloch/bytecode-viewer/issues/93
|
||||
*
|
||||
* @author Konloch
|
||||
|
@ -50,7 +51,7 @@ public class JavapDisassembler extends InternalDecompiler
|
|||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
{
|
||||
if(!ExternalResources.getSingleton().hasJavaToolsSet())
|
||||
if (!ExternalResources.getSingleton().hasJavaToolsSet())
|
||||
return "Set Java Tools Path!";
|
||||
|
||||
return synchronizedDecompilation(cn, b);
|
||||
|
@ -68,10 +69,7 @@ public class JavapDisassembler extends InternalDecompiler
|
|||
try
|
||||
{
|
||||
//load java tools into a temporary classloader
|
||||
URLClassLoader child = new URLClassLoader(
|
||||
new URL[] {new File(Configuration.javaTools).toURI().toURL()},
|
||||
this.getClass().getClassLoader()
|
||||
);
|
||||
URLClassLoader child = new URLClassLoader(new URL[]{new File(Configuration.javaTools).toURI().toURL()}, this.getClass().getClassLoader());
|
||||
|
||||
//setup reflection
|
||||
Class<?> javap = child.loadClass("com.sun.tools.javap.Main");
|
||||
|
@ -84,8 +82,7 @@ public class JavapDisassembler extends InternalDecompiler
|
|||
BytecodeViewer.sm.silenceExec(true);
|
||||
|
||||
//invoke Javap
|
||||
main.invoke(null, (Object) new String[]{
|
||||
"-p", //Shows all classes and members
|
||||
main.invoke(null, (Object) new String[]{"-p", //Shows all classes and members
|
||||
"-c", //Prints out disassembled code
|
||||
//"-l", //Prints out line and local variable tables
|
||||
"-constants", //Shows static final constants
|
||||
|
@ -105,7 +102,7 @@ public class JavapDisassembler extends InternalDecompiler
|
|||
tempClass.delete();
|
||||
}
|
||||
|
||||
if(sysOutBuffer != null)
|
||||
if (sysOutBuffer != null)
|
||||
{
|
||||
sysOutBuffer.finished();
|
||||
return sysOutBuffer.getTextAreaOutputStreamOut().getBuffer().toString();
|
||||
|
@ -115,5 +112,7 @@ public class JavapDisassembler extends InternalDecompiler
|
|||
}
|
||||
|
||||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName) { }
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,14 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
import me.konloch.kontainer.io.DiskReader;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
@ -40,9 +32,11 @@ import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
|||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.ZipUtils;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.krakatauWorkingDirectory;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
* Krakatau Java Decompiler Wrapper, requires Python 2.7
|
||||
|
@ -67,50 +61,38 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
if (files == null || files.length == 0)
|
||||
return "";
|
||||
|
||||
return ";" + Arrays.stream(files).filter(File::isFile)
|
||||
.map(File::getAbsolutePath).collect(Collectors.joining(";"));
|
||||
return ";" + Arrays.stream(files).filter(File::isFile).map(File::getAbsolutePath).collect(Collectors.joining(";"));
|
||||
}
|
||||
|
||||
public String decompileClassNode(File krakatauTempJar, File krakatauTempDir, ClassNode cn)
|
||||
{
|
||||
if(!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
if (!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
return TranslatedStrings.YOU_NEED_TO_SET_YOUR_PYTHON_2_PATH.toString();
|
||||
|
||||
ExternalResources.getSingleton().rtCheck();
|
||||
if (Configuration.rt.isEmpty())
|
||||
{
|
||||
BytecodeViewer.showMessage(TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_A
|
||||
+ "\r\n" + TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_B);
|
||||
BytecodeViewer.showMessage(TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_A + "\r\n" + TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_B);
|
||||
ExternalResources.getSingleton().selectJRERTLibrary();
|
||||
}
|
||||
|
||||
if (Configuration.rt.isEmpty())
|
||||
{
|
||||
BytecodeViewer.showMessage(TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_A
|
||||
+ "\r\n" + TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_B);
|
||||
return TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_A
|
||||
+ " " + TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_B;
|
||||
BytecodeViewer.showMessage(TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_A + "\r\n" + TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_B);
|
||||
return TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_A + " " + TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_B;
|
||||
}
|
||||
|
||||
String s = ExceptionUI.SEND_STACKTRACE_TO_NL;
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
String[] pythonCommands = new String[]{Configuration.python2};
|
||||
if(Configuration.python2Extra)
|
||||
if (Configuration.python2Extra)
|
||||
pythonCommands = ArrayUtils.addAll(pythonCommands, "-2");
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
|
||||
pythonCommands,
|
||||
"-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "decompile.py",
|
||||
"-skip", //love you storyyeller <3
|
||||
"-nauto",
|
||||
"-path",
|
||||
Configuration.rt + ";" + krakatauTempJar.getAbsolutePath() + buildCLIArguments(),
|
||||
"-out",
|
||||
krakatauTempDir.getAbsolutePath(),
|
||||
cn.name + ".class"
|
||||
));
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(pythonCommands, "-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "decompile.py", "-skip", //love you storyyeller <3
|
||||
"-nauto", "-path", Configuration.rt + ";" + krakatauTempJar.getAbsolutePath() + buildCLIArguments(), "-out", krakatauTempDir.getAbsolutePath(), cn.name + ".class"));
|
||||
|
||||
Process process = pb.start();
|
||||
BytecodeViewer.createdProcesses.add(process);
|
||||
|
@ -118,22 +100,22 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
StringBuilder log = new StringBuilder(TranslatedStrings.PROCESS2 + nl + nl);
|
||||
|
||||
//Read out dir output
|
||||
try (InputStream is = process.getInputStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr)) {
|
||||
try (InputStream is = process.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
log.append(nl).append(line);
|
||||
}
|
||||
}
|
||||
|
||||
log.append(nl).append(nl).append(TranslatedStrings.ERROR2).append(nl).append(nl);
|
||||
|
||||
try (InputStream is = process.getErrorStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr)) {
|
||||
try (InputStream is = process.getErrorStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
log.append(nl).append(line);
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +126,9 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
|
||||
//if the motherfucker failed this'll fail, aka wont set.
|
||||
s = DiskReader.loadAsString(krakatauTempDir.getAbsolutePath() + fs + cn.name + ".java");
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
|
@ -159,16 +143,17 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
{
|
||||
//TODO look into transforming through krakatau as a zip rather than direct classfile
|
||||
|
||||
if(!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
if (!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
return TranslatedStrings.YOU_NEED_TO_SET_YOUR_PYTHON_2_PATH.toString();
|
||||
|
||||
if (Configuration.rt.isEmpty()) {
|
||||
BytecodeViewer.showMessage(TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_A
|
||||
+ "\r\n" + TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_B);
|
||||
if (Configuration.rt.isEmpty())
|
||||
{
|
||||
BytecodeViewer.showMessage(TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_A + "\r\n" + TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_B);
|
||||
ExternalResources.getSingleton().selectJRERTLibrary();
|
||||
}
|
||||
|
||||
if (Configuration.rt.isEmpty()) {
|
||||
if (Configuration.rt.isEmpty())
|
||||
{
|
||||
BytecodeViewer.showMessage("You need to set RT.jar!");
|
||||
return "Set your paths";
|
||||
}
|
||||
|
@ -181,23 +166,15 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
|
||||
JarUtils.saveAsJarClassesOnly(BytecodeViewer.getLoadedClasses(), tempJar.getAbsolutePath());
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
String[] pythonCommands = new String[]{Configuration.python2};
|
||||
if(Configuration.python2Extra)
|
||||
if (Configuration.python2Extra)
|
||||
pythonCommands = ArrayUtils.addAll(pythonCommands, "-2");
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
|
||||
pythonCommands,
|
||||
"-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "decompile.py",
|
||||
"-skip", //love you storyyeller <3
|
||||
"-nauto",
|
||||
"-path",
|
||||
Configuration.rt + ";" + tempJar.getAbsolutePath() + buildCLIArguments(),
|
||||
"-out",
|
||||
tempDirectory.getAbsolutePath(),
|
||||
cn.name + ".class"
|
||||
));
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(pythonCommands, "-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "decompile.py", "-skip", //love you storyyeller <3
|
||||
"-nauto", "-path", Configuration.rt + ";" + tempJar.getAbsolutePath() + buildCLIArguments(), "-out", tempDirectory.getAbsolutePath(), cn.name + ".class"));
|
||||
|
||||
Process process = pb.start();
|
||||
BytecodeViewer.createdProcesses.add(process);
|
||||
|
@ -205,22 +182,22 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
StringBuilder log = new StringBuilder(TranslatedStrings.PROCESS2 + nl + nl);
|
||||
|
||||
//Read out dir output
|
||||
try (InputStream is = process.getInputStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr)) {
|
||||
try (InputStream is = process.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
log.append(nl).append(line);
|
||||
}
|
||||
}
|
||||
|
||||
log.append(nl).append(nl).append(TranslatedStrings.ERROR2).append(nl).append(nl);
|
||||
|
||||
try (InputStream is = process.getErrorStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr)) {
|
||||
try (InputStream is = process.getErrorStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
log.append(nl).append(line);
|
||||
}
|
||||
}
|
||||
|
@ -233,7 +210,9 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
s = DiskReader.loadAsString(tempDirectory.getAbsolutePath() + fs + cn.name + ".java");
|
||||
tempDirectory.delete();
|
||||
tempJar.delete();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
|
@ -244,14 +223,15 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
}
|
||||
|
||||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName) {
|
||||
if(!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
if (!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
return;
|
||||
|
||||
ExternalResources.getSingleton().rtCheck();
|
||||
if (Configuration.rt.isEmpty()) {
|
||||
BytecodeViewer.showMessage(TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_A
|
||||
+ "\r\n" + TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_B);
|
||||
if (Configuration.rt.isEmpty())
|
||||
{
|
||||
BytecodeViewer.showMessage(TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_A + "\r\n" + TranslatedStrings.YOU_NEED_TO_SET_YOUR_JAVA_RT_PATH_B);
|
||||
ExternalResources.getSingleton().selectJRERTLibrary();
|
||||
}
|
||||
|
||||
|
@ -261,23 +241,15 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
|
||||
final File tempJar = new File(sourceJar);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
String[] pythonCommands = new String[]{Configuration.python2};
|
||||
if(Configuration.python2Extra)
|
||||
if (Configuration.python2Extra)
|
||||
pythonCommands = ArrayUtils.addAll(pythonCommands, "-2");
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
|
||||
pythonCommands,
|
||||
"-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "decompile.py",
|
||||
"-skip", //love you storyyeller <3
|
||||
"-nauto",
|
||||
"-path",
|
||||
Configuration.rt + ";" + tempJar.getAbsolutePath(),
|
||||
"-out",
|
||||
tempDirectory.getAbsolutePath(),
|
||||
tempJar.getAbsolutePath()
|
||||
));
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(pythonCommands, "-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "decompile.py", "-skip", //love you storyyeller <3
|
||||
"-nauto", "-path", Configuration.rt + ";" + tempJar.getAbsolutePath(), "-out", tempDirectory.getAbsolutePath(), tempJar.getAbsolutePath()));
|
||||
|
||||
Process process = pb.start();
|
||||
BytecodeViewer.createdProcesses.add(process);
|
||||
|
@ -285,7 +257,9 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
MiscUtils.printProcess(process);
|
||||
|
||||
ZipUtils.zipFolder(tempDirectory.getAbsolutePath(), zipName, ran);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import me.konloch.kontainer.io.DiskReader;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
@ -38,9 +32,9 @@ import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
|||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.ZipUtils;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.krakatauWorkingDirectory;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import java.io.*;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
* Krakatau Java Disassembler Wrapper, requires Python 2.7
|
||||
|
@ -51,8 +45,9 @@ import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
|||
public class KrakatauDisassembler extends InternalDecompiler
|
||||
{
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b) {
|
||||
if(!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
{
|
||||
if (!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
return TranslatedStrings.YOU_NEED_TO_SET_YOUR_PYTHON_2_PATH.toString();
|
||||
|
||||
String s = ExceptionUI.SEND_STACKTRACE_TO_NL;
|
||||
|
@ -62,21 +57,14 @@ public class KrakatauDisassembler extends InternalDecompiler
|
|||
final File tempJar = new File(Constants.tempDirectory + fs + "temp" + MiscUtils.randomString(32) + ".jar");
|
||||
JarUtils.saveAsJarClassesOnly(BytecodeViewer.getLoadedClasses(), tempJar.getAbsolutePath());
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
String[] pythonCommands = new String[]{Configuration.python2};
|
||||
if(Configuration.python2Extra)
|
||||
if (Configuration.python2Extra)
|
||||
pythonCommands = ArrayUtils.addAll(pythonCommands, "-2");
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
|
||||
pythonCommands,
|
||||
"-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "disassemble.py",
|
||||
"-path",
|
||||
tempJar.getAbsolutePath(),
|
||||
"-out",
|
||||
tempDirectory.getAbsolutePath(),
|
||||
cn.name + ".class"
|
||||
));
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(pythonCommands, "-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "disassemble.py", "-path", tempJar.getAbsolutePath(), "-out", tempDirectory.getAbsolutePath(), cn.name + ".class"));
|
||||
|
||||
Process process = pb.start();
|
||||
BytecodeViewer.createdProcesses.add(process);
|
||||
|
@ -84,22 +72,22 @@ public class KrakatauDisassembler extends InternalDecompiler
|
|||
StringBuilder log = new StringBuilder(TranslatedStrings.PROCESS2 + nl + nl);
|
||||
|
||||
//Read out dir output
|
||||
try (InputStream is = process.getInputStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr)) {
|
||||
try (InputStream is = process.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
log.append(nl).append(line);
|
||||
}
|
||||
}
|
||||
|
||||
log.append(nl).append(nl).append(TranslatedStrings.ERROR2).append(nl).append(nl);
|
||||
|
||||
try (InputStream is = process.getErrorStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr)) {
|
||||
try (InputStream is = process.getErrorStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
log.append(nl).append(line);
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +98,9 @@ public class KrakatauDisassembler extends InternalDecompiler
|
|||
|
||||
// if the motherfucker failed this'll fail, aka won't set.
|
||||
s = DiskReader.loadAsString(tempDirectory.getAbsolutePath() + fs + cn.name + ".j");
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
|
@ -120,8 +110,9 @@ public class KrakatauDisassembler extends InternalDecompiler
|
|||
}
|
||||
|
||||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName) {
|
||||
if(!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
if (!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
return;
|
||||
|
||||
String ran = MiscUtils.randomString(32);
|
||||
|
@ -130,28 +121,23 @@ public class KrakatauDisassembler extends InternalDecompiler
|
|||
|
||||
final File tempJar = new File(sourceJar);
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
String[] pythonCommands = new String[]{Configuration.python2};
|
||||
if(Configuration.python2Extra)
|
||||
if (Configuration.python2Extra)
|
||||
pythonCommands = ArrayUtils.addAll(pythonCommands, "-2");
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
|
||||
pythonCommands,
|
||||
"-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "disassemble.py",
|
||||
"-path",
|
||||
Configuration.rt + ";" + tempJar.getAbsolutePath(),
|
||||
"-out",
|
||||
tempDirectory.getAbsolutePath(),
|
||||
tempJar.getAbsolutePath()
|
||||
));
|
||||
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(pythonCommands, "-O", //love you storyyeller <3
|
||||
krakatauWorkingDirectory + fs + "disassemble.py", "-path", Configuration.rt + ";" + tempJar.getAbsolutePath(), "-out", tempDirectory.getAbsolutePath(), tempJar.getAbsolutePath()));
|
||||
|
||||
Process process = pb.start();
|
||||
BytecodeViewer.createdProcesses.add(process);
|
||||
process.waitFor();
|
||||
|
||||
ZipUtils.zipFolder(tempDirectory.getAbsolutePath(), zipName, ran);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,35 +19,12 @@
|
|||
package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
||||
|
||||
import com.strobel.assembler.InputTypeLoader;
|
||||
import com.strobel.assembler.metadata.Buffer;
|
||||
import com.strobel.assembler.metadata.ITypeLoader;
|
||||
import com.strobel.assembler.metadata.JarTypeLoader;
|
||||
import com.strobel.assembler.metadata.MetadataSystem;
|
||||
import com.strobel.assembler.metadata.TypeDefinition;
|
||||
import com.strobel.assembler.metadata.TypeReference;
|
||||
import com.strobel.assembler.metadata.*;
|
||||
import com.strobel.core.StringUtilities;
|
||||
import com.strobel.decompiler.DecompilationOptions;
|
||||
import com.strobel.decompiler.DecompilerSettings;
|
||||
import com.strobel.decompiler.PlainTextOutput;
|
||||
import com.strobel.decompiler.languages.java.JavaFormattingOptions;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
|
||||
|
@ -56,9 +33,14 @@ import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
|||
import the.bytecode.club.bytecodeviewer.util.EncodeUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.ERROR;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.PROCYON;
|
||||
|
||||
|
@ -68,9 +50,11 @@ import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.PRO
|
|||
* @author Konloch
|
||||
* @author DeathMarine
|
||||
*/
|
||||
public class ProcyonDecompiler extends InternalDecompiler {
|
||||
public class ProcyonDecompiler extends InternalDecompiler
|
||||
{
|
||||
|
||||
public DecompilerSettings getDecompilerSettings() {
|
||||
public DecompilerSettings getDecompilerSettings()
|
||||
{
|
||||
DecompilerSettings settings = new DecompilerSettings();
|
||||
settings.setAlwaysGenerateExceptionVariableForCatchBlocks(BytecodeViewer.viewer.alwaysGenerateExceptionVars.isSelected());
|
||||
settings.setExcludeNestedTypes(BytecodeViewer.viewer.excludeNestedTypes.isSelected());
|
||||
|
@ -91,16 +75,21 @@ public class ProcyonDecompiler extends InternalDecompiler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b) {
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
{
|
||||
String exception;
|
||||
try {
|
||||
try
|
||||
{
|
||||
String fileStart = tempDirectory + fs + "temp";
|
||||
|
||||
final File tempClass = new File(MiscUtils.getUniqueName(fileStart, ".class") + ".class");
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass)) {
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass))
|
||||
{
|
||||
fos.write(b);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
|
||||
|
@ -122,7 +111,9 @@ public class ProcyonDecompiler extends InternalDecompiler {
|
|||
settings.getLanguage().decompileType(resolvedType, new PlainTextOutput(stringwriter), decompilationOptions);
|
||||
|
||||
return EncodeUtils.unicodeToString(stringwriter.toString());
|
||||
} catch (StackOverflowError | Exception e) {
|
||||
}
|
||||
catch (StackOverflowError | Exception e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
|
@ -130,16 +121,18 @@ public class ProcyonDecompiler extends InternalDecompiler {
|
|||
exception = ExceptionUI.SEND_STACKTRACE_TO_NL + sw;
|
||||
}
|
||||
|
||||
return PROCYON + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO +
|
||||
nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR +
|
||||
nl + nl + exception;
|
||||
return PROCYON + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR + nl + nl + exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName) {
|
||||
try {
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
try
|
||||
{
|
||||
doSaveJarDecompiled(new File(sourceJar), new File(zipName));
|
||||
} catch (StackOverflowError | Exception e) {
|
||||
}
|
||||
catch (StackOverflowError | Exception e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
}
|
||||
|
@ -147,12 +140,10 @@ public class ProcyonDecompiler extends InternalDecompiler {
|
|||
/**
|
||||
* @author DeathMarine
|
||||
*/
|
||||
private void doSaveJarDecompiled(File inFile, File outFile)
|
||||
throws Exception {
|
||||
try (JarFile jfile = new JarFile(inFile);
|
||||
FileOutputStream dest = new FileOutputStream(outFile);
|
||||
BufferedOutputStream buffDest = new BufferedOutputStream(dest);
|
||||
ZipOutputStream out = new ZipOutputStream(buffDest)) {
|
||||
private void doSaveJarDecompiled(File inFile, File outFile) throws Exception
|
||||
{
|
||||
try (JarFile jfile = new JarFile(inFile); FileOutputStream dest = new FileOutputStream(outFile); BufferedOutputStream buffDest = new BufferedOutputStream(dest); ZipOutputStream out = new ZipOutputStream(buffDest))
|
||||
{
|
||||
byte[] data = new byte[1024];
|
||||
DecompilerSettings settings = getDecompilerSettings();
|
||||
LuytenTypeLoader typeLoader = new LuytenTypeLoader();
|
||||
|
@ -166,52 +157,64 @@ public class ProcyonDecompiler extends InternalDecompiler {
|
|||
|
||||
Enumeration<JarEntry> ent = jfile.entries();
|
||||
Set<JarEntry> history = new HashSet<>();
|
||||
while (ent.hasMoreElements()) {
|
||||
while (ent.hasMoreElements())
|
||||
{
|
||||
JarEntry entry = ent.nextElement();
|
||||
if (entry.getName().endsWith(".class")) {
|
||||
JarEntry etn = new JarEntry(entry.getName().replace(
|
||||
".class", ".java"));
|
||||
if (history.add(etn)) {
|
||||
if (entry.getName().endsWith(".class"))
|
||||
{
|
||||
JarEntry etn = new JarEntry(entry.getName().replace(".class", ".java"));
|
||||
if (history.add(etn))
|
||||
{
|
||||
out.putNextEntry(etn);
|
||||
try {
|
||||
String internalName = StringUtilities.removeRight(
|
||||
entry.getName(), ".class");
|
||||
TypeReference type = metadataSystem
|
||||
.lookupType(internalName);
|
||||
try
|
||||
{
|
||||
String internalName = StringUtilities.removeRight(entry.getName(), ".class");
|
||||
TypeReference type = metadataSystem.lookupType(internalName);
|
||||
TypeDefinition resolvedType;
|
||||
if ((type == null)
|
||||
|| ((resolvedType = type.resolve()) == null)) {
|
||||
if ((type == null) || ((resolvedType = type.resolve()) == null))
|
||||
{
|
||||
throw new Exception("Unable to resolve type.");
|
||||
}
|
||||
Writer writer = new OutputStreamWriter(out);
|
||||
settings.getLanguage().decompileType(resolvedType,
|
||||
new PlainTextOutput(writer),
|
||||
decompilationOptions);
|
||||
settings.getLanguage().decompileType(resolvedType, new PlainTextOutput(writer), decompilationOptions);
|
||||
writer.flush();
|
||||
} finally {
|
||||
}
|
||||
finally
|
||||
{
|
||||
out.closeEntry();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
JarEntry etn = new JarEntry(entry.getName());
|
||||
if (history.add(etn))
|
||||
continue;
|
||||
history.add(etn);
|
||||
out.putNextEntry(etn);
|
||||
try (InputStream in = jfile.getInputStream(entry)) {
|
||||
if (in != null) {
|
||||
try (InputStream in = jfile.getInputStream(entry))
|
||||
{
|
||||
if (in != null)
|
||||
{
|
||||
int count;
|
||||
while ((count = in.read(data, 0, 1024)) != -1) {
|
||||
while ((count = in.read(data, 0, 1024)) != -1)
|
||||
{
|
||||
out.write(data, 0, count);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
}
|
||||
finally
|
||||
{
|
||||
out.closeEntry();
|
||||
}
|
||||
} catch (ZipException ze) {
|
||||
}
|
||||
catch (ZipException ze)
|
||||
{
|
||||
// some jars contain duplicate pom.xml entries: ignore it
|
||||
if (!ze.getMessage().contains("duplicate")) {
|
||||
if (!ze.getMessage().contains("duplicate"))
|
||||
{
|
||||
throw ze;
|
||||
}
|
||||
}
|
||||
|
@ -223,23 +226,29 @@ public class ProcyonDecompiler extends InternalDecompiler {
|
|||
/**
|
||||
* @author DeathMarine
|
||||
*/
|
||||
public static final class LuytenTypeLoader implements ITypeLoader {
|
||||
public static final class LuytenTypeLoader implements ITypeLoader
|
||||
{
|
||||
|
||||
private final List<ITypeLoader> _typeLoaders;
|
||||
|
||||
public LuytenTypeLoader() {
|
||||
public LuytenTypeLoader()
|
||||
{
|
||||
_typeLoaders = new ArrayList<>();
|
||||
_typeLoaders.add(new InputTypeLoader());
|
||||
}
|
||||
|
||||
public List<ITypeLoader> getTypeLoaders() {
|
||||
public List<ITypeLoader> getTypeLoaders()
|
||||
{
|
||||
return _typeLoaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryLoadType(String internalName, Buffer buffer) {
|
||||
for (ITypeLoader typeLoader : _typeLoaders) {
|
||||
if (typeLoader.tryLoadType(internalName, buffer)) {
|
||||
public boolean tryLoadType(String internalName, Buffer buffer)
|
||||
{
|
||||
for (ITypeLoader typeLoader : _typeLoaders)
|
||||
{
|
||||
if (typeLoader.tryLoadType(internalName, buffer))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,12 +19,6 @@
|
|||
package the.bytecode.club.bytecodeviewer.decompilers.impl;
|
||||
|
||||
import com.googlecode.d2j.smali.BaksmaliCmd;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Objects;
|
||||
import me.konloch.kontainer.io.DiskReader;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
@ -35,12 +29,11 @@ import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
|||
import the.bytecode.club.bytecodeviewer.util.Dex2Jar;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.DISASSEMBLER;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.ERROR;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.SMALI;
|
||||
import java.io.*;
|
||||
import java.util.Objects;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.*;
|
||||
|
||||
/**
|
||||
* Smali Disassembler Wrapper
|
||||
|
@ -63,9 +56,12 @@ public class SmaliDisassembler extends InternalDecompiler
|
|||
final File tempDexOut = new File(start + "-out");
|
||||
final File tempSmali = new File(start + "-smali"); //output directory
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass)) {
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass))
|
||||
{
|
||||
fos.write(b);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
|
||||
|
@ -73,10 +69,12 @@ public class SmaliDisassembler extends InternalDecompiler
|
|||
|
||||
Dex2Jar.saveAsDex(tempClass, tempDex, true);
|
||||
|
||||
try {
|
||||
BaksmaliCmd.main(tempDex.getAbsolutePath(),
|
||||
"-o", tempDexOut.getAbsolutePath());
|
||||
} catch (Exception e) {
|
||||
try
|
||||
{
|
||||
BaksmaliCmd.main(tempDex.getAbsolutePath(), "-o", tempDexOut.getAbsolutePath());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
|
@ -84,9 +82,12 @@ public class SmaliDisassembler extends InternalDecompiler
|
|||
exception += ExceptionUI.SEND_STACKTRACE_TO_NL + sw;
|
||||
}
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
FileUtils.moveDirectory(tempDexOut, tempSmali);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
|
@ -98,19 +99,24 @@ public class SmaliDisassembler extends InternalDecompiler
|
|||
|
||||
boolean found = false;
|
||||
File current = tempSmali;
|
||||
while (!found) {
|
||||
while (!found)
|
||||
{
|
||||
File f = Objects.requireNonNull(current.listFiles())[0];
|
||||
if (f.isDirectory())
|
||||
current = f;
|
||||
else {
|
||||
else
|
||||
{
|
||||
outputSmali = f;
|
||||
found = true;
|
||||
}
|
||||
|
||||
}
|
||||
try {
|
||||
try
|
||||
{
|
||||
return DiskReader.loadAsString(outputSmali.getAbsolutePath());
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
|
@ -118,13 +124,12 @@ public class SmaliDisassembler extends InternalDecompiler
|
|||
exception += ExceptionUI.SEND_STACKTRACE_TO_NL + sw;
|
||||
}
|
||||
|
||||
return SMALI + " " + DISASSEMBLER + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO +
|
||||
nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR +
|
||||
nl + nl + exception;
|
||||
return SMALI + " " + DISASSEMBLER + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + nl + nl + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR + nl + nl + exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName) {
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,8 @@ package the.bytecode.club.bytecodeviewer.decompilers.jdgui;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class CommonPreferences {
|
||||
public class CommonPreferences
|
||||
{
|
||||
private final Map<String, Object> preferences;
|
||||
protected boolean showDefaultConstructor;
|
||||
protected boolean realignmentLineNumber;
|
||||
|
@ -30,7 +31,8 @@ public class CommonPreferences {
|
|||
protected boolean unicodeEscape;
|
||||
protected boolean showLineNumbers;
|
||||
|
||||
public CommonPreferences() {
|
||||
public CommonPreferences()
|
||||
{
|
||||
this.showPrefixThis = true;
|
||||
this.mergeEmptyLines = false;
|
||||
this.unicodeEscape = false;
|
||||
|
@ -38,10 +40,8 @@ public class CommonPreferences {
|
|||
this.preferences = new HashMap<>();
|
||||
}
|
||||
|
||||
public CommonPreferences(
|
||||
boolean showDefaultConstructor, boolean realignmentLineNumber,
|
||||
boolean showPrefixThis, boolean mergeEmptyLines,
|
||||
boolean unicodeEscape, boolean showLineNumbers) {
|
||||
public CommonPreferences(boolean showDefaultConstructor, boolean realignmentLineNumber, boolean showPrefixThis, boolean mergeEmptyLines, boolean unicodeEscape, boolean showLineNumbers)
|
||||
{
|
||||
this.showDefaultConstructor = showDefaultConstructor;
|
||||
this.realignmentLineNumber = realignmentLineNumber;
|
||||
this.showPrefixThis = showPrefixThis;
|
||||
|
@ -51,31 +51,38 @@ public class CommonPreferences {
|
|||
this.preferences = new HashMap<>();
|
||||
}
|
||||
|
||||
public boolean isShowDefaultConstructor() {
|
||||
public boolean isShowDefaultConstructor()
|
||||
{
|
||||
return showDefaultConstructor;
|
||||
}
|
||||
|
||||
public boolean isRealignmentLineNumber() {
|
||||
public boolean isRealignmentLineNumber()
|
||||
{
|
||||
return realignmentLineNumber;
|
||||
}
|
||||
|
||||
public boolean isShowPrefixThis() {
|
||||
public boolean isShowPrefixThis()
|
||||
{
|
||||
return showPrefixThis;
|
||||
}
|
||||
|
||||
public boolean isMergeEmptyLines() {
|
||||
public boolean isMergeEmptyLines()
|
||||
{
|
||||
return mergeEmptyLines;
|
||||
}
|
||||
|
||||
public boolean isUnicodeEscape() {
|
||||
public boolean isUnicodeEscape()
|
||||
{
|
||||
return unicodeEscape;
|
||||
}
|
||||
|
||||
public boolean isShowLineNumbers() {
|
||||
public boolean isShowLineNumbers()
|
||||
{
|
||||
return showLineNumbers;
|
||||
}
|
||||
|
||||
public Map<String, Object> getPreferences() {
|
||||
public Map<String, Object> getPreferences()
|
||||
{
|
||||
return preferences;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.jdgui;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jd.core.v1.api.loader.Loader;
|
||||
import org.jd.core.v1.api.loader.LoaderException;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jd.core.v1.api.loader.Loader;
|
||||
import org.jd.core.v1.api.loader.LoaderException;
|
||||
|
||||
public class DirectoryLoader implements Loader
|
||||
{
|
||||
|
@ -43,21 +44,23 @@ public class DirectoryLoader implements Loader
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] load(String internalPath)
|
||||
throws LoaderException {
|
||||
public byte[] load(String internalPath) throws LoaderException
|
||||
{
|
||||
File file = new File(this.codebase, internalPath);
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(file);
|
||||
BufferedInputStream bis = new BufferedInputStream(fis)) {
|
||||
try (FileInputStream fis = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(fis))
|
||||
{
|
||||
return IOUtils.toByteArray(bis);
|
||||
} catch (IOException e) {
|
||||
throw new LoaderException(
|
||||
"'" + file.getAbsolutePath() + "' not found.");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new LoaderException("'" + file.getAbsolutePath() + "' not found.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canLoad(String internalPath) {
|
||||
public boolean canLoad(String internalPath)
|
||||
{
|
||||
File file = new File(this.codebase, internalPath);
|
||||
return file.exists() && file.isFile();
|
||||
}
|
||||
|
|
|
@ -18,17 +18,14 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.jdgui;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import org.jd.core.v1.model.classfile.constant.Constant;
|
||||
import org.jd.core.v1.model.classfile.constant.ConstantClass;
|
||||
import org.jd.core.v1.model.classfile.constant.ConstantUtf8;
|
||||
import org.jd.core.v1.service.deserializer.classfile.ClassFileFormatException;
|
||||
import org.jd.core.v1.service.deserializer.classfile.ClassFileReader;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
|
||||
public class JDGUIClassFileUtil
|
||||
{
|
||||
|
@ -39,14 +36,15 @@ public class JDGUIClassFileUtil
|
|||
* Lecture rapide de la structure de la classe et extraction du nom du
|
||||
* repoertoire de base.
|
||||
*/
|
||||
public static String ExtractDirectoryPath(String pathToClass) {
|
||||
public static String ExtractDirectoryPath(String pathToClass)
|
||||
{
|
||||
String directoryPath;
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(pathToClass);
|
||||
BufferedInputStream bis = new BufferedInputStream(fis);
|
||||
DataInputStream dis = new DataInputStream(bis)) {
|
||||
try (FileInputStream fis = new FileInputStream(pathToClass); BufferedInputStream bis = new BufferedInputStream(fis); DataInputStream dis = new DataInputStream(bis))
|
||||
{
|
||||
int magic = dis.readInt();
|
||||
if (magic != ClassFileReader.JAVA_MAGIC_NUMBER) {
|
||||
if (magic != ClassFileReader.JAVA_MAGIC_NUMBER)
|
||||
{
|
||||
throw new ClassFileFormatException("Invalid Java .class file");
|
||||
}
|
||||
|
||||
|
@ -61,32 +59,36 @@ public class JDGUIClassFileUtil
|
|||
dis.readUnsignedShort();
|
||||
int this_class = dis.readUnsignedShort();
|
||||
|
||||
if (this_class > constants.length) {
|
||||
if (this_class > constants.length)
|
||||
{
|
||||
throw new ClassFileFormatException("Unknown Java structure");
|
||||
}
|
||||
Constant c = constants[this_class];
|
||||
if ((c == null) || (c.getTag() != Constant.CONSTANT_Class)) {
|
||||
if ((c == null) || (c.getTag() != Constant.CONSTANT_Class))
|
||||
{
|
||||
throw new ClassFileFormatException("Invalid constant pool");
|
||||
}
|
||||
|
||||
c = constants[((ConstantClass) c).getNameIndex()];
|
||||
if ((c == null) || (c.getTag() != Constant.CONSTANT_Utf8)) {
|
||||
if ((c == null) || (c.getTag() != Constant.CONSTANT_Utf8))
|
||||
{
|
||||
throw new ClassFileFormatException("Invalid constant pool");
|
||||
}
|
||||
|
||||
String internalClassName = ((ConstantUtf8) c).getValue();
|
||||
String pathSuffix = internalClassName.replace(
|
||||
INTERNAL_PACKAGE_SEPARATOR, File.separatorChar) +
|
||||
CLASS_FILE_SUFFIX;
|
||||
String pathSuffix = internalClassName.replace(INTERNAL_PACKAGE_SEPARATOR, File.separatorChar) + CLASS_FILE_SUFFIX;
|
||||
|
||||
int index = pathToClass.indexOf(pathSuffix);
|
||||
|
||||
if (index < 0) {
|
||||
if (index < 0)
|
||||
{
|
||||
throw new ClassFileFormatException("Invalid internal class name");
|
||||
}
|
||||
|
||||
directoryPath = pathToClass.substring(0, index);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
directoryPath = null;
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -94,10 +96,9 @@ public class JDGUIClassFileUtil
|
|||
return directoryPath;
|
||||
}
|
||||
|
||||
public static String ExtractInternalPath(
|
||||
String directoryPath, String pathToClass) {
|
||||
if ((directoryPath == null) || (pathToClass == null) ||
|
||||
!pathToClass.startsWith(directoryPath))
|
||||
public static String ExtractInternalPath(String directoryPath, String pathToClass)
|
||||
{
|
||||
if ((directoryPath == null) || (pathToClass == null) || !pathToClass.startsWith(directoryPath))
|
||||
return null;
|
||||
|
||||
String s = pathToClass.substring(directoryPath.length());
|
||||
|
@ -105,15 +106,17 @@ public class JDGUIClassFileUtil
|
|||
return s.replace(File.separatorChar, INTERNAL_PACKAGE_SEPARATOR);
|
||||
}
|
||||
|
||||
private static Constant[] DeserializeConstants(DataInputStream dis)
|
||||
throws IOException {
|
||||
private static Constant[] DeserializeConstants(DataInputStream dis) throws IOException
|
||||
{
|
||||
int count = dis.readUnsignedShort();
|
||||
Constant[] constants = new Constant[count];
|
||||
|
||||
for (int i = 1; i < count; i++) {
|
||||
for (int i = 1; i < count; i++)
|
||||
{
|
||||
byte tag = dis.readByte();
|
||||
|
||||
switch (tag) {
|
||||
switch (tag)
|
||||
{
|
||||
case Constant.CONSTANT_Class:
|
||||
constants[i] = new ConstantClass(dis.readUnsignedShort());
|
||||
break;
|
||||
|
|
|
@ -18,11 +18,13 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.decompilers.jdgui;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.PrintStream;
|
||||
import org.jd.core.v1.api.printer.Printer;
|
||||
|
||||
public class PlainTextPrinter implements Printer, Closeable {
|
||||
import java.io.Closeable;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class PlainTextPrinter implements Printer, Closeable
|
||||
{
|
||||
protected static final String TAB = " ";
|
||||
protected static final String NEWLINE = "\n";
|
||||
|
||||
|
@ -38,8 +40,8 @@ public class PlainTextPrinter implements Printer, Closeable {
|
|||
protected int indentationCount;
|
||||
protected boolean display;
|
||||
|
||||
public PlainTextPrinter(
|
||||
CommonPreferences preferences, PrintStream printStream) {
|
||||
public PlainTextPrinter(CommonPreferences preferences, PrintStream printStream)
|
||||
{
|
||||
this.preferences = preferences;
|
||||
this.printStream = printStream;
|
||||
this.maxLineNumber = 0;
|
||||
|
@ -48,49 +50,57 @@ public class PlainTextPrinter implements Printer, Closeable {
|
|||
this.indentationCount = 0;
|
||||
}
|
||||
|
||||
public int getMajorVersion() {
|
||||
public int getMajorVersion()
|
||||
{
|
||||
return majorVersion;
|
||||
}
|
||||
|
||||
public int getMinorVersion() {
|
||||
public int getMinorVersion()
|
||||
{
|
||||
return minorVersion;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
|
||||
|
||||
@Override
|
||||
public void printKeyword(String s) {
|
||||
public void printKeyword(String s)
|
||||
{
|
||||
if (this.display)
|
||||
this.printStream.append(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDeclaration(int type, String internalTypeName, String name, String descriptor) {
|
||||
public void printDeclaration(int type, String internalTypeName, String name, String descriptor)
|
||||
{
|
||||
this.printStream.append(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printReference(int type, String internalTypeName, String name, String descriptor,
|
||||
String ownerInternalName) {
|
||||
public void printReference(int type, String internalTypeName, String name, String descriptor, String ownerInternalName)
|
||||
{
|
||||
this.printStream.append(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(int maxLineNumber, int majorVersion, int minorVersion) {
|
||||
public void start(int maxLineNumber, int majorVersion, int minorVersion)
|
||||
{
|
||||
this.majorVersion = majorVersion;
|
||||
this.minorVersion = minorVersion;
|
||||
this.indentationCount = 0;
|
||||
this.display = true;
|
||||
|
||||
if (this.preferences.isShowLineNumbers()) {
|
||||
if (this.preferences.isShowLineNumbers())
|
||||
{
|
||||
this.maxLineNumber = maxLineNumber;
|
||||
|
||||
if (maxLineNumber > 0) {
|
||||
if (maxLineNumber > 0)
|
||||
{
|
||||
this.digitCount = 1;
|
||||
StringBuilder unknownLineNumberPrefixBuilder = new StringBuilder(" ");
|
||||
int maximum = 9;
|
||||
|
||||
while (maximum < maxLineNumber) {
|
||||
while (maximum < maxLineNumber)
|
||||
{
|
||||
this.digitCount++;
|
||||
unknownLineNumberPrefixBuilder.append(' ');
|
||||
maximum = maximum * 10 + 9;
|
||||
|
@ -99,12 +109,16 @@ public class PlainTextPrinter implements Printer, Closeable {
|
|||
this.unknownLineNumberPrefix = unknownLineNumberPrefixBuilder.toString();
|
||||
this.lineNumberBeginPrefix = "/* ";
|
||||
this.lineNumberEndPrefix = " */ ";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
this.unknownLineNumberPrefix = "";
|
||||
this.lineNumberBeginPrefix = "";
|
||||
this.lineNumberEndPrefix = "";
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
this.maxLineNumber = 0;
|
||||
this.unknownLineNumberPrefix = "";
|
||||
this.lineNumberBeginPrefix = "";
|
||||
|
@ -113,44 +127,55 @@ public class PlainTextPrinter implements Printer, Closeable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
public void end()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printText(String s) {
|
||||
public void printText(String s)
|
||||
{
|
||||
if (this.display)
|
||||
printEscape(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printNumericConstant(String s) {
|
||||
public void printNumericConstant(String s)
|
||||
{
|
||||
this.printStream.append(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStringConstant(String s, String s1) {
|
||||
public void printStringConstant(String s, String s1)
|
||||
{
|
||||
this.printStream.append(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void indent() {
|
||||
public void indent()
|
||||
{
|
||||
this.indentationCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unindent() {
|
||||
public void unindent()
|
||||
{
|
||||
if (this.indentationCount > 0)
|
||||
this.indentationCount--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startLine(int lineNumber) {
|
||||
if (this.maxLineNumber > 0) {
|
||||
public void startLine(int lineNumber)
|
||||
{
|
||||
if (this.maxLineNumber > 0)
|
||||
{
|
||||
this.printStream.append(this.lineNumberBeginPrefix);
|
||||
|
||||
if (lineNumber == UNKNOWN_LINE_NUMBER) {
|
||||
if (lineNumber == UNKNOWN_LINE_NUMBER)
|
||||
{
|
||||
this.printStream.append(this.unknownLineNumberPrefix);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int left = 0;
|
||||
|
||||
left = printDigit(5, lineNumber, 10000, left);
|
||||
|
@ -168,15 +193,20 @@ public class PlainTextPrinter implements Printer, Closeable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void endLine() {
|
||||
public void endLine()
|
||||
{
|
||||
this.printStream.append(NEWLINE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void extraLine(int count) {
|
||||
if (!this.preferences.isMergeEmptyLines()) {
|
||||
while (count-- > 0) {
|
||||
if (this.maxLineNumber > 0) {
|
||||
public void extraLine(int count)
|
||||
{
|
||||
if (!this.preferences.isMergeEmptyLines())
|
||||
{
|
||||
while (count-- > 0)
|
||||
{
|
||||
if (this.maxLineNumber > 0)
|
||||
{
|
||||
this.printStream.append(this.lineNumberBeginPrefix);
|
||||
this.printStream.append(this.unknownLineNumberPrefix);
|
||||
this.printStream.append(this.lineNumberEndPrefix);
|
||||
|
@ -188,30 +218,40 @@ public class PlainTextPrinter implements Printer, Closeable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void startMarker(int i) {
|
||||
public void startMarker(int i)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endMarker(int i) {
|
||||
public void endMarker(int i)
|
||||
{
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
|
||||
|
||||
protected void printEscape(String s) {
|
||||
if (this.preferences.isUnicodeEscape()) {
|
||||
protected void printEscape(String s)
|
||||
{
|
||||
if (this.preferences.isUnicodeEscape())
|
||||
{
|
||||
int length = s.length();
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
char c = s.charAt(i);
|
||||
|
||||
if (c == '\t') {
|
||||
if (c == '\t')
|
||||
{
|
||||
this.printStream.append('\t');
|
||||
} else if (c < 32) {
|
||||
}
|
||||
else if (c < 32)
|
||||
{
|
||||
// Write octal format
|
||||
this.printStream.append("\\0");
|
||||
this.printStream.append((char) ('0' + (c >> 3)));
|
||||
this.printStream.append((char) ('0' + (c & 0x7)));
|
||||
} else if (c > 127) {
|
||||
}
|
||||
else if (c > 127)
|
||||
{
|
||||
// Write octal format
|
||||
this.printStream.append("\\u");
|
||||
|
||||
|
@ -223,20 +263,29 @@ public class PlainTextPrinter implements Printer, Closeable {
|
|||
this.printStream.append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z)));
|
||||
z = (c & 0xF);
|
||||
this.printStream.append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z)));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
this.printStream.append(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
this.printStream.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
protected int printDigit(int dcv, int lineNumber, int divisor, int left) {
|
||||
if (this.digitCount >= dcv) {
|
||||
if (lineNumber < divisor) {
|
||||
protected int printDigit(int dcv, int lineNumber, int divisor, int left)
|
||||
{
|
||||
if (this.digitCount >= dcv)
|
||||
{
|
||||
if (lineNumber < divisor)
|
||||
{
|
||||
this.printStream.append(' ');
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int e = (lineNumber - left) / divisor;
|
||||
this.printStream.append((char) ('0' + e));
|
||||
left += e * divisor;
|
||||
|
@ -247,7 +296,8 @@ public class PlainTextPrinter implements Printer, Closeable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
public void close()
|
||||
{
|
||||
if (this.printStream != null)
|
||||
this.printStream.close();
|
||||
}
|
||||
|
|
|
@ -18,25 +18,11 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||
import the.bytecode.club.bytecodeviewer.Constants;
|
||||
import the.bytecode.club.bytecodeviewer.SettingsSerializer;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.AboutWindow;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.RunOptions;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.SettingsDialog;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.VisibleComponent;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.WaitBusyIcon;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.*;
|
||||
import the.bytecode.club.bytecodeviewer.gui.plugins.MaliciousCodeScannerOptions;
|
||||
import the.bytecode.club.bytecodeviewer.gui.plugins.ReplaceStringsOptions;
|
||||
import the.bytecode.club.bytecodeviewer.gui.resourcelist.ResourceListPane;
|
||||
|
@ -52,16 +38,7 @@ import the.bytecode.club.bytecodeviewer.obfuscators.rename.RenameFields;
|
|||
import the.bytecode.club.bytecodeviewer.obfuscators.rename.RenameMethods;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.PluginTemplate;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.AllatoriStringDecrypter;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.ChangeClassFileVersions;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.CodeSequenceDiagram;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.ShowAllStrings;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.ShowMainMethods;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.StackFramesRemover;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.ViewAPKAndroidPermissions;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.ViewManifest;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.ZKMStringDecrypter;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.ZStringArrayDecrypter;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.*;
|
||||
import the.bytecode.club.bytecodeviewer.resources.ExternalResources;
|
||||
import the.bytecode.club.bytecodeviewer.resources.IconResources;
|
||||
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
|
||||
|
@ -74,12 +51,15 @@ import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckB
|
|||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJMenu;
|
||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJMenuItem;
|
||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJRadioButtonMenuItem;
|
||||
import the.bytecode.club.bytecodeviewer.util.DialogUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.KeyEventDispatch;
|
||||
import the.bytecode.club.bytecodeviewer.util.LazyNameUtil;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
import the.bytecode.club.bytecodeviewer.util.WindowClosingAdapter;
|
||||
import the.bytecode.club.bytecodeviewer.util.WindowStateChangeAdapter;
|
||||
import the.bytecode.club.bytecodeviewer.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Configuration.useNewSettingsDialog;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.VERSION;
|
||||
|
@ -451,10 +431,12 @@ public class MainViewerGUI extends JFrame
|
|||
fontSpinner.setPreferredSize(new Dimension(60, 24));
|
||||
fontSpinner.setMinimumSize(new Dimension(60, 24));
|
||||
fontSpinner.setModel(new SpinnerNumberModel(12, 1, null, 1));
|
||||
fontSpinner.addChangeListener(e -> {
|
||||
fontSpinner.addChangeListener(e ->
|
||||
{
|
||||
JSpinner spinner = (JSpinner) e.getSource();
|
||||
Font font = UIManager.getFont("defaultFont");
|
||||
if (font == null) {
|
||||
if (font == null)
|
||||
{
|
||||
font = UIManager.getFont("Label.font");
|
||||
}
|
||||
|
||||
|
@ -473,7 +455,7 @@ public class MainViewerGUI extends JFrame
|
|||
apkConversionGroup.add(apkConversionEnjarify);
|
||||
apkConversionGroup.setSelected(apkConversionDex.getModel(), true);
|
||||
//apkConversionSettingsDialog = new SettingsDialogue(apkConversionSecondaryMenu, new JPanel());
|
||||
apkConversionSettings.addActionListener((e)-> apkConversionSettingsDialog.showDialog());
|
||||
apkConversionSettings.addActionListener((e) -> apkConversionSettingsDialog.showDialog());
|
||||
|
||||
ButtonGroup rstaGroup = new ButtonGroup();
|
||||
for (RSTATheme t : RSTATheme.values())
|
||||
|
@ -497,7 +479,7 @@ public class MainViewerGUI extends JFrame
|
|||
}
|
||||
|
||||
rstaThemeSettingsDialog = new SettingsDialog(rstaTheme, new JPanel());
|
||||
rstaThemeSettings.addActionListener((e)-> rstaThemeSettingsDialog.showDialog());
|
||||
rstaThemeSettings.addActionListener((e) -> rstaThemeSettingsDialog.showDialog());
|
||||
|
||||
ButtonGroup lafGroup = new ButtonGroup();
|
||||
for (LAFTheme theme : LAFTheme.values())
|
||||
|
@ -532,7 +514,7 @@ public class MainViewerGUI extends JFrame
|
|||
}
|
||||
|
||||
lafThemeSettingsDialog = new SettingsDialog(lafTheme, new JPanel());
|
||||
lafThemeSettings.addActionListener((e)-> lafThemeSettingsDialog.showDialog());
|
||||
lafThemeSettings.addActionListener((e) -> lafThemeSettingsDialog.showDialog());
|
||||
|
||||
ButtonGroup languageGroup = new ButtonGroup();
|
||||
for (Language l : Language.values())
|
||||
|
@ -554,7 +536,7 @@ public class MainViewerGUI extends JFrame
|
|||
}
|
||||
|
||||
languageSettingsDialog = new SettingsDialog(language, new JPanel());
|
||||
languageSettings.addActionListener((e)-> languageSettingsDialog.showDialog());
|
||||
languageSettings.addActionListener((e) -> languageSettingsDialog.showDialog());
|
||||
|
||||
visualSettings.add(useNewSettingsDialog ? lafThemeSettings : lafTheme);
|
||||
visualSettings.add(useNewSettingsDialog ? rstaThemeSettings : rstaTheme);
|
||||
|
@ -582,7 +564,7 @@ public class MainViewerGUI extends JFrame
|
|||
procyonSettingsSecondaryMenu.add(retainRedunantCasts);
|
||||
procyonSettingsSecondaryMenu.add(unicodeOutputEnabled);
|
||||
procyonSettingsDialog = new SettingsDialog(procyonSettingsSecondaryMenu, new JPanel());
|
||||
procyonSettings.addActionListener((e)-> procyonSettingsDialog.showDialog());
|
||||
procyonSettings.addActionListener((e) -> procyonSettingsDialog.showDialog());
|
||||
|
||||
//CFR SETTINGS
|
||||
settingsMainMenu.add(useNewSettingsDialog ? cfrSettings : cfrSettingsSecondaryMenu);
|
||||
|
@ -631,7 +613,7 @@ public class MainViewerGUI extends JFrame
|
|||
cfrSettingsSecondaryMenu.add(forceTurningIFs);
|
||||
cfrSettingsSecondaryMenu.add(forLoopAGGCapture);
|
||||
cfrSettingsDialog = new SettingsDialog(cfrSettingsSecondaryMenu, new JPanel());
|
||||
cfrSettings.addActionListener((e)-> cfrSettingsDialog.showDialog());
|
||||
cfrSettings.addActionListener((e) -> cfrSettingsDialog.showDialog());
|
||||
|
||||
//FERNFLOWER SETTINGS
|
||||
settingsMainMenu.add(useNewSettingsDialog ? fernFlowerSettings : fernFlowerSettingsSecondaryMenu);
|
||||
|
@ -655,7 +637,7 @@ public class MainViewerGUI extends JFrame
|
|||
fernFlowerSettingsSecondaryMenu.add(fdi);
|
||||
fernFlowerSettingsSecondaryMenu.add(asc);
|
||||
fernFlowerSettingsDialog = new SettingsDialog(fernFlowerSettingsSecondaryMenu, new JPanel());
|
||||
fernFlowerSettings.addActionListener((e)-> fernFlowerSettingsDialog.showDialog());
|
||||
fernFlowerSettings.addActionListener((e) -> fernFlowerSettingsDialog.showDialog());
|
||||
|
||||
//CFIDE SETTINGS
|
||||
settingsMainMenu.add(useNewSettingsDialog ? bytecodeDecompilerSettings : bytecodeDecompilerSettingsSecondaryMenu);
|
||||
|
@ -663,7 +645,7 @@ public class MainViewerGUI extends JFrame
|
|||
bytecodeDecompilerSettingsSecondaryMenu.add(appendBracketsToLabels);
|
||||
bytecodeDecompilerSettingsSecondaryMenu.add(printLineNumbers);
|
||||
bytecodeDecompilerSettingsDialog = new SettingsDialog(bytecodeDecompilerSettingsSecondaryMenu, new JPanel());
|
||||
bytecodeDecompilerSettings.addActionListener((e)-> bytecodeDecompilerSettingsDialog.showDialog());
|
||||
bytecodeDecompilerSettings.addActionListener((e) -> bytecodeDecompilerSettingsDialog.showDialog());
|
||||
|
||||
deleteForeignOutdatedLibs.addActionListener(arg0 -> showForeignLibraryWarning());
|
||||
forcePureAsciiAsText.addActionListener(arg0 -> SettingsSerializer.saveSettingsAsync());
|
||||
|
@ -672,12 +654,14 @@ public class MainViewerGUI extends JFrame
|
|||
setPython3.addActionListener(arg0 -> ExternalResources.getSingleton().selectPython3());
|
||||
setOptionalLibrary.addActionListener(arg0 -> ExternalResources.getSingleton().selectOptionalLibraryFolder());
|
||||
setJavac.addActionListener(arg0 -> ExternalResources.getSingleton().selectJavac());
|
||||
showFileInTabTitle.addActionListener(arg0 -> {
|
||||
showFileInTabTitle.addActionListener(arg0 ->
|
||||
{
|
||||
Configuration.displayParentInTab = BytecodeViewer.viewer.showFileInTabTitle.isSelected();
|
||||
SettingsSerializer.saveSettingsAsync();
|
||||
BytecodeViewer.refreshAllTabTitles();
|
||||
});
|
||||
simplifyNameInTabTitle.addActionListener(arg0 -> {
|
||||
simplifyNameInTabTitle.addActionListener(arg0 ->
|
||||
{
|
||||
Configuration.simplifiedTabNames = BytecodeViewer.viewer.simplifyNameInTabTitle.isSelected();
|
||||
SettingsSerializer.saveSettingsAsync();
|
||||
BytecodeViewer.refreshAllTabTitles();
|
||||
|
@ -844,7 +828,8 @@ public class MainViewerGUI extends JFrame
|
|||
printLineNumbers.setSelected(false);
|
||||
}
|
||||
|
||||
public void calledAfterLoad() {
|
||||
public void calledAfterLoad()
|
||||
{
|
||||
deleteForeignOutdatedLibs.setSelected(Configuration.deleteForeignLibraries);
|
||||
}
|
||||
|
||||
|
@ -860,7 +845,7 @@ public class MainViewerGUI extends JFrame
|
|||
|
||||
public synchronized void clearBusyStatus()
|
||||
{
|
||||
SwingUtilities.invokeLater(()->
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
int length = waitIcons.size();
|
||||
for (int i = 0; i < length; i++)
|
||||
|
@ -881,7 +866,7 @@ public class MainViewerGUI extends JFrame
|
|||
}
|
||||
else
|
||||
{
|
||||
if(waitIcons.isEmpty())
|
||||
if (waitIcons.isEmpty())
|
||||
return;
|
||||
|
||||
JMenuItem waitIcon = waitIcons.get(0);
|
||||
|
@ -889,7 +874,7 @@ public class MainViewerGUI extends JFrame
|
|||
rootMenu.remove(waitIcon);
|
||||
|
||||
//re-enable the Refresh Button incase it gets stuck
|
||||
if(waitIcons.isEmpty() && !workPane.refreshClass.isEnabled())
|
||||
if (waitIcons.isEmpty() && !workPane.refreshClass.isEnabled())
|
||||
workPane.refreshClass.setEnabled(true);
|
||||
}
|
||||
|
||||
|
@ -913,9 +898,7 @@ public class MainViewerGUI extends JFrame
|
|||
|
||||
public void reloadResources()
|
||||
{
|
||||
MultipleChoiceDialog dialog = new MultipleChoiceDialog(TranslatedStrings.RELOAD_RESOURCES_TITLE.toString(),
|
||||
TranslatedStrings.RELOAD_RESOURCES_CONFIRM.toString(),
|
||||
new String[]{TranslatedStrings.YES.toString(), TranslatedStrings.NO.toString()});
|
||||
MultipleChoiceDialog dialog = new MultipleChoiceDialog(TranslatedStrings.RELOAD_RESOURCES_TITLE.toString(), TranslatedStrings.RELOAD_RESOURCES_CONFIRM.toString(), new String[]{TranslatedStrings.YES.toString(), TranslatedStrings.NO.toString()});
|
||||
|
||||
if (dialog.promptChoice() == 0)
|
||||
{
|
||||
|
@ -925,8 +908,7 @@ public class MainViewerGUI extends JFrame
|
|||
for (ResourceContainer container : BytecodeViewer.resourceContainers.values())
|
||||
{
|
||||
File newFile = new File(container.file.getParent() + fs + container.name);
|
||||
if (!container.file.getAbsolutePath().equals(newFile.getAbsolutePath()) &&
|
||||
(container.file.getAbsolutePath().endsWith(".apk") || container.file.getAbsolutePath().endsWith(".dex"))) //APKs & dex get renamed
|
||||
if (!container.file.getAbsolutePath().equals(newFile.getAbsolutePath()) && (container.file.getAbsolutePath().endsWith(".apk") || container.file.getAbsolutePath().endsWith(".dex"))) //APKs & dex get renamed
|
||||
{
|
||||
container.file.renameTo(newFile);
|
||||
container.file = newFile;
|
||||
|
@ -948,11 +930,9 @@ public class MainViewerGUI extends JFrame
|
|||
|
||||
public void selectFile()
|
||||
{
|
||||
final File file = DialogUtils.fileChooser(TranslatedStrings.SELECT_FILE_TITLE.toString(),
|
||||
TranslatedStrings.SELECT_FILE_DESCRIPTION.toString(),
|
||||
Constants.SUPPORTED_FILE_EXTENSIONS);
|
||||
final File file = DialogUtils.fileChooser(TranslatedStrings.SELECT_FILE_TITLE.toString(), TranslatedStrings.SELECT_FILE_DESCRIPTION.toString(), Constants.SUPPORTED_FILE_EXTENSIONS);
|
||||
|
||||
if(file == null)
|
||||
if (file == null)
|
||||
return;
|
||||
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
|
@ -962,14 +942,9 @@ public class MainViewerGUI extends JFrame
|
|||
|
||||
public void openExternalPlugin()
|
||||
{
|
||||
final File file = DialogUtils.fileChooser(TranslatedStrings.SELECT_EXTERNAL_PLUGIN_TITLE.toString(),
|
||||
TranslatedStrings.SELECT_EXTERNAL_PLUGIN_DESCRIPTION.toString(),
|
||||
Configuration.getLastPluginDirectory(),
|
||||
PluginManager.fileFilter(),
|
||||
Configuration::setLastPluginDirectory,
|
||||
FileChooser.EVERYTHING);
|
||||
final File file = DialogUtils.fileChooser(TranslatedStrings.SELECT_EXTERNAL_PLUGIN_TITLE.toString(), TranslatedStrings.SELECT_EXTERNAL_PLUGIN_DESCRIPTION.toString(), Configuration.getLastPluginDirectory(), PluginManager.fileFilter(), Configuration::setLastPluginDirectory, FileChooser.EVERYTHING);
|
||||
|
||||
if(file == null)
|
||||
if (file == null)
|
||||
return;
|
||||
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
|
@ -980,9 +955,7 @@ public class MainViewerGUI extends JFrame
|
|||
|
||||
public void askBeforeExiting()
|
||||
{
|
||||
MultipleChoiceDialog dialog = new MultipleChoiceDialog(TranslatedStrings.EXIT_TITLE.toString(),
|
||||
TranslatedStrings.EXIT_CONFIRM.toString(),
|
||||
new String[]{TranslatedStrings.YES.toString(), TranslatedStrings.NO.toString()});
|
||||
MultipleChoiceDialog dialog = new MultipleChoiceDialog(TranslatedStrings.EXIT_TITLE.toString(), TranslatedStrings.EXIT_CONFIRM.toString(), new String[]{TranslatedStrings.YES.toString(), TranslatedStrings.NO.toString()});
|
||||
|
||||
if (dialog.promptChoice() == 0)
|
||||
{
|
||||
|
@ -1003,13 +976,13 @@ public class MainViewerGUI extends JFrame
|
|||
{
|
||||
try
|
||||
{
|
||||
for(Component viewerComponent : BytecodeViewer.viewer.workPane.tabs.getComponents())
|
||||
for (Component viewerComponent : BytecodeViewer.viewer.workPane.tabs.getComponents())
|
||||
{
|
||||
if(!(viewerComponent instanceof ResourceViewer))
|
||||
if (!(viewerComponent instanceof ResourceViewer))
|
||||
continue;
|
||||
|
||||
ResourceViewer viewerResource = (ResourceViewer) viewerComponent;
|
||||
if(!(viewerResource instanceof ClassViewer))
|
||||
if (!(viewerResource instanceof ClassViewer))
|
||||
continue;
|
||||
|
||||
ClassViewer viewerClass = (ClassViewer) viewerResource;
|
||||
|
|
|
@ -18,14 +18,14 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.CardLayout;
|
||||
import java.io.IOException;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JScrollPane;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.InitialBootScreen;
|
||||
import the.bytecode.club.bytecodeviewer.resources.IconResources;
|
||||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Configuration.language;
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,17 +18,14 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JRadioButtonMenuItem;
|
||||
import javax.swing.JSeparator;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.WorkspaceRefreshEvent;
|
||||
import the.bytecode.club.bytecodeviewer.translation.TranslatedComponents;
|
||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckBoxMenuItem;
|
||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJRadioButtonMenuItem;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.gui.components.DecompilerViewComponent.DecompilerComponentType.*;
|
||||
|
||||
/**
|
||||
|
@ -53,19 +50,19 @@ public class DecompilerViewComponent
|
|||
this.decompilers = decompilers;
|
||||
this.java = new TranslatedJRadioButtonMenuItem("Java", TranslatedComponents.JAVA);
|
||||
this.bytecode = new TranslatedJRadioButtonMenuItem("Bytecode", TranslatedComponents.BYTECODE);
|
||||
this.editable = new TranslatedJCheckBoxMenuItem( "Editable", TranslatedComponents.EDITABLE);
|
||||
this.editable = new TranslatedJCheckBoxMenuItem("Editable", TranslatedComponents.EDITABLE);
|
||||
|
||||
createMenu();
|
||||
}
|
||||
|
||||
private void createMenu()
|
||||
{
|
||||
if(type == JAVA || type == JAVA_NON_EDITABLE || type == JAVA_AND_BYTECODE)
|
||||
if (type == JAVA || type == JAVA_NON_EDITABLE || type == JAVA_AND_BYTECODE)
|
||||
menu.add(java);
|
||||
if(type == BYTECODE || type == JAVA_AND_BYTECODE || type == BYTECODE_NON_EDITABLE)
|
||||
if (type == BYTECODE || type == JAVA_AND_BYTECODE || type == BYTECODE_NON_EDITABLE)
|
||||
menu.add(bytecode);
|
||||
|
||||
if(type != JAVA_NON_EDITABLE && type != BYTECODE_NON_EDITABLE)
|
||||
if (type != JAVA_NON_EDITABLE && type != BYTECODE_NON_EDITABLE)
|
||||
{
|
||||
menu.add(new JSeparator());
|
||||
menu.add(editable);
|
||||
|
@ -76,9 +73,9 @@ public class DecompilerViewComponent
|
|||
|
||||
public void addToGroup(ButtonGroup group)
|
||||
{
|
||||
if(type == JAVA || type == JAVA_NON_EDITABLE || type == JAVA_AND_BYTECODE)
|
||||
if (type == JAVA || type == JAVA_NON_EDITABLE || type == JAVA_AND_BYTECODE)
|
||||
group.add(java);
|
||||
if(type == BYTECODE || type == JAVA_AND_BYTECODE || type == BYTECODE_NON_EDITABLE)
|
||||
if (type == BYTECODE || type == JAVA_AND_BYTECODE || type == BYTECODE_NON_EDITABLE)
|
||||
group.add(bytecode);
|
||||
}
|
||||
|
||||
|
@ -114,10 +111,6 @@ public class DecompilerViewComponent
|
|||
|
||||
public enum DecompilerComponentType
|
||||
{
|
||||
JAVA,
|
||||
JAVA_NON_EDITABLE,
|
||||
BYTECODE,
|
||||
BYTECODE_NON_EDITABLE,
|
||||
JAVA_AND_BYTECODE
|
||||
JAVA, JAVA_NON_EDITABLE, BYTECODE, BYTECODE_NON_EDITABLE, JAVA_AND_BYTECODE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,16 +18,12 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* The export as Jar UI.
|
||||
*
|
||||
|
|
|
@ -18,27 +18,12 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.HeadlessException;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.UIManager;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
import static javax.swing.JOptionPane.CLOSED_OPTION;
|
||||
import static javax.swing.JOptionPane.DEFAULT_OPTION;
|
||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||
import static javax.swing.JOptionPane.INFORMATION_MESSAGE;
|
||||
import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
|
||||
import static javax.swing.JOptionPane.PLAIN_MESSAGE;
|
||||
import static javax.swing.JOptionPane.QUESTION_MESSAGE;
|
||||
import static javax.swing.JOptionPane.UNINITIALIZED_VALUE;
|
||||
import static javax.swing.JOptionPane.WARNING_MESSAGE;
|
||||
import static javax.swing.JOptionPane.getRootFrame;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
import static javax.swing.JOptionPane.*;
|
||||
|
||||
/**
|
||||
* Extends the JOptionPane
|
||||
|
@ -51,117 +36,90 @@ import static javax.swing.JOptionPane.getRootFrame;
|
|||
|
||||
public class ExtendedJOptionPane
|
||||
{
|
||||
public static void showMessageDialog(Component parentComponent,
|
||||
Object message) throws HeadlessException
|
||||
public static void showMessageDialog(Component parentComponent, Object message) throws HeadlessException
|
||||
{
|
||||
showMessageDialog(parentComponent, message, UIManager.getString(
|
||||
"OptionPane.messageDialogTitle", parentComponent.getLocale()),
|
||||
INFORMATION_MESSAGE);
|
||||
showMessageDialog(parentComponent, message, UIManager.getString("OptionPane.messageDialogTitle", parentComponent.getLocale()), INFORMATION_MESSAGE);
|
||||
}
|
||||
|
||||
public static void showMessageDialog(Component parentComponent,
|
||||
Object message, String title, int messageType)
|
||||
throws HeadlessException
|
||||
public static void showMessageDialog(Component parentComponent, Object message, String title, int messageType) throws HeadlessException
|
||||
{
|
||||
showMessageDialog(parentComponent, message, title, messageType, null);
|
||||
}
|
||||
|
||||
public static void showMessageDialog(Component parentComponent,
|
||||
Object message, String title, int messageType, Icon icon)
|
||||
throws HeadlessException
|
||||
public static void showMessageDialog(Component parentComponent, Object message, String title, int messageType, Icon icon) throws HeadlessException
|
||||
{
|
||||
showOptionDialog(parentComponent, message, title, DEFAULT_OPTION,
|
||||
messageType, icon, null, null);
|
||||
showOptionDialog(parentComponent, message, title, DEFAULT_OPTION, messageType, icon, null, null);
|
||||
}
|
||||
|
||||
public static String showInputDialog(Object message)
|
||||
throws HeadlessException {
|
||||
public static String showInputDialog(Object message) throws HeadlessException
|
||||
{
|
||||
return showInputDialog(null, message);
|
||||
}
|
||||
|
||||
public static String showInputDialog(Object message, Object initialSelectionValue) {
|
||||
public static String showInputDialog(Object message, Object initialSelectionValue)
|
||||
{
|
||||
return showInputDialog(null, message, initialSelectionValue);
|
||||
}
|
||||
|
||||
public static String showInputDialog(Component parentComponent,
|
||||
Object message) throws HeadlessException {
|
||||
return showInputDialog(parentComponent, message, UIManager.getString(
|
||||
"OptionPane.inputDialogTitle", parentComponent.getLocale()), QUESTION_MESSAGE);
|
||||
}
|
||||
|
||||
public static String showInputDialog(Component parentComponent, Object message,
|
||||
Object initialSelectionValue) {
|
||||
return (String)showInputDialog(parentComponent, message,
|
||||
UIManager.getString("OptionPane.inputDialogTitle",
|
||||
parentComponent.getLocale()), QUESTION_MESSAGE, null, null,
|
||||
initialSelectionValue);
|
||||
}
|
||||
|
||||
public static String showInputDialog(Component parentComponent,
|
||||
Object message, String title, int messageType)
|
||||
throws HeadlessException {
|
||||
return (String)showInputDialog(parentComponent, message, title,
|
||||
messageType, null, null, null);
|
||||
}
|
||||
|
||||
public static int showOptionDialog(Component parentComponent,
|
||||
Object message, String title, int optionType, int messageType,
|
||||
Icon icon, Object[] options, Object initialValue)
|
||||
throws HeadlessException
|
||||
public static String showInputDialog(Component parentComponent, Object message) throws HeadlessException
|
||||
{
|
||||
JOptionPane pane = new JOptionPane(message, messageType,
|
||||
optionType, icon,
|
||||
options, initialValue);
|
||||
return showInputDialog(parentComponent, message, UIManager.getString("OptionPane.inputDialogTitle", parentComponent.getLocale()), QUESTION_MESSAGE);
|
||||
}
|
||||
|
||||
public static String showInputDialog(Component parentComponent, Object message, Object initialSelectionValue)
|
||||
{
|
||||
return (String) showInputDialog(parentComponent, message, UIManager.getString("OptionPane.inputDialogTitle", parentComponent.getLocale()), QUESTION_MESSAGE, null, null, initialSelectionValue);
|
||||
}
|
||||
|
||||
public static String showInputDialog(Component parentComponent, Object message, String title, int messageType) throws HeadlessException
|
||||
{
|
||||
return (String) showInputDialog(parentComponent, message, title, messageType, null, null, null);
|
||||
}
|
||||
|
||||
public static int showOptionDialog(Component parentComponent, Object message, String title, int optionType, int messageType, Icon icon, Object[] options, Object initialValue) throws HeadlessException
|
||||
{
|
||||
JOptionPane pane = new JOptionPane(message, messageType, optionType, icon, options, initialValue);
|
||||
|
||||
pane.setInitialValue(initialValue);
|
||||
pane.setComponentOrientation(((parentComponent == null) ?
|
||||
getRootFrame() : parentComponent).getComponentOrientation());
|
||||
pane.setComponentOrientation(((parentComponent == null) ? getRootFrame() : parentComponent).getComponentOrientation());
|
||||
|
||||
int style = styleFromMessageType(messageType);
|
||||
JDialog dialog = createNewJDialog(parentComponent, pane, title, style, (d)->
|
||||
pane.selectInitialValue());
|
||||
JDialog dialog = createNewJDialog(parentComponent, pane, title, style, (d) -> pane.selectInitialValue());
|
||||
|
||||
pane.selectInitialValue();
|
||||
|
||||
Object selectedValue = pane.getValue();
|
||||
|
||||
if(selectedValue == null)
|
||||
if (selectedValue == null)
|
||||
return CLOSED_OPTION;
|
||||
|
||||
if(options == null)
|
||||
if (options == null)
|
||||
{
|
||||
if(selectedValue instanceof Integer)
|
||||
if (selectedValue instanceof Integer)
|
||||
return (Integer) selectedValue;
|
||||
return CLOSED_OPTION;
|
||||
}
|
||||
|
||||
for(int counter = 0, maxCounter = options.length;
|
||||
counter < maxCounter; counter++)
|
||||
for (int counter = 0, maxCounter = options.length; counter < maxCounter; counter++)
|
||||
{
|
||||
if(options[counter].equals(selectedValue))
|
||||
if (options[counter].equals(selectedValue))
|
||||
return counter;
|
||||
}
|
||||
|
||||
return CLOSED_OPTION;
|
||||
}
|
||||
|
||||
public static Object showInputDialog(Component parentComponent,
|
||||
Object message, String title, int messageType, Icon icon,
|
||||
Object[] selectionValues, Object initialSelectionValue)
|
||||
throws HeadlessException {
|
||||
JOptionPane pane = new JOptionPane(message, messageType,
|
||||
OK_CANCEL_OPTION, icon,
|
||||
null, null);
|
||||
public static Object showInputDialog(Component parentComponent, Object message, String title, int messageType, Icon icon, Object[] selectionValues, Object initialSelectionValue) throws HeadlessException
|
||||
{
|
||||
JOptionPane pane = new JOptionPane(message, messageType, OK_CANCEL_OPTION, icon, null, null);
|
||||
|
||||
pane.setWantsInput(true);
|
||||
pane.setSelectionValues(selectionValues);
|
||||
pane.setInitialSelectionValue(initialSelectionValue);
|
||||
pane.setComponentOrientation(((parentComponent == null) ?
|
||||
getRootFrame() : parentComponent).getComponentOrientation());
|
||||
pane.setComponentOrientation(((parentComponent == null) ? getRootFrame() : parentComponent).getComponentOrientation());
|
||||
|
||||
int style = styleFromMessageType(messageType);
|
||||
JDialog dialog = createNewJDialog(parentComponent, pane, title, style, (d)->
|
||||
pane.selectInitialValue());
|
||||
JDialog dialog = createNewJDialog(parentComponent, pane, title, style, (d) -> pane.selectInitialValue());
|
||||
|
||||
pane.selectInitialValue();
|
||||
|
||||
|
@ -173,20 +131,19 @@ public class ExtendedJOptionPane
|
|||
return value;
|
||||
}
|
||||
|
||||
public static void showJPanelDialog(Component parentComponent, JScrollPane panel, int minimumHeight, OnCreate onCreate)
|
||||
throws HeadlessException
|
||||
public static void showJPanelDialog(Component parentComponent, JScrollPane panel, int minimumHeight, OnCreate onCreate) throws HeadlessException
|
||||
{
|
||||
//create a new option pane with a empty text and just 'ok'
|
||||
JOptionPane pane = new JOptionPane("");
|
||||
pane.add(panel, 0);
|
||||
|
||||
JDialog dialog = createNewJDialog(parentComponent, pane, panel.getName(), ERROR_MESSAGE, (d)->
|
||||
JDialog dialog = createNewJDialog(parentComponent, pane, panel.getName(), ERROR_MESSAGE, (d) ->
|
||||
{
|
||||
int newHeight = Math.min(minimumHeight, d.getHeight());
|
||||
d.setMinimumSize(new Dimension(d.getWidth(), newHeight));
|
||||
d.setSize(new Dimension(d.getWidth(), newHeight));
|
||||
|
||||
if(onCreate != null)
|
||||
if (onCreate != null)
|
||||
onCreate.onCreate(d);
|
||||
});
|
||||
}
|
||||
|
@ -194,10 +151,11 @@ public class ExtendedJOptionPane
|
|||
private static JDialog createNewJDialog(Component parentComponent, JOptionPane pane, String title, int style, OnCreate onCreate)
|
||||
{
|
||||
JDialog dialog = pane.createDialog(parentComponent, title);
|
||||
if (JDialog.isDefaultLookAndFeelDecorated()) {
|
||||
boolean supportsWindowDecorations =
|
||||
UIManager.getLookAndFeel().getSupportsWindowDecorations();
|
||||
if (supportsWindowDecorations) {
|
||||
if (JDialog.isDefaultLookAndFeelDecorated())
|
||||
{
|
||||
boolean supportsWindowDecorations = UIManager.getLookAndFeel().getSupportsWindowDecorations();
|
||||
if (supportsWindowDecorations)
|
||||
{
|
||||
dialog.setUndecorated(true);
|
||||
pane.getRootPane().setWindowDecorationStyle(style);
|
||||
}
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
|
@ -44,14 +45,18 @@ public class FileChooser extends JFileChooser
|
|||
Set<String> extensionSet = new HashSet<>(Arrays.asList(extensions));
|
||||
|
||||
setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
|
||||
try {
|
||||
try
|
||||
{
|
||||
setSelectedFile(file);
|
||||
} catch (Exception ignored) { }
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
}
|
||||
|
||||
setDialogTitle(title);
|
||||
setFileHidingEnabled(false);
|
||||
setAcceptAllFileFilterUsed(false);
|
||||
if(!skipFileFilter)
|
||||
if (!skipFileFilter)
|
||||
{
|
||||
addChoosableFileFilter(new FileFilter()
|
||||
{
|
||||
|
@ -61,14 +66,15 @@ public class FileChooser extends JFileChooser
|
|||
if (f.isDirectory())
|
||||
return true;
|
||||
|
||||
if(extensions[0].equals(EVERYTHING))
|
||||
if (extensions[0].equals(EVERYTHING))
|
||||
return true;
|
||||
|
||||
return extensionSet.contains(MiscUtils.extension(f.getAbsolutePath()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -18,20 +18,16 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Scanner;
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.InitialBootScreen;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.BCVDir;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.FAT_JAR;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.enjarifyVersion;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.enjarifyWorkingDirectory;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.krakatauVersion;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.krakatauWorkingDirectory;
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Scanner;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
|
@ -47,7 +43,8 @@ public class HTMLPane extends JEditorPane
|
|||
|
||||
public static HTMLPane fromResource(String resourcePath) throws IOException
|
||||
{
|
||||
try (InputStream is = InitialBootScreen.class.getClassLoader().getResourceAsStream(resourcePath)) {
|
||||
try (InputStream is = InitialBootScreen.class.getClassLoader().getResourceAsStream(resourcePath))
|
||||
{
|
||||
return fromString(convertStreamToString(is));
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +60,7 @@ public class HTMLPane extends JEditorPane
|
|||
text = text.replace("{java}", Configuration.java);
|
||||
text = text.replace("{javac}", Configuration.javac);
|
||||
text = text.replace("{bcvDir}", BCVDir.getAbsolutePath());
|
||||
text = text.replace("{python}", Configuration.python2+" " + (Configuration.python2Extra ? "-2" : ""));
|
||||
text = text.replace("{python}", Configuration.python2 + " " + (Configuration.python2Extra ? "-2" : ""));
|
||||
text = text.replace("{python3}", Configuration.python3 + " " + (Configuration.python3Extra ? "-3" : ""));
|
||||
text = text.replace("{rt}", Configuration.rt);
|
||||
text = text.replace("{lib}", Configuration.library);
|
||||
|
@ -82,8 +79,8 @@ public class HTMLPane extends JEditorPane
|
|||
{
|
||||
if (is == null)
|
||||
return null;
|
||||
try (InputStream stream = is;
|
||||
Scanner s = new Scanner(stream, "UTF-8").useDelimiter("\\A")) {
|
||||
try (InputStream stream = is; Scanner s = new Scanner(stream, "UTF-8").useDelimiter("\\A"))
|
||||
{
|
||||
return s.hasNext() ? s.next() : "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,8 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.Image;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Display an image on a JLabel element
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.io.File;
|
||||
import javax.swing.JFrame;
|
||||
import me.konloch.kontainer.io.DiskWriter;
|
||||
import the.bytecode.club.bytecodeviewer.resources.IconResources;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
||||
|
||||
/**
|
||||
|
@ -63,10 +63,7 @@ public class JFrameConsole extends JFrame
|
|||
*/
|
||||
public void appendText(String t)
|
||||
{
|
||||
setText((textArea.getText().isEmpty()
|
||||
? ""
|
||||
: textArea.getText() + "\r\n"
|
||||
) + t);
|
||||
setText((textArea.getText().isEmpty() ? "" : textArea.getText() + "\r\n") + t);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,14 +126,14 @@ public class JFrameConsole extends JFrame
|
|||
|
||||
//TODO this should also be a setting eventually
|
||||
int max = 500_000;
|
||||
if(len >= max)
|
||||
if (len >= max)
|
||||
{
|
||||
//TODO if two consoles are ran at the same time and exceed the maximum this file will be overwritten
|
||||
|
||||
final File tempFile = new File(tempDirectory, "console_" + consoleID + ".log");
|
||||
|
||||
//TODO this needs to be rewritten, it doesn't work for a plugin that causes multiple exception UIs
|
||||
new Thread(()->
|
||||
new Thread(() ->
|
||||
{
|
||||
//save to disk
|
||||
DiskWriter.replaceFile(tempFile.getAbsolutePath(), s, false);
|
||||
|
@ -146,10 +143,8 @@ public class JFrameConsole extends JFrame
|
|||
int skipped = len - max;
|
||||
String trimmed = s.substring(0, max);
|
||||
|
||||
if(!trimmed.startsWith("WARNING: Skipping"))
|
||||
trimmed = ("WARNING: Skipping " + skipped + " chars, allowing " + max + "\n\r")
|
||||
+ "Full log saved to: " + tempFile.getAbsolutePath() + "\n\r\n\r"
|
||||
+ trimmed;
|
||||
if (!trimmed.startsWith("WARNING: Skipping"))
|
||||
trimmed = ("WARNING: Skipping " + skipped + " chars, allowing " + max + "\n\r") + "Full log saved to: " + tempFile.getAbsolutePath() + "\n\r\n\r" + trimmed;
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import javax.swing.SwingUtilities;
|
||||
import the.bytecode.club.bytecodeviewer.Constants;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.nl;
|
||||
|
||||
/**
|
||||
|
@ -59,7 +60,7 @@ public class JFrameConsolePrintStream extends JFrameConsole
|
|||
{
|
||||
super.setVisible(b);
|
||||
|
||||
if(b && updateThread == null)
|
||||
if (b && updateThread == null)
|
||||
{
|
||||
updateThread = new Thread(() ->
|
||||
{
|
||||
|
@ -67,9 +68,13 @@ public class JFrameConsolePrintStream extends JFrameConsole
|
|||
{
|
||||
update();
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException ignored) { }
|
||||
}
|
||||
catch (InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
lastUpdate = 0;
|
||||
|
@ -99,16 +104,16 @@ public class JFrameConsolePrintStream extends JFrameConsole
|
|||
|
||||
private void update()
|
||||
{
|
||||
if(System.currentTimeMillis()-lastUpdate <= 50)
|
||||
if (System.currentTimeMillis() - lastUpdate <= 50)
|
||||
return;
|
||||
|
||||
lastUpdate = System.currentTimeMillis();
|
||||
|
||||
//update only if required
|
||||
if(textAreaOutputStreamErr.noUpdateRequired() && textAreaOutputStreamOut.noUpdateRequired())
|
||||
if (textAreaOutputStreamErr.noUpdateRequired() && textAreaOutputStreamOut.noUpdateRequired())
|
||||
return;
|
||||
|
||||
SwingUtilities.invokeLater(()->
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
//print output to the pane
|
||||
textAreaOutputStreamOut.update();
|
||||
|
@ -118,7 +123,7 @@ public class JFrameConsolePrintStream extends JFrameConsole
|
|||
|
||||
//reformat the pane
|
||||
String content = getTextArea().getText();
|
||||
if(content.contains("File `"))
|
||||
if (content.contains("File `"))
|
||||
{
|
||||
String[] test = content.split("\r?\n");
|
||||
|
||||
|
|
|
@ -18,13 +18,11 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JTabbedPane;
|
||||
import the.bytecode.club.bytecodeviewer.resources.IconResources;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
* @since 7/14/2021
|
||||
|
|
|
@ -18,11 +18,8 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
|
@ -36,7 +33,7 @@ public class JMenuItemIcon extends JMenuItem
|
|||
|
||||
setIcon(icon);
|
||||
setAlignmentY(0.65f);
|
||||
Dimension size = new Dimension((int) (icon.getIconWidth()*1.4), icon.getIconHeight());
|
||||
Dimension size = new Dimension((int) (icon.getIconWidth() * 1.4), icon.getIconHeight());
|
||||
setSize(size);
|
||||
setPreferredSize(size);
|
||||
setMinimumSize(size);
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.Closeable;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import javax.swing.JTextArea;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
|
@ -54,7 +54,7 @@ public class JTextAreaOutputStream extends OutputStream implements Closeable
|
|||
public void write(int b)
|
||||
{
|
||||
sb.append((char) b);
|
||||
if(og != null)
|
||||
if (og != null)
|
||||
og.write(b);
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,8 @@ public class JTextAreaOutputStream extends OutputStream implements Closeable
|
|||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
public void close()
|
||||
{
|
||||
if (og != null)
|
||||
og.close();
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
|
|
|
@ -18,16 +18,14 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.util.List;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.ListCellRenderer;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.BytecodeViewPanel;
|
||||
import the.bytecode.club.bytecodeviewer.gui.util.BytecodeViewPanelUpdater;
|
||||
import the.bytecode.club.bytecodeviewer.util.MethodParser;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
* @author Waterwolf
|
||||
|
@ -44,16 +42,18 @@ public class MethodsRenderer extends JLabel implements ListCellRenderer<Object>
|
|||
}
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
|
||||
boolean cellHasFocus)
|
||||
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus)
|
||||
{
|
||||
int methodIndex = (Integer) value;
|
||||
MethodParser methods;
|
||||
List<MethodParser> methodParsers = bytecodeViewPanelUpdater.viewer.methods;
|
||||
BytecodeViewPanel bytecodeViewPanel = bytecodeViewPanelUpdater.bytecodeViewPanel;
|
||||
try {
|
||||
try
|
||||
{
|
||||
methods = methodParsers.get(bytecodeViewPanel.decompiler.ordinal());
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException e)
|
||||
{
|
||||
methods = methodParsers.get(bytecodeViewPanel.panelIndex);
|
||||
}
|
||||
MethodParser.Method method = methods.getMethod(methodIndex);
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JOptionPane;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
* @since 6/26/2021
|
||||
|
|
|
@ -122,7 +122,8 @@ public class MyErrorStripe extends JPanel
|
|||
try
|
||||
{
|
||||
line = textArea.getLineOfOffset(range.getStartOffset());
|
||||
} catch (BadLocationException e)
|
||||
}
|
||||
catch (BadLocationException e)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -136,7 +137,8 @@ public class MyErrorStripe extends JPanel
|
|||
m.addMouseListener(listener);
|
||||
markerMap.put(key, m);
|
||||
add(m);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m.containsMarkedOccurrence())
|
||||
m.addNotice(notice);
|
||||
|
@ -214,7 +216,8 @@ public class MyErrorStripe extends JPanel
|
|||
int offset = textArea.getLineOfOffset(line);
|
||||
textArea.setCaretPosition(offset);
|
||||
RSyntaxUtilities.selectAndPossiblyCenter(textArea, new DocumentRange(offset, offset), false);
|
||||
} catch (BadLocationException exception)
|
||||
}
|
||||
catch (BadLocationException exception)
|
||||
{
|
||||
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
|
||||
}
|
||||
|
@ -263,7 +266,8 @@ public class MyErrorStripe extends JPanel
|
|||
try
|
||||
{
|
||||
return textArea.getLineOfOffset(range.getStartOffset()) + 1;
|
||||
} catch (BadLocationException e)
|
||||
}
|
||||
catch (BadLocationException e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -362,7 +366,8 @@ public class MyErrorStripe extends JPanel
|
|||
{
|
||||
DocumentRange range = new DocumentRange(offs, offs + len);
|
||||
RSyntaxUtilities.selectAndPossiblyCenter(textArea, range, true);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
int line = pn.getLine();
|
||||
try
|
||||
|
@ -370,7 +375,8 @@ public class MyErrorStripe extends JPanel
|
|||
offs = textArea.getLineStartOffset(line);
|
||||
textArea.getFoldManager().ensureOffsetNotInClosedFold(offs);
|
||||
textArea.setCaretPosition(offs);
|
||||
} catch (BadLocationException ble) // Never happens
|
||||
}
|
||||
catch (BadLocationException ble) // Never happens
|
||||
{
|
||||
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
|
||||
}
|
||||
|
|
|
@ -18,17 +18,14 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTextField;
|
||||
import the.bytecode.club.bytecodeviewer.api.ASMResourceUtil;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
|
||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.EZInjection;
|
||||
import the.bytecode.club.bytecodeviewer.resources.IconResources;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* The UI for File>Run aka EZ-Injection plugin.
|
||||
*
|
||||
|
@ -114,16 +111,9 @@ public class RunOptions extends JFrame
|
|||
printToCommandLine.setBounds(6, 315, 232, 23);
|
||||
getContentPane().add(printToCommandLine);
|
||||
this.setLocationRelativeTo(null);
|
||||
btnNewButton.addActionListener(arg0 -> {
|
||||
PluginManager.runPlugin(new EZInjection(accessModifiers
|
||||
.isSelected(), injectHooks.isSelected(),
|
||||
debugMethodCalls.isSelected(), invokeMethod
|
||||
.isSelected(),
|
||||
mainMethodFQN.getText(), false, false, debugClasses
|
||||
.getText(), this.socksProxy.getText(), forceProxy
|
||||
.isSelected(),
|
||||
launchReflectionKit.isSelected(), console.isSelected(),
|
||||
printToCommandLine.isSelected()));
|
||||
btnNewButton.addActionListener(arg0 ->
|
||||
{
|
||||
PluginManager.runPlugin(new EZInjection(accessModifiers.isSelected(), injectHooks.isSelected(), debugMethodCalls.isSelected(), invokeMethod.isSelected(), mainMethodFQN.getText(), false, false, debugClasses.getText(), this.socksProxy.getText(), forceProxy.isSelected(), launchReflectionKit.isSelected(), console.isSelected(), printToCommandLine.isSelected()));
|
||||
dispose();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -18,18 +18,6 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Font;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.GlobalHotKeys;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.listeners.PressKeyListener;
|
||||
|
@ -39,6 +27,12 @@ import the.bytecode.club.bytecodeviewer.translation.TranslatedComponents;
|
|||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckBox;
|
||||
import the.bytecode.club.bytecodeviewer.util.JTextAreaUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
|
||||
/**
|
||||
* Searching on a JTextArea using swing highlighting
|
||||
*
|
||||
|
@ -93,7 +87,8 @@ public class SearchableJTextArea extends JTextArea
|
|||
//set number-bar font
|
||||
setFont(newFont);
|
||||
|
||||
SwingUtilities.invokeLater(()-> {
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
//attach CTRL + Mouse Wheel Zoom
|
||||
attachCtrlMouseWheelZoom();
|
||||
|
||||
|
@ -115,11 +110,10 @@ public class SearchableJTextArea extends JTextArea
|
|||
public void attachCtrlMouseWheelZoom()
|
||||
{
|
||||
//get the existing scroll event
|
||||
MouseWheelListener ogListener = scrollPane.getMouseWheelListeners().length > 0 ?
|
||||
scrollPane.getMouseWheelListeners()[0] : null;
|
||||
MouseWheelListener ogListener = scrollPane.getMouseWheelListeners().length > 0 ? scrollPane.getMouseWheelListeners()[0] : null;
|
||||
|
||||
//remove the existing event
|
||||
if(ogListener != null)
|
||||
if (ogListener != null)
|
||||
scrollPane.removeMouseWheelListener(ogListener);
|
||||
|
||||
//add a new event
|
||||
|
@ -140,7 +134,7 @@ public class SearchableJTextArea extends JTextArea
|
|||
|
||||
e.consume();
|
||||
}
|
||||
else if(ogListener != null)
|
||||
else if (ogListener != null)
|
||||
{
|
||||
ogListener.mouseWheelMoved(e);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,8 @@ public class SearchableRSyntaxTextArea extends RSyntaxTextArea
|
|||
scrollPane.getHorizontalScrollBar().setForeground(blackScrollForeground);
|
||||
scrollPane.getVerticalScrollBar().setBackground(blackScrollBackground);
|
||||
scrollPane.getVerticalScrollBar().setForeground(blackScrollForeground);
|
||||
} else if (Configuration.lafTheme.isDark())
|
||||
}
|
||||
else if (Configuration.lafTheme.isDark())
|
||||
{
|
||||
//this fixes the white border on the jScrollBar panes
|
||||
scrollPane.getHorizontalScrollBar().setBackground(darkScrollBackground);
|
||||
|
@ -108,7 +109,8 @@ public class SearchableRSyntaxTextArea extends RSyntaxTextArea
|
|||
//set number-bar font
|
||||
setFont(newFont);
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
//attach CTRL + Mouse Wheel Zoom
|
||||
attachCtrlMouseWheelZoom();
|
||||
|
||||
|
@ -130,8 +132,10 @@ public class SearchableRSyntaxTextArea extends RSyntaxTextArea
|
|||
|
||||
public void attachCtrlMouseWheelZoom()
|
||||
{
|
||||
scrollPane.addMouseWheelListener(e -> {
|
||||
if (getText().isEmpty()) return;
|
||||
scrollPane.addMouseWheelListener(e ->
|
||||
{
|
||||
if (getText().isEmpty())
|
||||
return;
|
||||
if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0)
|
||||
{
|
||||
Font font = getFont();
|
||||
|
@ -176,7 +180,8 @@ public class SearchableRSyntaxTextArea extends RSyntaxTextArea
|
|||
int end = getLineEndOffset(line);
|
||||
return getText(start, end - start).trim();
|
||||
}
|
||||
} catch (BadLocationException ignored)
|
||||
}
|
||||
catch (BadLocationException ignored)
|
||||
{
|
||||
}
|
||||
return "";
|
||||
|
|
|
@ -18,16 +18,10 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import java.awt.Component;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.Configuration.useNewSettingsDialog;
|
||||
|
||||
|
@ -51,13 +45,13 @@ public class SettingsDialog extends JScrollPane
|
|||
this.menu = menu;
|
||||
this.display = display;
|
||||
|
||||
if(!useNewSettingsDialog)
|
||||
if (!useNewSettingsDialog)
|
||||
return;
|
||||
|
||||
List<JMenuItem> options = new ArrayList<>();
|
||||
for(Component child : menu.getMenuComponents())
|
||||
for (Component child : menu.getMenuComponents())
|
||||
{
|
||||
if(!(child instanceof JMenuItem))
|
||||
if (!(child instanceof JMenuItem))
|
||||
continue;
|
||||
|
||||
JMenuItem menuItem = (JMenuItem) child;
|
||||
|
@ -89,14 +83,14 @@ public class SettingsDialog extends JScrollPane
|
|||
private void buildPanel()
|
||||
{
|
||||
display.setLayout(new BoxLayout(display, BoxLayout.Y_AXIS));
|
||||
for(JMenuItem menuItem : options)
|
||||
for (JMenuItem menuItem : options)
|
||||
display.add(menuItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
if(menu == null)
|
||||
if (menu == null)
|
||||
return "ERROR: Dialog missing menu";
|
||||
|
||||
return menu.getText();
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import com.github.weisj.darklaf.iconset.AllIcons;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JInternalFrame;
|
||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||
import the.bytecode.club.bytecodeviewer.gui.theme.LAFTheme;
|
||||
import the.bytecode.club.bytecodeviewer.resources.IconResources;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* Used to represent all the panes inside of Bytecode Viewer.
|
||||
*
|
||||
|
@ -42,7 +42,8 @@ public abstract class VisibleComponent extends JInternalFrame
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateUI() {
|
||||
public void updateUI()
|
||||
{
|
||||
if (Configuration.lafTheme != LAFTheme.SYSTEM)
|
||||
setBorder(BorderFactory.createEmptyBorder());
|
||||
else
|
||||
|
@ -52,12 +53,15 @@ public abstract class VisibleComponent extends JInternalFrame
|
|||
|
||||
public void setDefaultIcon()
|
||||
{
|
||||
try {
|
||||
if(Configuration.showDarkLAFComponentIcons)
|
||||
try
|
||||
{
|
||||
if (Configuration.showDarkLAFComponentIcons)
|
||||
setFrameIcon(AllIcons.Window.Frame.get(16, 16));
|
||||
else
|
||||
setFrameIcon(IconResources.jarIcon);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,15 +18,11 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.components;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import com.github.weisj.darklaf.components.RotatableIconAnimator;
|
||||
import com.github.weisj.darklaf.components.loading.LoadingIndicator;
|
||||
import com.github.weisj.darklaf.iconset.AllIcons;
|
||||
import com.github.weisj.darklaf.properties.icons.RotatableIcon;
|
||||
import the.bytecode.club.bytecodeviewer.resources.IconResources;
|
||||
|
||||
import java.awt.event.*;
|
||||
import java.awt.event.HierarchyEvent;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
|
@ -40,7 +36,8 @@ public class WaitBusyIcon extends JMenuItemIcon
|
|||
{
|
||||
super(new RotatableIcon(IconResources.busyIcon));
|
||||
animator = new RotatableIconAnimator(8, (RotatableIcon) getIcon(), this);
|
||||
addHierarchyListener(e -> {
|
||||
addHierarchyListener(e ->
|
||||
{
|
||||
if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0)
|
||||
{
|
||||
if (getParent() == null)
|
||||
|
|
|
@ -42,7 +42,8 @@ public class GoToAction extends AbstractAction
|
|||
int line = textArea.getCaretLineNumber() + 1;
|
||||
int column = textArea.getCaretOffsetFromLineStart();
|
||||
|
||||
container.fieldMembers.values().forEach(fields -> fields.forEach(field -> {
|
||||
container.fieldMembers.values().forEach(fields -> fields.forEach(field ->
|
||||
{
|
||||
if (field.line == line && field.columnStart - 1 <= column && field.columnEnd >= column)
|
||||
{
|
||||
Element root = textArea.getDocument().getDefaultRootElement();
|
||||
|
@ -59,7 +60,8 @@ public class GoToAction extends AbstractAction
|
|||
}
|
||||
}));
|
||||
|
||||
container.methodParameterMembers.values().forEach(parameters -> parameters.forEach(parameter -> {
|
||||
container.methodParameterMembers.values().forEach(parameters -> parameters.forEach(parameter ->
|
||||
{
|
||||
if (parameter.line == line && parameter.columnStart - 1 <= column && parameter.columnEnd >= column)
|
||||
{
|
||||
Element root = textArea.getDocument().getDefaultRootElement();
|
||||
|
@ -67,10 +69,12 @@ public class GoToAction extends AbstractAction
|
|||
{
|
||||
int startOffset = root.getElement(parameter.line - 1).getStartOffset() + (parameter.columnStart - 1);
|
||||
textArea.setCaretPosition(startOffset);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
String method = parameter.method;
|
||||
parameters.stream().filter(classParameterLocation -> classParameterLocation.method.equals(method)).forEach(classParameterLocation -> {
|
||||
parameters.stream().filter(classParameterLocation -> classParameterLocation.method.equals(method)).forEach(classParameterLocation ->
|
||||
{
|
||||
if (classParameterLocation.decRef.equalsIgnoreCase("declaration"))
|
||||
{
|
||||
int startOffset = root.getElement(classParameterLocation.line - 1).getStartOffset() + (classParameterLocation.columnStart - 1);
|
||||
|
@ -81,7 +85,8 @@ public class GoToAction extends AbstractAction
|
|||
}
|
||||
}));
|
||||
|
||||
container.methodLocalMembers.values().forEach(localMembers -> localMembers.forEach(localMember -> {
|
||||
container.methodLocalMembers.values().forEach(localMembers -> localMembers.forEach(localMember ->
|
||||
{
|
||||
if (localMember.line == line && localMember.columnStart - 1 <= column && localMember.columnEnd >= column)
|
||||
{
|
||||
Element root = textArea.getDocument().getDefaultRootElement();
|
||||
|
@ -89,10 +94,12 @@ public class GoToAction extends AbstractAction
|
|||
{
|
||||
int startOffset = root.getElement(localMember.line - 1).getStartOffset() + (localMember.columnStart - 1);
|
||||
textArea.setCaretPosition(startOffset);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
String method = localMember.method;
|
||||
localMembers.stream().filter(classLocalVariableLocation -> classLocalVariableLocation.method.equals(method)).forEach(classLocalVariableLocation -> {
|
||||
localMembers.stream().filter(classLocalVariableLocation -> classLocalVariableLocation.method.equals(method)).forEach(classLocalVariableLocation ->
|
||||
{
|
||||
if (classLocalVariableLocation.decRef.equalsIgnoreCase("declaration"))
|
||||
{
|
||||
int startOffset = root.getElement(classLocalVariableLocation.line - 1).getStartOffset() + (classLocalVariableLocation.columnStart - 1);
|
||||
|
@ -103,7 +110,8 @@ public class GoToAction extends AbstractAction
|
|||
}
|
||||
}));
|
||||
|
||||
container.methodMembers.values().forEach(methods -> methods.forEach(method -> {
|
||||
container.methodMembers.values().forEach(methods -> methods.forEach(method ->
|
||||
{
|
||||
if (method.line == line && method.columnStart - 1 <= column && method.columnEnd >= column)
|
||||
{
|
||||
Element root = textArea.getDocument().getDefaultRootElement();
|
||||
|
@ -111,9 +119,11 @@ public class GoToAction extends AbstractAction
|
|||
{
|
||||
int startOffset = root.getElement(method.line - 1).getStartOffset() + (method.columnStart - 1);
|
||||
textArea.setCaretPosition(startOffset);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
methods.stream().filter(classMethodLocation -> classMethodLocation.owner.equals(method.owner)).forEach(classMethodLocation ->
|
||||
{
|
||||
methods.stream().filter(classMethodLocation -> classMethodLocation.owner.equals(method.owner)).forEach(classMethodLocation -> {
|
||||
if (classMethodLocation.decRef.equalsIgnoreCase("declaration"))
|
||||
{
|
||||
int startOffset = root.getElement(classMethodLocation.line - 1).getStartOffset() + (classMethodLocation.columnStart - 1);
|
||||
|
@ -127,7 +137,8 @@ public class GoToAction extends AbstractAction
|
|||
}
|
||||
}));
|
||||
|
||||
container.classReferences.values().forEach(classes -> classes.forEach(clazz -> {
|
||||
container.classReferences.values().forEach(classes -> classes.forEach(clazz ->
|
||||
{
|
||||
String name;
|
||||
if (clazz.line == line && clazz.columnStart - 1 <= column && clazz.columnEnd - 1 >= column)
|
||||
{
|
||||
|
@ -137,9 +148,11 @@ public class GoToAction extends AbstractAction
|
|||
{
|
||||
int startOffset = root.getElement(clazz.line - 1).getStartOffset() + (clazz.columnStart - 1);
|
||||
textArea.setCaretPosition(startOffset);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
classes.stream().filter(classReferenceLocation -> classReferenceLocation.owner.equals(name)).forEach(classReferenceLocation ->
|
||||
{
|
||||
classes.stream().filter(classReferenceLocation -> classReferenceLocation.owner.equals(name)).forEach(classReferenceLocation -> {
|
||||
if (classReferenceLocation.type.equals("declaration"))
|
||||
{
|
||||
int startOffset = root.getElement(classReferenceLocation.line - 1).getStartOffset() + (classReferenceLocation.columnStart - 1);
|
||||
|
@ -170,14 +183,16 @@ public class GoToAction extends AbstractAction
|
|||
ClassViewer activeResource = (ClassViewer) BytecodeViewer.viewer.workPane.getActiveResource();
|
||||
HashMap<String, ClassFileContainer> classFiles = BytecodeViewer.viewer.workPane.classFiles;
|
||||
return wait(classFiles, activeResource);
|
||||
} else if (method)
|
||||
}
|
||||
else if (method)
|
||||
{
|
||||
ClassMethodLocation classMethodLocation = container.getMethodLocationsFor(lexeme).get(0);
|
||||
ClassReferenceLocation classReferenceLocation = null;
|
||||
try
|
||||
{
|
||||
classReferenceLocation = container.getClassReferenceLocationsFor(classMethodLocation.owner).get(0);
|
||||
} catch (Exception ignored)
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -196,7 +211,8 @@ public class GoToAction extends AbstractAction
|
|||
HashMap<String, ClassFileContainer> classFiles = BytecodeViewer.viewer.workPane.classFiles;
|
||||
return wait(classFiles, activeResource);
|
||||
}
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
ClassReferenceLocation classReferenceLocation = container.getClassReferenceLocationsFor(lexeme).get(0);
|
||||
String packagePath = classReferenceLocation.packagePath;
|
||||
|
@ -218,7 +234,8 @@ public class GoToAction extends AbstractAction
|
|||
|
||||
private void open(RSyntaxTextArea textArea, boolean isClass, boolean isField, boolean isMethod)
|
||||
{
|
||||
Thread thread = new Thread(() -> {
|
||||
Thread thread = new Thread(() ->
|
||||
{
|
||||
Token token = textArea.modelToToken(textArea.getCaretPosition());
|
||||
token = TokenUtil.getToken(textArea, token);
|
||||
String lexeme = token.getLexeme();
|
||||
|
@ -229,10 +246,12 @@ public class GoToAction extends AbstractAction
|
|||
if (classFileContainer == null)
|
||||
return;
|
||||
|
||||
classFileContainer.classReferences.forEach((className, classReference) -> {
|
||||
classFileContainer.classReferences.forEach((className, classReference) ->
|
||||
{
|
||||
if (className.equals(lexeme))
|
||||
{
|
||||
classReference.forEach(classReferenceLocation -> {
|
||||
classReference.forEach(classReferenceLocation ->
|
||||
{
|
||||
if (classReferenceLocation.type.equals("declaration"))
|
||||
{
|
||||
moveCursor(classReferenceLocation.line, classReferenceLocation.columnStart);
|
||||
|
@ -240,16 +259,19 @@ public class GoToAction extends AbstractAction
|
|||
});
|
||||
}
|
||||
});
|
||||
} else if (isField)
|
||||
}
|
||||
else if (isField)
|
||||
{
|
||||
classFileContainer = openClass(lexeme, true, false);
|
||||
if (classFileContainer == null)
|
||||
return;
|
||||
|
||||
classFileContainer.fieldMembers.forEach((fieldName, fields) -> {
|
||||
classFileContainer.fieldMembers.forEach((fieldName, fields) ->
|
||||
{
|
||||
if (fieldName.equals(lexeme))
|
||||
{
|
||||
fields.forEach(classFieldLocation -> {
|
||||
fields.forEach(classFieldLocation ->
|
||||
{
|
||||
if (classFieldLocation.type.equals("declaration"))
|
||||
{
|
||||
moveCursor(classFieldLocation.line, classFieldLocation.columnStart);
|
||||
|
@ -257,16 +279,19 @@ public class GoToAction extends AbstractAction
|
|||
});
|
||||
}
|
||||
});
|
||||
} else if (isMethod)
|
||||
}
|
||||
else if (isMethod)
|
||||
{
|
||||
classFileContainer = openClass(lexeme, false, true);
|
||||
if (classFileContainer == null)
|
||||
return;
|
||||
|
||||
classFileContainer.methodMembers.forEach((methodName, methods) -> {
|
||||
classFileContainer.methodMembers.forEach((methodName, methods) ->
|
||||
{
|
||||
if (methodName.equals(lexeme))
|
||||
{
|
||||
methods.forEach(method -> {
|
||||
methods.forEach(method ->
|
||||
{
|
||||
if (method.decRef.equalsIgnoreCase("declaration"))
|
||||
{
|
||||
moveCursor(method.line, method.columnStart);
|
||||
|
@ -285,22 +310,26 @@ public class GoToAction extends AbstractAction
|
|||
try
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
Thread.getAllStackTraces().forEach((name, stackTrace) -> {
|
||||
Thread.getAllStackTraces().forEach((name, stackTrace) ->
|
||||
{
|
||||
if (name.getName().equals("Pane Update"))
|
||||
{
|
||||
try
|
||||
{
|
||||
name.join();
|
||||
} catch (InterruptedException e)
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e)
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
} finally
|
||||
}
|
||||
finally
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ package the.bytecode.club.bytecodeviewer.gui.components.listeners;
|
|||
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
|
@ -36,7 +35,8 @@ public class MouseClickedListener extends MouseAdapter
|
|||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
mouseClickedEvent.mouseClicked(e);
|
||||
super.mouseClicked(e);
|
||||
}
|
||||
|
|
|
@ -29,10 +29,15 @@ public class PressKeyListener implements KeyListener
|
|||
{
|
||||
private final KeyPressedEvent keyPressedEvent;
|
||||
|
||||
public PressKeyListener(KeyPressedEvent keyPressedEvent) {this.keyPressedEvent = keyPressedEvent;}
|
||||
public PressKeyListener(KeyPressedEvent keyPressedEvent)
|
||||
{
|
||||
this.keyPressedEvent = keyPressedEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) { }
|
||||
public void keyTyped(KeyEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e)
|
||||
|
@ -41,7 +46,9 @@ public class PressKeyListener implements KeyListener
|
|||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {}
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
public interface KeyPressedEvent
|
||||
{
|
||||
|
|
|
@ -29,13 +29,20 @@ public class ReleaseKeyListener implements KeyListener
|
|||
{
|
||||
private final KeyReleasedEvent keyReleasedEvent;
|
||||
|
||||
public ReleaseKeyListener(KeyReleasedEvent keyReleasedEvent) {this.keyReleasedEvent = keyReleasedEvent;}
|
||||
public ReleaseKeyListener(KeyReleasedEvent keyReleasedEvent)
|
||||
{
|
||||
this.keyReleasedEvent = keyReleasedEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) { }
|
||||
public void keyTyped(KeyEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) { }
|
||||
public void keyPressed(KeyEvent e)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e)
|
||||
|
|
|
@ -18,11 +18,12 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.contextmenu;
|
||||
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.tree.TreePath;
|
||||
import the.bytecode.club.bytecodeviewer.gui.resourcelist.ResourceTree;
|
||||
import the.bytecode.club.bytecodeviewer.searching.LDCSearchTreeNodeResult;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
* @since 7/26/2021
|
||||
|
|
|
@ -18,21 +18,16 @@
|
|||
|
||||
package the.bytecode.club.bytecodeviewer.gui.contextmenu;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
import the.bytecode.club.bytecodeviewer.gui.contextmenu.resourcelist.Collapse;
|
||||
import the.bytecode.club.bytecodeviewer.gui.contextmenu.resourcelist.Expand;
|
||||
import the.bytecode.club.bytecodeviewer.gui.contextmenu.resourcelist.New;
|
||||
import the.bytecode.club.bytecodeviewer.gui.contextmenu.resourcelist.Open;
|
||||
import the.bytecode.club.bytecodeviewer.gui.contextmenu.resourcelist.QuickEdit;
|
||||
import the.bytecode.club.bytecodeviewer.gui.contextmenu.resourcelist.QuickOpen;
|
||||
import the.bytecode.club.bytecodeviewer.gui.contextmenu.resourcelist.Delete;
|
||||
import the.bytecode.club.bytecodeviewer.gui.contextmenu.resourcelist.*;
|
||||
import the.bytecode.club.bytecodeviewer.gui.resourcelist.ResourceTree;
|
||||
import the.bytecode.club.bytecodeviewer.searching.LDCSearchTreeNodeResult;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
* @since 7/26/2021
|
||||
|
@ -73,35 +68,35 @@ public class ContextMenu
|
|||
boolean isResourceSelected = false;
|
||||
|
||||
//TODO this is hacky - there is probably a better way to do this
|
||||
if(!searchBoxPane)
|
||||
if (!searchBoxPane)
|
||||
{
|
||||
tree.setSelectionPath(selPath);
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
|
||||
isResourceSelected = !node.children().hasMoreElements();
|
||||
}
|
||||
|
||||
for(ContextMenuItem item : SINGLETON.contextMenuItems)
|
||||
for (ContextMenuItem item : SINGLETON.contextMenuItems)
|
||||
{
|
||||
switch(item.getMenuType())
|
||||
switch (item.getMenuType())
|
||||
{
|
||||
case CONTAINER:
|
||||
if(!isContainerSelected)
|
||||
if (!isContainerSelected)
|
||||
continue;
|
||||
break;
|
||||
case RESOURCE:
|
||||
if(!isResourceSelected || isContainerSelected)
|
||||
if (!isResourceSelected || isContainerSelected)
|
||||
continue;
|
||||
break;
|
||||
case DIRECTORY:
|
||||
if(isResourceSelected || searchBoxPane)
|
||||
if (isResourceSelected || searchBoxPane)
|
||||
continue;
|
||||
break;
|
||||
case RESOURCE_LIST:
|
||||
if(searchBoxPane)
|
||||
if (searchBoxPane)
|
||||
continue;
|
||||
break;
|
||||
case SEARCH_BOX_RESULT:
|
||||
if(!searchBoxPane)
|
||||
if (!searchBoxPane)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user