Merge branch 'Konloch:master' into master
This commit is contained in:
commit
2b70b564e7
|
@ -29,6 +29,8 @@ import the.bytecode.club.bytecodeviewer.bootloader.Boot;
|
|||
import the.bytecode.club.bytecodeviewer.bootloader.BootState;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.InstallFatJar;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.UpdateCheck;
|
||||
import the.bytecode.club.bytecodeviewer.cli.CLIAction;
|
||||
import the.bytecode.club.bytecodeviewer.cli.CommandLineInput;
|
||||
import the.bytecode.club.bytecodeviewer.gui.MainViewerGUI;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.ExtendedJOptionPane;
|
||||
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialog;
|
||||
|
@ -202,8 +204,8 @@ public class BytecodeViewer
|
|||
MiscUtils.setLanguage(MiscUtils.guessLanguage());
|
||||
|
||||
//handle CLI
|
||||
int isCLI = CommandLineInput.parseCommandLine(args);
|
||||
if (isCLI == CommandLineInput.STOP)
|
||||
CLIAction isCLI = CommandLineInput.parseCommandLine(args);
|
||||
if (isCLI == CLIAction.STOP)
|
||||
return;
|
||||
|
||||
//load with shaded libraries
|
||||
|
@ -214,11 +216,11 @@ public class BytecodeViewer
|
|||
else //load through bootloader
|
||||
{
|
||||
BOOT_CHECK.start();
|
||||
Boot.boot(args, isCLI != CommandLineInput.GUI);
|
||||
Boot.boot(args, isCLI != CLIAction.GUI);
|
||||
}
|
||||
|
||||
//CLI arguments say spawn the GUI
|
||||
if (isCLI == CommandLineInput.GUI)
|
||||
if (isCLI == CLIAction.GUI)
|
||||
{
|
||||
BytecodeViewer.boot(false);
|
||||
Configuration.bootState = BootState.GUI_SHOWING;
|
||||
|
|
|
@ -68,7 +68,7 @@ public class Constants
|
|||
|
||||
public static final String FS = System.getProperty("file.separator");
|
||||
public static final String NL = System.getProperty("line.separator");
|
||||
public static final String[] SUPPORTED_FILE_EXTENSIONS = ResourceType.supportedBCVExtensionMap.keySet().toArray(new String[0]);
|
||||
public static final String[] SUPPORTED_FILE_EXTENSIONS = ResourceType.SUPPORTED_BCV_EXTENSION_MAP.keySet().toArray(new String[0]);
|
||||
public static final int ASM_VERSION = Opcodes.ASM9;
|
||||
|
||||
public static final File BCVDir = resolveBCVRoot();
|
||||
|
|
|
@ -106,6 +106,7 @@ public class GlobalHotKeys
|
|||
JFileChooser fc = new FileChooser(Configuration.getLastSaveDirectory(), "Select Zip Export", "Zip Archives", "zip");
|
||||
|
||||
int returnVal = fc.showSaveDialog(BytecodeViewer.viewer);
|
||||
|
||||
if (returnVal == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
Configuration.setLastSaveDirectory(fc.getSelectedFile());
|
||||
|
@ -124,6 +125,7 @@ public class GlobalHotKeys
|
|||
jarExport.start();
|
||||
}
|
||||
}, "Resource Export");
|
||||
|
||||
resourceExport.start();
|
||||
}
|
||||
|
||||
|
|
|
@ -127,32 +127,38 @@ public class Settings
|
|||
{
|
||||
//build recent files
|
||||
BytecodeViewer.viewer.recentFilesSecondaryMenu.removeAll();
|
||||
|
||||
for (String s : recentFiles)
|
||||
{
|
||||
if (!s.isEmpty())
|
||||
{
|
||||
JMenuItem m = new JMenuItem(s);
|
||||
|
||||
m.addActionListener(e ->
|
||||
{
|
||||
JMenuItem m12 = (JMenuItem) e.getSource();
|
||||
BytecodeViewer.openFiles(new File[]{new File(m12.getText())}, true);
|
||||
});
|
||||
|
||||
BytecodeViewer.viewer.recentFilesSecondaryMenu.add(m);
|
||||
}
|
||||
}
|
||||
|
||||
//build recent plugins
|
||||
BytecodeViewer.viewer.recentPluginsSecondaryMenu.removeAll();
|
||||
|
||||
for (String s : recentPlugins)
|
||||
{
|
||||
if (!s.isEmpty())
|
||||
{
|
||||
JMenuItem m = new JMenuItem(s);
|
||||
|
||||
m.addActionListener(e ->
|
||||
{
|
||||
JMenuItem m1 = (JMenuItem) e.getSource();
|
||||
BytecodeViewer.startPlugin(new File(m1.getText()));
|
||||
});
|
||||
|
||||
BytecodeViewer.viewer.recentPluginsSecondaryMenu.add(m);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -338,11 +338,13 @@ public class SettingsSerializer
|
|||
BytecodeViewer.viewer.refreshOnChange.setSelected(asBoolean(84));
|
||||
|
||||
boolean bool = Boolean.parseBoolean(asString(85));
|
||||
|
||||
if (bool)
|
||||
{
|
||||
BytecodeViewer.viewer.setExtendedState(JFrame.MAXIMIZED_BOTH);
|
||||
BytecodeViewer.viewer.isMaximized = true;
|
||||
}
|
||||
|
||||
//86 is deprecated
|
||||
//87 is deprecated
|
||||
Configuration.lastOpenDirectory = asString(88);
|
||||
|
@ -388,6 +390,7 @@ public class SettingsSerializer
|
|||
//line 130 is used for preload
|
||||
if (Configuration.language != Language.ENGLISH)
|
||||
Configuration.language.setLanguageTranslations(); //load language translations
|
||||
|
||||
Settings.hasSetLanguageAsSystemLanguage = true;
|
||||
|
||||
BytecodeViewer.viewer.viewPane1.setPaneEditable(asBoolean(131));
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package the.bytecode.club.bytecodeviewer.cli;
|
||||
|
||||
/**
|
||||
* @author Konloch
|
||||
* @since 9/27/2024
|
||||
*/
|
||||
public enum CLIAction
|
||||
{
|
||||
STOP,
|
||||
GUI,
|
||||
CLI
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
package the.bytecode.club.bytecodeviewer;
|
||||
package the.bytecode.club.bytecodeviewer.cli;
|
||||
|
||||
import me.konloch.kontainer.io.DiskWriter;
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
|
@ -25,6 +25,9 @@ import org.apache.commons.cli.DefaultParser;
|
|||
import org.apache.commons.cli.Options;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||
import the.bytecode.club.bytecodeviewer.Constants;
|
||||
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
||||
import the.bytecode.club.bytecodeviewer.translation.Language;
|
||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||
|
@ -32,6 +35,7 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
import static the.bytecode.club.bytecodeviewer.cli.CLIAction.*;
|
||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||
|
||||
/**
|
||||
|
@ -46,11 +50,6 @@ public class CommandLineInput
|
|||
private static final Options OPTIONS = new Options();
|
||||
private static final CommandLineParser PARSER = new DefaultParser();
|
||||
|
||||
/*BECAUSE WHO DOESN'T LOVE MAGIC NUMBERS*/
|
||||
public static final int STOP = -1;
|
||||
public static final int GUI = 0;
|
||||
public static final int CLI = 1;
|
||||
|
||||
static
|
||||
{
|
||||
OPTIONS.addOption("help", false, "prints the help menu.");
|
||||
|
@ -92,7 +91,7 @@ public class CommandLineInput
|
|||
return false;
|
||||
}
|
||||
|
||||
public static int parseCommandLine(String[] args)
|
||||
public static CLIAction parseCommandLine(String[] args)
|
||||
{
|
||||
if (!containsCommand(args))
|
||||
return GUI;
|
|
@ -43,20 +43,23 @@ public class JavaCompiler extends InternalCompiler
|
|||
@Override
|
||||
public byte[] compile(String contents, String fullyQualifiedName)
|
||||
{
|
||||
String fileStart = TEMP_DIRECTORY + FS + "temp" + MiscUtils.randomString(12) + FS;
|
||||
String fileStart2 = TEMP_DIRECTORY + FS + "temp" + MiscUtils.randomString(12) + FS;
|
||||
File java = new File(fileStart + FS + fullyQualifiedName + ".java");
|
||||
File clazz = new File(fileStart2 + FS + fullyQualifiedName + ".class");
|
||||
File cp = new File(TEMP_DIRECTORY + FS + "cpath_" + MiscUtils.randomString(12) + ".jar");
|
||||
File tempD = new File(fileStart + FS + fullyQualifiedName.substring(0, fullyQualifiedName.length() -
|
||||
final String fileStart = TEMP_DIRECTORY + FS + "temp" + MiscUtils.randomString(12) + FS;
|
||||
final String fileStart2 = TEMP_DIRECTORY + FS + "temp" + MiscUtils.randomString(12) + FS;
|
||||
|
||||
final File javaFile = new File(fileStart + FS + fullyQualifiedName + ".java");
|
||||
final File classFile = new File(fileStart2 + FS + fullyQualifiedName + ".class");
|
||||
final File classPath = new File(TEMP_DIRECTORY + FS + "cpath_" + MiscUtils.randomString(12) + ".jar");
|
||||
final File tempDirectory = new File(fileStart + FS + fullyQualifiedName.substring(0, fullyQualifiedName.length() -
|
||||
fullyQualifiedName.split("/")[fullyQualifiedName.split("/").length - 1].length()));
|
||||
|
||||
tempD.mkdirs();
|
||||
//create the temp directories
|
||||
tempDirectory.mkdirs();
|
||||
new File(fileStart2).mkdirs();
|
||||
|
||||
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)");
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -66,8 +69,11 @@ public class JavaCompiler extends InternalCompiler
|
|||
return null;
|
||||
}
|
||||
|
||||
DiskWriter.replaceFile(java.getAbsolutePath(), contents, false);
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), cp.getAbsolutePath());
|
||||
//write the file we're assembling to disk
|
||||
DiskWriter.replaceFile(javaFile.getAbsolutePath(), contents, false);
|
||||
|
||||
//write the entire temporary classpath to disk
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), classPath.getAbsolutePath());
|
||||
|
||||
boolean cont = true;
|
||||
try
|
||||
|
@ -77,10 +83,10 @@ public class JavaCompiler extends InternalCompiler
|
|||
|
||||
if (Configuration.library.isEmpty())
|
||||
pb = new ProcessBuilder(Configuration.javac, "-d", fileStart2,
|
||||
"-classpath", cp.getAbsolutePath(), java.getAbsolutePath());
|
||||
"-classpath", classPath.getAbsolutePath(), javaFile.getAbsolutePath());
|
||||
else
|
||||
pb = new ProcessBuilder(Configuration.javac, "-d", fileStart2,
|
||||
"-classpath", cp.getAbsolutePath() + System.getProperty("path.separator") + Configuration.library, java.getAbsolutePath());
|
||||
"-classpath", classPath.getAbsolutePath() + System.getProperty("path.separator") + Configuration.library, javaFile.getAbsolutePath());
|
||||
|
||||
Process process = pb.start();
|
||||
BytecodeViewer.createdProcesses.add(process);
|
||||
|
@ -111,6 +117,7 @@ public class JavaCompiler extends InternalCompiler
|
|||
}
|
||||
|
||||
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))
|
||||
|
@ -123,7 +130,7 @@ public class JavaCompiler extends InternalCompiler
|
|||
log.append(NL).append(NL).append(TranslatedStrings.EXIT_VALUE_IS).append(" ").append(exitValue);
|
||||
System.out.println(log);
|
||||
|
||||
if (!clazz.exists())
|
||||
if (!classFile.exists())
|
||||
throw new Exception(log.toString());
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -132,12 +139,12 @@ public class JavaCompiler extends InternalCompiler
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
cp.delete();
|
||||
classPath.delete();
|
||||
|
||||
if (cont)
|
||||
try
|
||||
{
|
||||
return org.apache.commons.io.FileUtils.readFileToByteArray(clazz);
|
||||
return org.apache.commons.io.FileUtils.readFileToByteArray(classFile);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
|
|
@ -51,16 +51,19 @@ public class KrakatauAssembler extends InternalCompiler
|
|||
if (!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
return null;
|
||||
|
||||
File tempD = new File(Constants.TEMP_DIRECTORY + FS + MiscUtils.randomString(32) + FS);
|
||||
tempD.mkdir();
|
||||
|
||||
File tempJ = new File(tempD.getAbsolutePath() + FS + fullyQualifiedName + ".j");
|
||||
DiskWriter.replaceFile(tempJ.getAbsolutePath(), contents, true);
|
||||
|
||||
final File tempDirectory = new File(Constants.TEMP_DIRECTORY + FS + MiscUtils.randomString(32) + FS);
|
||||
tempDirectory.mkdir();
|
||||
|
||||
final File tempDirectory1 = new File(Constants.TEMP_DIRECTORY + FS + MiscUtils.randomString(32) + FS);
|
||||
final File tempDirectory2 = new File(Constants.TEMP_DIRECTORY + FS + MiscUtils.randomString(32) + FS);
|
||||
final File javaFile = new File(tempDirectory1.getAbsolutePath() + FS + fullyQualifiedName + ".j");
|
||||
final File tempJar = new File(Constants.TEMP_DIRECTORY + FS + "temp" + MiscUtils.randomString(32) + ".jar");
|
||||
|
||||
//create the temp directories
|
||||
tempDirectory1.mkdir();
|
||||
tempDirectory2.mkdir();
|
||||
|
||||
//write the file we're assembling to disk
|
||||
DiskWriter.replaceFile(javaFile.getAbsolutePath(), contents, true);
|
||||
|
||||
//write the entire temporary classpath to disk
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), tempJar.getAbsolutePath());
|
||||
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
@ -72,7 +75,7 @@ public class KrakatauAssembler extends InternalCompiler
|
|||
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()));
|
||||
krakatauWorkingDirectory + FS + "assemble.py", "-out", tempDirectory2.getAbsolutePath(), javaFile.getAbsolutePath()));
|
||||
|
||||
Process process = pb.start();
|
||||
BytecodeViewer.createdProcesses.add(process);
|
||||
|
@ -101,10 +104,15 @@ 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")));
|
||||
tempDirectory.delete();
|
||||
//read the assembled bytes from disk
|
||||
byte[] assembledBytes = FileUtils.readFileToByteArray(Objects.requireNonNull(ExternalResources.getSingleton().findFile(tempDirectory2, ".class")));
|
||||
|
||||
//cleanup
|
||||
tempDirectory2.delete();
|
||||
tempJar.delete();
|
||||
return b;
|
||||
|
||||
//return the assembled file
|
||||
return assembledBytes;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -44,19 +44,21 @@ public class SmaliAssembler extends InternalCompiler
|
|||
@Override
|
||||
public byte[] compile(String contents, String fullyQualifiedName)
|
||||
{
|
||||
String fileStart = TEMP_DIRECTORY + FS + "temp";
|
||||
int fileNumber = MiscUtils.getClassNumber(fileStart, ".dex");
|
||||
|
||||
final String fileStart = TEMP_DIRECTORY + FS + "temp";
|
||||
final int fileNumber = MiscUtils.getClassNumber(fileStart, ".dex");
|
||||
final File tempSmaliFolder = new File(fileStart + fileNumber + "-smalifolder" + FS);
|
||||
tempSmaliFolder.mkdir();
|
||||
|
||||
File tempSmali = new File(tempSmaliFolder.getAbsolutePath() + FS + fileNumber + ".smali");
|
||||
File tempDex = new File("./out.dex");
|
||||
File tempJar = new File(fileStart + fileNumber + ".jar");
|
||||
File tempJarFolder = new File(fileStart + fileNumber + "-jar" + FS);
|
||||
final File tempSmali = new File(tempSmaliFolder.getAbsolutePath() + FS + fileNumber + ".smali");
|
||||
final File tempDex = new File("./out.dex");
|
||||
final File tempJar = new File(fileStart + fileNumber + ".jar");
|
||||
final File tempJarFolder = new File(fileStart + fileNumber + "-jar" + FS);
|
||||
|
||||
//create the temp directory
|
||||
tempSmaliFolder.mkdir();
|
||||
|
||||
try
|
||||
{
|
||||
//write the file we're assembling to disk
|
||||
DiskWriter.replaceFile(tempSmali.getAbsolutePath(), contents, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -107,6 +109,7 @@ public class SmaliAssembler extends InternalCompiler
|
|||
|
||||
System.out.println("Saved as: " + outputClass.getAbsolutePath());
|
||||
|
||||
//return the assembled file
|
||||
return FileUtils.readFileToByteArray(outputClass);
|
||||
}
|
||||
catch (java.lang.NullPointerException ignored)
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.objectweb.asm.tree.ClassNode;
|
|||
*/
|
||||
public abstract class InternalDecompiler
|
||||
{
|
||||
public abstract String decompileClassNode(ClassNode cn, byte[] b);
|
||||
public abstract String decompileClassNode(ClassNode cn, byte[] bytes);
|
||||
|
||||
public abstract void decompileToZip(String sourceJar, String zipName);
|
||||
}
|
||||
|
|
|
@ -37,11 +37,14 @@ public class FieldNodeDecompiler
|
|||
{
|
||||
String s = getAccessString(f.access);
|
||||
sb.append(s);
|
||||
|
||||
if (s.length() > 0)
|
||||
sb.append(" ");
|
||||
|
||||
sb.append(Type.getType(f.desc).getClassName());
|
||||
sb.append(" ");
|
||||
sb.append(f.name);
|
||||
|
||||
if (f.value != null)
|
||||
{
|
||||
sb.append(" = ");
|
||||
|
@ -59,13 +62,16 @@ public class FieldNodeDecompiler
|
|||
sb.append(")");
|
||||
}
|
||||
}
|
||||
|
||||
sb.append(";");
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
private static String getAccessString(int access)
|
||||
{
|
||||
List<String> tokens = new ArrayList<>();
|
||||
|
||||
if ((access & Opcodes.ACC_PUBLIC) != 0)
|
||||
tokens.add("public");
|
||||
if ((access & Opcodes.ACC_PRIVATE) != 0)
|
||||
|
@ -84,6 +90,7 @@ public class FieldNodeDecompiler
|
|||
tokens.add("volatile");
|
||||
if (tokens.size() == 0)
|
||||
return "";
|
||||
|
||||
// hackery delimeters
|
||||
StringBuilder sb = new StringBuilder(tokens.get(0));
|
||||
for (int i = 1; i < tokens.size(); i++)
|
||||
|
@ -91,6 +98,7 @@ public class FieldNodeDecompiler
|
|||
sb.append(" ");
|
||||
sb.append(tokens.get(i));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,8 +61,6 @@ public class InstructionPrinter implements Opcodes
|
|||
mNode = m;
|
||||
labels = new HashMap<>();
|
||||
precalculateLabelIndexes(m);
|
||||
// matchedInsns = new ArrayList<AbstractInsnNode>(); // ingnored because
|
||||
// match = false
|
||||
match = false;
|
||||
}
|
||||
|
||||
|
@ -125,97 +123,39 @@ public class InstructionPrinter implements Opcodes
|
|||
{
|
||||
String line = "";
|
||||
if (ain instanceof VarInsnNode)
|
||||
{
|
||||
line = printVarInsnNode((VarInsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof IntInsnNode)
|
||||
{
|
||||
line = printIntInsnNode((IntInsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof FieldInsnNode)
|
||||
{
|
||||
line = printFieldInsnNode((FieldInsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof MethodInsnNode)
|
||||
{
|
||||
line = printMethodInsnNode((MethodInsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof LdcInsnNode)
|
||||
{
|
||||
line = printLdcInsnNode((LdcInsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof InsnNode)
|
||||
{
|
||||
line = printInsnNode((InsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof JumpInsnNode)
|
||||
{
|
||||
line = printJumpInsnNode((JumpInsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof LineNumberNode)
|
||||
{
|
||||
line = printLineNumberNode((LineNumberNode) ain);
|
||||
}
|
||||
else if (ain instanceof LabelNode)
|
||||
{
|
||||
if (firstLabel && BytecodeViewer.viewer.appendBracketsToLabels.isSelected())
|
||||
info.add("}");
|
||||
|
||||
LabelNode label = (LabelNode) ain;
|
||||
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);
|
||||
}
|
||||
line = printLabelNode((LabelNode) ain);
|
||||
|
||||
if (BytecodeViewer.viewer.appendBracketsToLabels.isSelected())
|
||||
{
|
||||
if (!firstLabel)
|
||||
firstLabel = true;
|
||||
line += " {";
|
||||
}
|
||||
}
|
||||
else if (ain instanceof TypeInsnNode)
|
||||
{
|
||||
line = printTypeInsnNode((TypeInsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof FrameNode)
|
||||
{
|
||||
line = printFrameNode((FrameNode) ain);
|
||||
}
|
||||
else if (ain instanceof IincInsnNode)
|
||||
{
|
||||
line = printIincInsnNode((IincInsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof TableSwitchInsnNode)
|
||||
{
|
||||
line = printTableSwitchInsnNode((TableSwitchInsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof LookupSwitchInsnNode)
|
||||
{
|
||||
line = printLookupSwitchInsnNode((LookupSwitchInsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof InvokeDynamicInsnNode)
|
||||
{
|
||||
line = printInvokeDynamicInsNode((InvokeDynamicInsnNode) ain);
|
||||
}
|
||||
else if (ain instanceof MultiANewArrayInsnNode)
|
||||
{
|
||||
line = printMultiANewArrayInsNode((MultiANewArrayInsnNode) ain);
|
||||
}
|
||||
else
|
||||
{
|
||||
line += "UNADDED OPCODE: " + nameOpcode(ain.getOpcode()) + " " + ain;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
@ -312,11 +252,44 @@ public class InstructionPrinter implements Opcodes
|
|||
return "";
|
||||
}
|
||||
|
||||
protected String printLabelNode(LabelNode label)
|
||||
protected String printOnlyLabelNode(LabelNode label)
|
||||
{
|
||||
return "L" + resolveLabel(label);
|
||||
}
|
||||
|
||||
protected String printLabelNode(LabelNode label)
|
||||
{
|
||||
if (firstLabel && BytecodeViewer.viewer.appendBracketsToLabels.isSelected())
|
||||
info.add("}");
|
||||
|
||||
String line = "";
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
line = printOnlyLabelNode(label);
|
||||
|
||||
if (BytecodeViewer.viewer.appendBracketsToLabels.isSelected())
|
||||
{
|
||||
if (!firstLabel)
|
||||
firstLabel = true;
|
||||
line += " {";
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
protected String printTypeInsnNode(TypeInsnNode tin)
|
||||
{
|
||||
try
|
||||
|
@ -403,6 +376,7 @@ public class InstructionPrinter implements Opcodes
|
|||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(nameFrameType(frame.type)).append(" ");
|
||||
|
||||
sb.append("(Locals");
|
||||
if (frame.local != null && !frame.local.isEmpty())
|
||||
{
|
||||
|
@ -490,15 +464,13 @@ public class InstructionPrinter implements Opcodes
|
|||
protected int resolveLabel(LabelNode label)
|
||||
{
|
||||
if (labels.containsKey(label))
|
||||
{
|
||||
return labels.get(label);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*int newLabelIndex = labels.size() + 1;
|
||||
//NOTE: Should NEVER enter this state, but if it ever does, here's the fall-back solution
|
||||
int newLabelIndex = labels.size() + 1;
|
||||
labels.put(label, newLabelIndex);
|
||||
return newLabelIndex;*/
|
||||
throw new IllegalStateException("LabelNode index not found. (Label not in InsnList?)");
|
||||
return newLabelIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ public class InstructionSearcher implements Opcodes
|
|||
|
||||
protected InsnList insns;
|
||||
protected InstructionPattern pattern;
|
||||
|
||||
protected List<AbstractInsnNode[]> matches;
|
||||
|
||||
public InstructionSearcher(InsnList insns, int[] opcodes)
|
||||
|
@ -62,6 +61,7 @@ public class InstructionSearcher implements Opcodes
|
|||
{
|
||||
if (ain instanceof LineNumberNode || ain instanceof FrameNode)
|
||||
continue;
|
||||
|
||||
if (pattern.accept(ain))
|
||||
{
|
||||
matches.add(pattern.getLastMatch());
|
||||
|
|
|
@ -40,14 +40,17 @@ public class MethodNodeDecompiler
|
|||
public static PrefixedStringBuilder decompile(PrefixedStringBuilder sb, MethodNode m, ClassNode cn)
|
||||
{
|
||||
String className;
|
||||
|
||||
if (cn.name.contains("/"))
|
||||
className = cn.name.substring(cn.name.lastIndexOf("/") + 1);
|
||||
else
|
||||
className = cn.name;
|
||||
|
||||
String s = getAccessString(m.access);
|
||||
|
||||
sb.append(" ");
|
||||
sb.append(s);
|
||||
|
||||
if (s.length() > 0)
|
||||
sb.append(" ");
|
||||
|
||||
|
@ -73,7 +76,6 @@ public class MethodNodeDecompiler
|
|||
for (int i = 0; i < argTypes.length; i++)
|
||||
{
|
||||
final Type type = argTypes[i];
|
||||
|
||||
final TypeAndName tan = new TypeAndName();
|
||||
final String argName = "arg" + i;
|
||||
|
||||
|
@ -89,10 +91,12 @@ public class MethodNodeDecompiler
|
|||
}
|
||||
|
||||
int amountOfThrows = m.exceptions.size();
|
||||
|
||||
if (amountOfThrows > 0)
|
||||
{
|
||||
sb.append(" throws ");
|
||||
sb.append(m.exceptions.get(0));// exceptions is list<string>
|
||||
|
||||
for (int i = 1; i < amountOfThrows; i++)
|
||||
{
|
||||
sb.append(", ");
|
||||
|
@ -109,7 +113,6 @@ public class MethodNodeDecompiler
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
sb.append(" {");
|
||||
|
||||
if (BytecodeViewer.viewer.debugHelpers.isSelected())
|
||||
|
@ -161,10 +164,12 @@ public class MethodNodeDecompiler
|
|||
sb.append(" handled by L");
|
||||
sb.append(insnPrinter.resolveLabel(o.handler));
|
||||
sb.append(": ");
|
||||
|
||||
if (o.type != null)
|
||||
sb.append(o.type);
|
||||
else
|
||||
sb.append("Type is null.");
|
||||
|
||||
sb.append(NL);
|
||||
}
|
||||
|
||||
|
@ -174,8 +179,10 @@ public class MethodNodeDecompiler
|
|||
sb.append(insn);
|
||||
sb.append(NL);
|
||||
}
|
||||
|
||||
sb.append(" }" + NL);
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
|
@ -194,6 +201,7 @@ public class MethodNodeDecompiler
|
|||
sb.append(">");
|
||||
sb.append(NL);
|
||||
}
|
||||
|
||||
sb.append(NL);
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +211,8 @@ public class MethodNodeDecompiler
|
|||
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);
|
||||
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)
|
||||
{
|
||||
|
@ -212,6 +221,7 @@ public class MethodNodeDecompiler
|
|||
sb.append("desc = ");
|
||||
sb.append(an.desc);
|
||||
sb.append(" , values = ");
|
||||
|
||||
if (an.values != null)
|
||||
{
|
||||
sb.append(Arrays.toString(an.values.toArray()));
|
||||
|
@ -220,10 +230,13 @@ public class MethodNodeDecompiler
|
|||
{
|
||||
sb.append("[]");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
if (o == null)
|
||||
return "";
|
||||
|
||||
return o.toString();
|
||||
}
|
||||
|
||||
|
@ -258,6 +271,7 @@ public class MethodNodeDecompiler
|
|||
tokens.add("varargs");
|
||||
if (tokens.isEmpty())
|
||||
return "";
|
||||
|
||||
// hackery delimeters
|
||||
StringBuilder sb = new StringBuilder(tokens.get(0));
|
||||
for (int i = 1; i < tokens.size(); i++)
|
||||
|
@ -265,6 +279,7 @@ public class MethodNodeDecompiler
|
|||
sb.append(" ");
|
||||
sb.append(tokens.get(i));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,15 +36,11 @@ public class PrefixedStringBuilder
|
|||
public PrefixedStringBuilder append(String s)
|
||||
{
|
||||
sb.append(s);
|
||||
if (s.contains("\n") && (prefix != null) && (prefix.length() > 0))// insert
|
||||
// the
|
||||
// prefix
|
||||
// at
|
||||
// every
|
||||
// new
|
||||
// line,
|
||||
// overridable
|
||||
|
||||
// insert the prefix at every new line, overridable
|
||||
if (s.contains("\n") && (prefix != null) && (prefix.length() > 0))
|
||||
sb.append(prefix);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ import java.io.StringWriter;
|
|||
public class ASMTextifierDisassembler extends InternalDecompiler
|
||||
{
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
public String decompileClassNode(ClassNode cn, byte[] bytes)
|
||||
{
|
||||
StringWriter writer = new StringWriter();
|
||||
cn.accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(writer)));
|
||||
|
|
|
@ -34,7 +34,7 @@ import java.io.StringWriter;
|
|||
public class ASMifierGenerator extends InternalDecompiler
|
||||
{
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
public String decompileClassNode(ClassNode cn, byte[] bytes)
|
||||
{
|
||||
StringWriter writer = new StringWriter();
|
||||
cn.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(writer)));
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.ArrayList;
|
|||
public class BytecodeDisassembler extends InternalDecompiler
|
||||
{
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
public String decompileClassNode(ClassNode cn, byte[] bytes)
|
||||
{
|
||||
return ClassNodeDecompiler.decompile(new PrefixedStringBuilder(), new ArrayList<>(), cn).toString();
|
||||
}
|
||||
|
|
|
@ -59,9 +59,9 @@ 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[] bytes)
|
||||
{
|
||||
return decompile(cn, cn.name, content);
|
||||
return decompile(cn, cn.name, bytes);
|
||||
}
|
||||
|
||||
private String decompile(ClassNode cn, String name, byte[] content)
|
||||
|
@ -93,7 +93,10 @@ public class CFRDecompiler extends InternalDecompiler
|
|||
@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))
|
||||
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];
|
||||
|
||||
|
@ -105,6 +108,7 @@ public class CFRDecompiler extends InternalDecompiler
|
|||
if (entry.getName().endsWith(CLASS_SUFFIX))
|
||||
{
|
||||
JarEntry etn = new JarEntry(entry.getName().replace(CLASS_SUFFIX, ".java"));
|
||||
|
||||
if (history.add(etn))
|
||||
{
|
||||
out.putNextEntry(etn);
|
||||
|
@ -203,6 +207,7 @@ public class CFRDecompiler extends InternalDecompiler
|
|||
options.put("recovertypehints", String.valueOf(BytecodeViewer.viewer.recoveryTypehInts.isSelected()));
|
||||
options.put("forcereturningifs", String.valueOf(BytecodeViewer.viewer.forceTurningIFs.isSelected()));
|
||||
options.put("forloopaggcapture", String.valueOf(BytecodeViewer.viewer.forLoopAGGCapture.isSelected()));
|
||||
|
||||
return new OptionsImpl(options);
|
||||
}
|
||||
|
||||
|
@ -226,11 +231,15 @@ public class CFRDecompiler extends InternalDecompiler
|
|||
{
|
||||
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);
|
||||
|
||||
return Pair.make(data, classFilePath);
|
||||
}
|
||||
|
||||
|
@ -259,6 +268,7 @@ public class CFRDecompiler extends InternalDecompiler
|
|||
{
|
||||
return x -> dumpDecompiled.accept((SinkReturns.Decompiled) x);
|
||||
}
|
||||
|
||||
return ignore ->
|
||||
{
|
||||
};
|
||||
|
|
|
@ -65,7 +65,7 @@ public class FernFlowerDecompiler extends InternalDecompiler
|
|||
}
|
||||
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
public String decompileClassNode(ClassNode cn, byte[] bytes)
|
||||
{
|
||||
String start = TEMP_DIRECTORY + FS + MiscUtils.getUniqueName("", ".class");
|
||||
|
||||
|
@ -74,7 +74,7 @@ public class FernFlowerDecompiler extends InternalDecompiler
|
|||
String exception = "";
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass))
|
||||
{
|
||||
fos.write(b);
|
||||
fos.write(bytes);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
@ -154,7 +154,26 @@ public class FernFlowerDecompiler extends InternalDecompiler
|
|||
|
||||
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};
|
||||
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)
|
||||
|
|
|
@ -42,10 +42,8 @@ import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.JAD
|
|||
*/
|
||||
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[] bytes)
|
||||
{
|
||||
String fileStart = TEMP_DIRECTORY + FS;
|
||||
|
||||
|
@ -54,23 +52,23 @@ public class JADXDecompiler extends InternalDecompiler
|
|||
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass))
|
||||
{
|
||||
fos.write(b);
|
||||
fos.write(bytes);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
|
||||
File fuckery = new File(fuckery(fileStart));
|
||||
fuckery.mkdirs();
|
||||
File freeDirectory = new File(findUnusedFile(fileStart));
|
||||
freeDirectory.mkdirs();
|
||||
|
||||
try
|
||||
{
|
||||
JadxArgs args = new JadxArgs();
|
||||
args.setInputFile(tempClass);
|
||||
args.setOutDir(fuckery);
|
||||
args.setOutDirSrc(fuckery);
|
||||
args.setOutDirRes(fuckery);
|
||||
args.setOutDir(freeDirectory);
|
||||
args.setOutDirSrc(freeDirectory);
|
||||
args.setOutDirRes(freeDirectory);
|
||||
|
||||
JadxDecompiler jadx = new JadxDecompiler(args);
|
||||
jadx.load();
|
||||
|
@ -86,8 +84,8 @@ public class JADXDecompiler extends InternalDecompiler
|
|||
|
||||
tempClass.delete();
|
||||
|
||||
if (fuckery.exists())
|
||||
return findFile(MiscUtils.listFiles(fuckery));
|
||||
if (freeDirectory.exists())
|
||||
return findFile(MiscUtils.listFiles(freeDirectory));
|
||||
|
||||
if (exception.isEmpty())
|
||||
exception = "Decompiled source file not found!";
|
||||
|
@ -95,29 +93,29 @@ public class JADXDecompiler extends InternalDecompiler
|
|||
return JADX + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + NL + NL + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR + NL + NL + exception;
|
||||
}
|
||||
|
||||
//TODO remove
|
||||
public String fuckery(String start)
|
||||
public String findUnusedFile(String start)
|
||||
{
|
||||
int failSafe = 0;
|
||||
while (failSafe++ <= 42069)
|
||||
long index = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
File f = new File(start + r.nextInt(Integer.MAX_VALUE));
|
||||
File f = new File(start + index);
|
||||
|
||||
if (!f.exists())
|
||||
return f.toString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String findFile(File[] fA)
|
||||
public String findFile(File[] fileArray)
|
||||
{
|
||||
for (File f : fA)
|
||||
for (File f : fileArray)
|
||||
{
|
||||
if (f.isDirectory())
|
||||
return findFile(MiscUtils.listFiles(f));
|
||||
else
|
||||
{
|
||||
String s;
|
||||
|
||||
try
|
||||
{
|
||||
s = DiskReader.loadAsString(f.getAbsolutePath());
|
||||
|
@ -131,6 +129,7 @@ public class JADXDecompiler extends InternalDecompiler
|
|||
|
||||
return JADX + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + NL + NL + TranslatedStrings.SUGGESTED_FIX_DECOMPILER_ERROR + NL + NL + exception;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
@ -141,5 +140,6 @@ public class JADXDecompiler extends InternalDecompiler
|
|||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,9 +50,10 @@ public class JDGUIDecompiler extends InternalDecompiler
|
|||
{
|
||||
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
public String decompileClassNode(ClassNode cn, byte[] bytes)
|
||||
{
|
||||
String exception;
|
||||
|
||||
try
|
||||
{
|
||||
final File tempDirectory = new File(Constants.TEMP_DIRECTORY + FS + MiscUtils.randomString(32) + FS);
|
||||
|
@ -75,14 +76,13 @@ public class JDGUIDecompiler extends InternalDecompiler
|
|||
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass))
|
||||
{
|
||||
fos.write(b);
|
||||
fos.write(bytes);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
BytecodeViewer.handleException(e);
|
||||
}
|
||||
|
||||
|
||||
String pathToClass = tempClass.getAbsolutePath().replace('/', File.separatorChar).replace('\\', File.separatorChar);
|
||||
String directoryPath = JDGUIClassFileUtil.ExtractDirectoryPath(pathToClass);
|
||||
String internalPath = JDGUIClassFileUtil.ExtractInternalPath(directoryPath, pathToClass);
|
||||
|
@ -104,8 +104,6 @@ public class JDGUIDecompiler extends InternalDecompiler
|
|||
|
||||
DirectoryLoader loader = new DirectoryLoader(new File(directoryPath));
|
||||
|
||||
//PrintStream ps = new PrintStream("test.html");
|
||||
//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))
|
||||
|
@ -130,5 +128,6 @@ public class JDGUIDecompiler extends InternalDecompiler
|
|||
@Override
|
||||
public void decompileToZip(String sourceJar, String zipName)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,20 +49,21 @@ import static the.bytecode.club.bytecodeviewer.api.ExceptionUI.SEND_STACKTRACE_T
|
|||
public class JavapDisassembler extends InternalDecompiler
|
||||
{
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
public String decompileClassNode(ClassNode cn, byte[] bytes)
|
||||
{
|
||||
if (!ExternalResources.getSingleton().hasJavaToolsSet())
|
||||
return "Set Java Tools Path!";
|
||||
|
||||
return synchronizedDecompilation(cn, b);
|
||||
return synchronizedDecompilation(cn, bytes);
|
||||
}
|
||||
|
||||
private synchronized String synchronizedDecompilation(ClassNode cn, byte[] b)
|
||||
{
|
||||
final File tempDirectory = new File(Constants.TEMP_DIRECTORY + FS + MiscUtils.randomString(32) + FS);
|
||||
tempDirectory.mkdir();
|
||||
final File tempClass = new File(Constants.TEMP_DIRECTORY + FS + "temp" + MiscUtils.randomString(32) + ".class");
|
||||
|
||||
tempDirectory.mkdir();
|
||||
|
||||
DiskWriter.replaceFileBytes(tempClass.getAbsolutePath(), b, false);
|
||||
|
||||
JFrameConsolePrintStream sysOutBuffer = null;
|
||||
|
|
|
@ -64,12 +64,14 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
return ";" + Arrays.stream(files).filter(File::isFile).map(File::getAbsolutePath).collect(Collectors.joining(";"));
|
||||
}
|
||||
|
||||
public String decompileClassNode(File krakatauTempJar, File krakatauTempDir, ClassNode cn)
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] bytes)
|
||||
{
|
||||
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);
|
||||
|
@ -82,74 +84,23 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
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;
|
||||
final File tempDirectory = new File(Constants.TEMP_DIRECTORY + FS + MiscUtils.randomString(32) + FS);
|
||||
final File tempJar = new File(Constants.TEMP_DIRECTORY + FS + "temp" + MiscUtils.randomString(32) + ".jar");
|
||||
|
||||
try
|
||||
{
|
||||
String[] pythonCommands = new String[]{Configuration.python2};
|
||||
if (Configuration.python2Extra)
|
||||
pythonCommands = ArrayUtils.addAll(pythonCommands, "-2");
|
||||
tempDirectory.mkdir();
|
||||
|
||||
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"));
|
||||
JarUtils.saveAsJarClassesOnly(BytecodeViewer.getLoadedClasses(), tempJar.getAbsolutePath());
|
||||
|
||||
Process process = pb.start();
|
||||
BytecodeViewer.createdProcesses.add(process);
|
||||
|
||||
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))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
log.append(NL).append(line);
|
||||
}
|
||||
return decompileClassNode(tempJar, tempDirectory, cn);
|
||||
}
|
||||
|
||||
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))
|
||||
public String decompileClassNode(File tempJar, File tempDir, ClassNode cn)
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
log.append(NL).append(line);
|
||||
}
|
||||
}
|
||||
|
||||
int exitValue = process.waitFor();
|
||||
log.append(NL).append(NL).append(TranslatedStrings.EXIT_VALUE_IS).append(" ").append(exitValue);
|
||||
s = log.toString();
|
||||
|
||||
//if the motherfucker failed this'll fail, aka wont set.
|
||||
s = DiskReader.loadAsString(krakatauTempDir.getAbsolutePath() + FS + cn.name + ".java");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
s += NL + ExceptionUI.SEND_STACKTRACE_TO_NL + sw;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
{
|
||||
//TODO look into transforming through krakatau as a zip rather than direct classfile
|
||||
|
||||
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);
|
||||
|
@ -158,17 +109,11 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
|
||||
if (Configuration.rt.isEmpty())
|
||||
{
|
||||
BytecodeViewer.showMessage("You need to set RT.jar!");
|
||||
return "Set your paths";
|
||||
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;
|
||||
|
||||
final File tempDirectory = new File(Constants.TEMP_DIRECTORY + FS + MiscUtils.randomString(32) + FS);
|
||||
tempDirectory.mkdir();
|
||||
final File tempJar = new File(Constants.TEMP_DIRECTORY + FS + "temp" + MiscUtils.randomString(32) + ".jar");
|
||||
|
||||
JarUtils.saveAsJarClassesOnly(BytecodeViewer.getLoadedClasses(), tempJar.getAbsolutePath());
|
||||
String returnString = ExceptionUI.SEND_STACKTRACE_TO_NL;
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -178,7 +123,8 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
|
||||
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"));
|
||||
"-nauto", "-path", Configuration.rt + ";" + tempJar.getAbsolutePath() + buildCLIArguments(),
|
||||
"-out", tempDir.getAbsolutePath(), cn.name + ".class"));
|
||||
|
||||
Process process = pb.start();
|
||||
BytecodeViewer.createdProcesses.add(process);
|
||||
|
@ -212,22 +158,20 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
|
||||
int exitValue = process.waitFor();
|
||||
log.append(NL).append(NL).append(TranslatedStrings.EXIT_VALUE_IS).append(" ").append(exitValue);
|
||||
s = log.toString();
|
||||
returnString = log.toString();
|
||||
|
||||
//if the motherfucker failed this'll fail, aka wont set.
|
||||
s = DiskReader.loadAsString(tempDirectory.getAbsolutePath() + FS + cn.name + ".java");
|
||||
tempDirectory.delete();
|
||||
tempJar.delete();
|
||||
// update the string on a successful disassemble
|
||||
returnString = DiskReader.loadAsString(tempDir.getAbsolutePath() + FS + cn.name + ".java");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
s += NL + ExceptionUI.SEND_STACKTRACE_TO_NL + sw;
|
||||
returnString += NL + ExceptionUI.SEND_STACKTRACE_TO_NL + sw;
|
||||
}
|
||||
|
||||
return s;
|
||||
return returnString;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -237,18 +181,19 @@ public class KrakatauDecompiler extends InternalDecompiler
|
|||
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);
|
||||
ExternalResources.getSingleton().selectJRERTLibrary();
|
||||
}
|
||||
|
||||
String ran = MiscUtils.randomString(32);
|
||||
final String ran = MiscUtils.randomString(32);
|
||||
final File tempDirectory = new File(Constants.TEMP_DIRECTORY + FS + ran + FS);
|
||||
tempDirectory.mkdir();
|
||||
|
||||
final File tempJar = new File(sourceJar);
|
||||
|
||||
tempDirectory.mkdir();
|
||||
|
||||
try
|
||||
{
|
||||
String[] pythonCommands = new String[]{Configuration.python2};
|
||||
|
|
|
@ -45,12 +45,12 @@ import static the.bytecode.club.bytecodeviewer.Constants.*;
|
|||
public class KrakatauDisassembler extends InternalDecompiler
|
||||
{
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
public String decompileClassNode(ClassNode cn, byte[] bytes)
|
||||
{
|
||||
if (!ExternalResources.getSingleton().hasSetPython2Command())
|
||||
return TranslatedStrings.YOU_NEED_TO_SET_YOUR_PYTHON_2_PATH.toString();
|
||||
|
||||
String s = ExceptionUI.SEND_STACKTRACE_TO_NL;
|
||||
String returnString = ExceptionUI.SEND_STACKTRACE_TO_NL;
|
||||
|
||||
final File tempDirectory = new File(Constants.TEMP_DIRECTORY + FS + MiscUtils.randomString(32) + FS);
|
||||
tempDirectory.mkdir();
|
||||
|
@ -98,19 +98,20 @@ public class KrakatauDisassembler extends InternalDecompiler
|
|||
|
||||
int exitValue = process.waitFor();
|
||||
log.append(NL).append(NL).append(TranslatedStrings.EXIT_VALUE_IS).append(" ").append(exitValue);
|
||||
s = log.toString();
|
||||
returnString = log.toString();
|
||||
|
||||
// if the motherfucker failed this'll fail, aka won't set.
|
||||
s = DiskReader.loadAsString(tempDirectory.getAbsolutePath() + FS + cn.name + ".j");
|
||||
// update the string on a successful disassemble
|
||||
returnString = DiskReader.loadAsString(tempDirectory.getAbsolutePath() + FS + cn.name + ".j");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
e.printStackTrace();
|
||||
s += NL + ExceptionUI.SEND_STACKTRACE_TO_NL + sw;
|
||||
returnString += NL + ExceptionUI.SEND_STACKTRACE_TO_NL + sw;
|
||||
}
|
||||
return s;
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -132,7 +133,8 @@ public class KrakatauDisassembler extends InternalDecompiler
|
|||
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()));
|
||||
krakatauWorkingDirectory + FS + "disassemble.py", "-path", Configuration.rt + ";" + tempJar.getAbsolutePath(),
|
||||
"-out", tempDirectory.getAbsolutePath(), tempJar.getAbsolutePath()));
|
||||
|
||||
Process process = pb.start();
|
||||
BytecodeViewer.createdProcesses.add(process);
|
||||
|
|
|
@ -75,18 +75,17 @@ public class ProcyonDecompiler extends InternalDecompiler
|
|||
}
|
||||
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
public String decompileClassNode(ClassNode cn, byte[] bytes)
|
||||
{
|
||||
String exception;
|
||||
try
|
||||
{
|
||||
String fileStart = TEMP_DIRECTORY + FS + "temp";
|
||||
|
||||
final String fileStart = TEMP_DIRECTORY + FS + "temp";
|
||||
final File tempClass = new File(MiscUtils.getUniqueName(fileStart, ".class") + ".class");
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass))
|
||||
{
|
||||
fos.write(b);
|
||||
fos.write(bytes);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
@ -104,6 +103,7 @@ public class ProcyonDecompiler extends InternalDecompiler
|
|||
decompilationOptions.setFullDecompilation(true);
|
||||
|
||||
TypeDefinition resolvedType;
|
||||
|
||||
if (type == null || ((resolvedType = type.resolve()) == null))
|
||||
throw new Exception("Unable to resolve type.");
|
||||
|
||||
|
@ -142,7 +142,10 @@ public class ProcyonDecompiler extends InternalDecompiler
|
|||
*/
|
||||
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))
|
||||
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();
|
||||
|
@ -157,24 +160,30 @@ public class ProcyonDecompiler extends InternalDecompiler
|
|||
|
||||
Enumeration<JarEntry> ent = jfile.entries();
|
||||
Set<JarEntry> history = new HashSet<>();
|
||||
|
||||
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))
|
||||
{
|
||||
out.putNextEntry(etn);
|
||||
|
||||
try
|
||||
{
|
||||
String internalName = StringUtilities.removeRight(entry.getName(), ".class");
|
||||
TypeReference type = metadataSystem.lookupType(internalName);
|
||||
TypeDefinition resolvedType;
|
||||
|
||||
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);
|
||||
writer.flush();
|
||||
|
@ -190,10 +199,13 @@ public class ProcyonDecompiler extends InternalDecompiler
|
|||
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)
|
||||
|
@ -214,14 +226,12 @@ public class ProcyonDecompiler extends InternalDecompiler
|
|||
{
|
||||
// some jars contain duplicate pom.xml entries: ignore it
|
||||
if (!ze.getMessage().contains("duplicate"))
|
||||
{
|
||||
throw ze;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author DeathMarine
|
||||
|
@ -229,28 +239,26 @@ public class ProcyonDecompiler extends InternalDecompiler
|
|||
public static final class LuytenTypeLoader implements ITypeLoader
|
||||
{
|
||||
|
||||
private final List<ITypeLoader> _typeLoaders;
|
||||
private final List<ITypeLoader> typeLoaders;
|
||||
|
||||
public LuytenTypeLoader()
|
||||
{
|
||||
_typeLoaders = new ArrayList<>();
|
||||
_typeLoaders.add(new InputTypeLoader());
|
||||
typeLoaders = new ArrayList<>();
|
||||
typeLoaders.add(new InputTypeLoader());
|
||||
}
|
||||
|
||||
public List<ITypeLoader> getTypeLoaders()
|
||||
{
|
||||
return _typeLoaders;
|
||||
return typeLoaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryLoadType(String internalName, Buffer buffer)
|
||||
{
|
||||
for (ITypeLoader typeLoader : _typeLoaders)
|
||||
for (ITypeLoader typeLoader : typeLoaders)
|
||||
{
|
||||
if (typeLoader.tryLoadType(internalName, buffer))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
buffer.reset();
|
||||
}
|
||||
|
|
|
@ -44,21 +44,20 @@ import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.*;
|
|||
public class SmaliDisassembler extends InternalDecompiler
|
||||
{
|
||||
@Override
|
||||
public String decompileClassNode(ClassNode cn, byte[] b)
|
||||
public String decompileClassNode(ClassNode cn, byte[] bytes)
|
||||
{
|
||||
String exception = "";
|
||||
String fileStart = TEMP_DIRECTORY + FS + "temp";
|
||||
|
||||
String start = MiscUtils.getUniqueName(fileStart, ".class");
|
||||
|
||||
final String fileStart = TEMP_DIRECTORY + FS + "temp";
|
||||
final String start = MiscUtils.getUniqueName(fileStart, ".class");
|
||||
final File tempClass = new File(start + ".class");
|
||||
final File tempDex = new File(start + ".dex");
|
||||
final File tempDexOut = new File(start + "-out");
|
||||
final File tempSmali = new File(start + "-smali"); //output directory
|
||||
|
||||
String exception = "";
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(tempClass))
|
||||
{
|
||||
fos.write(b);
|
||||
fos.write(bytes);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
|
|
@ -40,7 +40,9 @@ public class JDGUIClassFileUtil
|
|||
{
|
||||
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)
|
||||
|
|
|
@ -59,6 +59,7 @@ public class DecompilerViewComponent
|
|||
{
|
||||
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)
|
||||
menu.add(bytecode);
|
||||
|
||||
|
@ -75,6 +76,7 @@ public class DecompilerViewComponent
|
|||
{
|
||||
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)
|
||||
group.add(bytecode);
|
||||
}
|
||||
|
|
|
@ -57,11 +57,13 @@ public class ExportJar extends JFrame
|
|||
btnNewButton.addActionListener(arg0 ->
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
|
||||
Thread t = new Thread(() ->
|
||||
{
|
||||
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), jarPath, manifest.getText());
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
}, "Jar Export");
|
||||
|
||||
t.start();
|
||||
dispose();
|
||||
});
|
||||
|
|
|
@ -151,6 +151,7 @@ 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();
|
||||
|
|
|
@ -45,6 +45,7 @@ public class FileChooser extends JFileChooser
|
|||
Set<String> extensionSet = new HashSet<>(Arrays.asList(extensions));
|
||||
|
||||
setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
|
||||
|
||||
try
|
||||
{
|
||||
setSelectedFile(file);
|
||||
|
|
|
@ -144,7 +144,8 @@ public class JFrameConsole extends JFrame
|
|||
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;
|
||||
trimmed = ("WARNING: Skipping " + skipped + " chars, allowing " + max + "\n\r")
|
||||
+ "Full log saved to: " + tempFile.getAbsolutePath() + "\n\r\n\r" + trimmed;
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ public class MethodsRenderer extends JLabel implements ListCellRenderer<Object>
|
|||
MethodParser methods;
|
||||
List<MethodParser> methodParsers = bytecodeViewPanelUpdater.viewer.methods;
|
||||
BytecodeViewPanel bytecodeViewPanel = bytecodeViewPanelUpdater.bytecodeViewPanel;
|
||||
|
||||
try
|
||||
{
|
||||
methods = methodParsers.get(bytecodeViewPanel.decompiler.ordinal());
|
||||
|
@ -56,8 +57,10 @@ public class MethodsRenderer extends JLabel implements ListCellRenderer<Object>
|
|||
{
|
||||
methods = methodParsers.get(bytecodeViewPanel.panelIndex);
|
||||
}
|
||||
|
||||
MethodParser.Method method = methods.getMethod(methodIndex);
|
||||
setText(method.toString());
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public class MultipleChoiceDialog
|
|||
dialog.setVisible(true);
|
||||
Object obj = pane.getValue();
|
||||
int result = -1;
|
||||
|
||||
for (int k = 0; k < options.length; k++)
|
||||
if (options[k].equals(obj))
|
||||
result = k;
|
||||
|
|
|
@ -71,6 +71,7 @@ public class MyErrorStripe extends JPanel
|
|||
float lineCount = textArea.getLineCount();
|
||||
int lineHeight = textArea.getLineHeight();
|
||||
int linesPerVisibleRect = h / lineHeight;
|
||||
|
||||
return Math.round((h - 1) * line / Math.max(lineCount, linesPerVisibleRect));
|
||||
}
|
||||
|
||||
|
@ -81,6 +82,7 @@ public class MyErrorStripe extends JPanel
|
|||
int lineHeight = textArea.getLineHeight();
|
||||
int linesPerVisibleRect = h / lineHeight;
|
||||
int lineCount = textArea.getLineCount();
|
||||
|
||||
if (y < h)
|
||||
{
|
||||
float at = y / (float) h;
|
||||
|
@ -119,6 +121,7 @@ public class MyErrorStripe extends JPanel
|
|||
for (DocumentRange range : occurrences)
|
||||
{
|
||||
int line;
|
||||
|
||||
try
|
||||
{
|
||||
line = textArea.getLineOfOffset(range.getStartOffset());
|
||||
|
@ -131,6 +134,7 @@ public class MyErrorStripe extends JPanel
|
|||
ParserNotice notice = new MarkedOccurrenceNotice(range, color);
|
||||
Integer key = line;
|
||||
Marker m = markerMap.get(key);
|
||||
|
||||
if (m == null)
|
||||
{
|
||||
m = new Marker(notice);
|
||||
|
@ -201,6 +205,7 @@ public class MyErrorStripe extends JPanel
|
|||
public void mouseClicked(@NotNull MouseEvent e)
|
||||
{
|
||||
Component source = (Component) e.getSource();
|
||||
|
||||
if (source instanceof MyErrorStripe.Marker)
|
||||
{
|
||||
Marker m = (Marker) source;
|
||||
|
@ -209,6 +214,7 @@ public class MyErrorStripe extends JPanel
|
|||
}
|
||||
|
||||
int line = yToLine(e.getY());
|
||||
|
||||
if (line > -1)
|
||||
{
|
||||
try
|
||||
|
@ -353,6 +359,7 @@ public class MyErrorStripe extends JPanel
|
|||
protected void paintComponent(Graphics g)
|
||||
{
|
||||
final ParserNotice notice = getHighestPriorityNotice();
|
||||
|
||||
if (notice != null)
|
||||
paintParserNoticeMarker((Graphics2D) g, notice, getWidth(), getHeight());
|
||||
}
|
||||
|
@ -362,6 +369,7 @@ public class MyErrorStripe extends JPanel
|
|||
ParserNotice pn = notices.get(0);
|
||||
int offs = pn.getOffset();
|
||||
int len = pn.getLength();
|
||||
|
||||
if (offs > -1 && len > -1) // These values are optional
|
||||
{
|
||||
DocumentRange range = new DocumentRange(offs, offs + len);
|
||||
|
@ -370,6 +378,7 @@ public class MyErrorStripe extends JPanel
|
|||
else
|
||||
{
|
||||
int line = pn.getLine();
|
||||
|
||||
try
|
||||
{
|
||||
offs = textArea.getLineStartOffset(line);
|
||||
|
|
|
@ -72,6 +72,7 @@ public class RSyntaxTextAreaHighlighterEx extends RSyntaxTextAreaHighlighter
|
|||
{
|
||||
int start = info.getStartOffset();
|
||||
int end = info.getEndOffset() + 1; // HACK
|
||||
|
||||
if (start <= end)
|
||||
{
|
||||
// Occasionally a Marked Occurrence can have a lost end offset
|
||||
|
@ -116,6 +117,7 @@ public class RSyntaxTextAreaHighlighterEx extends RSyntaxTextAreaHighlighter
|
|||
if (notice != null)
|
||||
{
|
||||
color = notice.getColor();
|
||||
|
||||
if (color == null)
|
||||
color = DEFAULT_PARSER_NOTICE_COLOR;
|
||||
}
|
||||
|
|
|
@ -111,6 +111,7 @@ 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()));
|
||||
|
|
|
@ -49,6 +49,7 @@ public class SettingsDialog extends JScrollPane
|
|||
return;
|
||||
|
||||
List<JMenuItem> options = new ArrayList<>();
|
||||
|
||||
for (Component child : menu.getMenuComponents())
|
||||
{
|
||||
if (!(child instanceof JMenuItem))
|
||||
|
@ -83,6 +84,7 @@ public class SettingsDialog extends JScrollPane
|
|||
private void buildPanel()
|
||||
{
|
||||
display.setLayout(new BoxLayout(display, BoxLayout.Y_AXIS));
|
||||
|
||||
for (JMenuItem menuItem : options)
|
||||
display.add(menuItem);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,9 @@ public class TextAreaSearchPanel extends JPanel
|
|||
public TextAreaSearchPanel(JTextArea textArea)
|
||||
{
|
||||
super(new BorderLayout());
|
||||
|
||||
this.textArea = textArea;
|
||||
|
||||
setup();
|
||||
setVisible(true);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,9 @@ public class WaitBusyIcon extends JMenuItemIcon
|
|||
public WaitBusyIcon()
|
||||
{
|
||||
super(new RotatableIcon(IconResources.busyIcon));
|
||||
|
||||
animator = new RotatableIconAnimator(8, (RotatableIcon) getIcon(), this);
|
||||
|
||||
addHierarchyListener(e ->
|
||||
{
|
||||
if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0)
|
||||
|
|
|
@ -90,6 +90,7 @@ public class GoToAction extends AbstractAction
|
|||
if (localMember.line == line && localMember.columnStart - 1 <= column && localMember.columnEnd >= column)
|
||||
{
|
||||
Element root = textArea.getDocument().getDefaultRootElement();
|
||||
|
||||
if (localMember.decRef.equals("declaration"))
|
||||
{
|
||||
int startOffset = root.getElement(localMember.line - 1).getStartOffset() + (localMember.columnStart - 1);
|
||||
|
@ -115,6 +116,7 @@ public class GoToAction extends AbstractAction
|
|||
if (method.line == line && method.columnStart - 1 <= column && method.columnEnd >= column)
|
||||
{
|
||||
Element root = textArea.getDocument().getDefaultRootElement();
|
||||
|
||||
if (method.decRef.equalsIgnoreCase("declaration"))
|
||||
{
|
||||
int startOffset = root.getElement(method.line - 1).getStartOffset() + (method.columnStart - 1);
|
||||
|
@ -131,7 +133,6 @@ public class GoToAction extends AbstractAction
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
open(textArea, false, false, true);
|
||||
}
|
||||
}
|
||||
|
@ -144,6 +145,7 @@ public class GoToAction extends AbstractAction
|
|||
{
|
||||
name = clazz.owner;
|
||||
Element root = textArea.getDocument().getDefaultRootElement();
|
||||
|
||||
if (clazz.type.equals("declaration"))
|
||||
{
|
||||
int startOffset = root.getElement(clazz.line - 1).getStartOffset() + (clazz.columnStart - 1);
|
||||
|
@ -173,6 +175,7 @@ public class GoToAction extends AbstractAction
|
|||
return null;
|
||||
|
||||
ResourceContainer resourceContainer = BytecodeViewer.getFileContainer(container.getParentContainer());
|
||||
|
||||
if (resourceContainer == null)
|
||||
return null;
|
||||
|
||||
|
@ -188,6 +191,7 @@ public class GoToAction extends AbstractAction
|
|||
{
|
||||
ClassMethodLocation classMethodLocation = container.getMethodLocationsFor(lexeme).get(0);
|
||||
ClassReferenceLocation classReferenceLocation = null;
|
||||
|
||||
try
|
||||
{
|
||||
classReferenceLocation = container.getClassReferenceLocationsFor(classMethodLocation.owner).get(0);
|
||||
|
@ -200,10 +204,12 @@ public class GoToAction extends AbstractAction
|
|||
return null;
|
||||
|
||||
String packagePath = classReferenceLocation.packagePath;
|
||||
|
||||
if (packagePath.startsWith("java") || packagePath.startsWith("javax") || packagePath.startsWith("com.sun"))
|
||||
return null;
|
||||
|
||||
String resourceName = packagePath + "/" + classMethodLocation.owner;
|
||||
|
||||
if (resourceContainer.resourceClasses.containsKey(resourceName))
|
||||
{
|
||||
BytecodeViewer.viewer.workPane.addClassResource(resourceContainer, resourceName + ".class");
|
||||
|
@ -216,10 +222,12 @@ public class GoToAction extends AbstractAction
|
|||
{
|
||||
ClassReferenceLocation classReferenceLocation = container.getClassReferenceLocationsFor(lexeme).get(0);
|
||||
String packagePath = classReferenceLocation.packagePath;
|
||||
|
||||
if (packagePath.startsWith("java") || packagePath.startsWith("javax") || packagePath.startsWith("com.sun"))
|
||||
return null;
|
||||
|
||||
String resourceName = packagePath + "/" + lexeme;
|
||||
|
||||
if (resourceContainer.resourceClasses.containsKey(resourceName))
|
||||
{
|
||||
BytecodeViewer.viewer.workPane.addClassResource(resourceContainer, resourceName + ".class");
|
||||
|
@ -240,9 +248,11 @@ public class GoToAction extends AbstractAction
|
|||
token = TokenUtil.getToken(textArea, token);
|
||||
String lexeme = token.getLexeme();
|
||||
ClassFileContainer classFileContainer;
|
||||
|
||||
if (isClass)
|
||||
{
|
||||
classFileContainer = openClass(lexeme, false, false);
|
||||
|
||||
if (classFileContainer == null)
|
||||
return;
|
||||
|
||||
|
@ -253,9 +263,7 @@ public class GoToAction extends AbstractAction
|
|||
classReference.forEach(classReferenceLocation ->
|
||||
{
|
||||
if (classReferenceLocation.type.equals("declaration"))
|
||||
{
|
||||
moveCursor(classReferenceLocation.line, classReferenceLocation.columnStart);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -273,9 +281,7 @@ public class GoToAction extends AbstractAction
|
|||
fields.forEach(classFieldLocation ->
|
||||
{
|
||||
if (classFieldLocation.type.equals("declaration"))
|
||||
{
|
||||
moveCursor(classFieldLocation.line, classFieldLocation.columnStart);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -283,6 +289,7 @@ public class GoToAction extends AbstractAction
|
|||
else if (isMethod)
|
||||
{
|
||||
classFileContainer = openClass(lexeme, false, true);
|
||||
|
||||
if (classFileContainer == null)
|
||||
return;
|
||||
|
||||
|
@ -293,14 +300,13 @@ public class GoToAction extends AbstractAction
|
|||
methods.forEach(method ->
|
||||
{
|
||||
if (method.decRef.equalsIgnoreCase("declaration"))
|
||||
{
|
||||
moveCursor(method.line, method.columnStart);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}, "Open Class");
|
||||
|
||||
thread.start();
|
||||
}
|
||||
|
||||
|
@ -352,6 +358,7 @@ public class GoToAction extends AbstractAction
|
|||
if (caretListener instanceof BytecodeViewPanelUpdater.MarkerCaretListener)
|
||||
{
|
||||
BytecodeViewPanelUpdater.MarkerCaretListener markerCaretListener = (BytecodeViewPanelUpdater.MarkerCaretListener) caretListener;
|
||||
|
||||
markerCaretListener.caretUpdate(new CaretEvent(panel.textArea)
|
||||
{
|
||||
@Override
|
||||
|
|
|
@ -63,7 +63,7 @@ public class ResourceListIconRenderer extends DefaultTreeCellRenderer
|
|||
boolean iconSet = false;
|
||||
|
||||
//guess file type based on extension
|
||||
ResourceType knownResourceType = onlyName.contains(":") ? null : ResourceType.extensionMap.get(FilenameUtils.getExtension(onlyName).toLowerCase());
|
||||
ResourceType knownResourceType = onlyName.contains(":") ? null : ResourceType.EXTENSION_MAP.get(FilenameUtils.getExtension(onlyName).toLowerCase());
|
||||
|
||||
//set the icon to a known file type
|
||||
if (knownResourceType != null
|
||||
|
|
|
@ -24,5 +24,6 @@ package the.bytecode.club.bytecodeviewer.gui.resourcesearch;
|
|||
*/
|
||||
public enum SearchRadius
|
||||
{
|
||||
All_Classes, Current_Class
|
||||
All_Classes,
|
||||
Current_Class
|
||||
}
|
||||
|
|
|
@ -27,7 +27,11 @@ import the.bytecode.club.bytecodeviewer.searching.impl.*;
|
|||
*/
|
||||
public enum SearchType
|
||||
{
|
||||
Strings(new LDCSearch()), Regex(new RegexSearch()), MethodCall(new MethodCallSearch()), FieldCall(new FieldCallSearch()), MemberWithAnnotation(new MemberWithAnnotationSearch());
|
||||
Strings(new LDCSearch()),
|
||||
Regex(new RegexSearch()),
|
||||
MethodCall(new MethodCallSearch()),
|
||||
FieldCall(new FieldCallSearch()),
|
||||
MemberWithAnnotation(new MemberWithAnnotationSearch());
|
||||
|
||||
public final SearchPanel panel;
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@ public class DecompilerSelectionPane
|
|||
//build the action commands
|
||||
none.setActionCommand(Decompiler.NONE.name());
|
||||
hexcode.setActionCommand(Decompiler.HEXCODE_VIEWER.name());
|
||||
|
||||
for (DecompilerViewComponent component : components)
|
||||
{
|
||||
for (Decompiler decompiler : component.getDecompilers())
|
||||
|
@ -123,6 +124,7 @@ public class DecompilerSelectionPane
|
|||
|
||||
//auto-save on decompiler change
|
||||
Enumeration<AbstractButton> it = group.getElements();
|
||||
|
||||
while (it.hasMoreElements())
|
||||
{
|
||||
AbstractButton button = it.nextElement();
|
||||
|
@ -140,14 +142,18 @@ public class DecompilerSelectionPane
|
|||
menu.add(new JSeparator());
|
||||
menu.add(procyon.getMenu());
|
||||
menu.add(CFR.getMenu());
|
||||
|
||||
if (!Configuration.jadxGroupedWithSmali)
|
||||
menu.add(JADX.getMenu());
|
||||
|
||||
menu.add(JD.getMenu());
|
||||
menu.add(fern.getMenu());
|
||||
menu.add(krakatau.getMenu());
|
||||
menu.add(new JSeparator());
|
||||
|
||||
if (Configuration.jadxGroupedWithSmali)
|
||||
menu.add(JADX.getMenu());
|
||||
|
||||
menu.add(smali.getMenu());
|
||||
menu.add(new JSeparator());
|
||||
menu.add(bytecode.getMenu());
|
||||
|
@ -166,6 +172,7 @@ public class DecompilerSelectionPane
|
|||
public void setSelectedDecompiler(Decompiler decompiler)
|
||||
{
|
||||
Enumeration<AbstractButton> it = group.getElements();
|
||||
|
||||
while (it.hasMoreElements())
|
||||
{
|
||||
AbstractButton button = it.nextElement();
|
||||
|
|
|
@ -38,10 +38,9 @@ public class TabComponent extends JPanel
|
|||
public TabComponent(JTabbedPane pane)
|
||||
{
|
||||
super(new FlowLayout(FlowLayout.LEFT, 0, 0));
|
||||
|
||||
if (pane == null)
|
||||
{
|
||||
throw new NullPointerException("TabbedPane is null");
|
||||
}
|
||||
|
||||
this.pane = pane;
|
||||
|
||||
|
@ -52,9 +51,7 @@ public class TabComponent extends JPanel
|
|||
{
|
||||
int i = pane.indexOfTabComponent(TabComponent.this);
|
||||
if (i != -1)
|
||||
{
|
||||
return pane.getTitleAt(i);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -101,14 +98,10 @@ public class TabComponent extends JPanel
|
|||
return;
|
||||
|
||||
if (pane.indexOfTabComponent(TabComponent.this) != 0)
|
||||
{
|
||||
removeTab(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
removeTab(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
|
||||
|
|
|
@ -29,8 +29,8 @@ import the.bytecode.club.bytecodeviewer.translation.TranslatedComponents;
|
|||
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
|
||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJButton;
|
||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedVisibleComponent;
|
||||
import the.bytecode.club.uikit.tabpopup.closer.JTabbedPanePopupMenuTabsCloser;
|
||||
import the.bytecode.club.uikit.tabpopup.closer.PopupMenuTabsCloseConfiguration;
|
||||
import the.bytecode.club.bytecodeviewer.gui.tabpopup.closer.JTabbedPanePopupMenuTabsCloser;
|
||||
import the.bytecode.club.bytecodeviewer.gui.tabpopup.closer.PopupMenuTabsCloseConfiguration;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
|
|
@ -82,7 +82,7 @@ public class FileViewer extends ResourceViewer
|
|||
// (If none selected, try Pane2, Pane3, default to Procyon)
|
||||
|
||||
//check by file extension to display image
|
||||
if (!onlyName.contains(":") && ResourceType.imageExtensionMap.containsKey(FilenameUtils.getExtension(onlyName)) && !hexViewerOnly)
|
||||
if (!onlyName.contains(":") && ResourceType.IMAGE_EXTENSION_MAP.containsKey(FilenameUtils.getExtension(onlyName)) && !hexViewerOnly)
|
||||
{
|
||||
canRefresh = true;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
package the.bytecode.club.uikit.tabpopup;
|
||||
package the.bytecode.club.bytecodeviewer.gui.tabpopup;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
@ -32,6 +32,7 @@ public abstract class AbstractJTabbedPanePopupMenuHandler extends JTabbedPanePop
|
|||
public AbstractJTabbedPanePopupMenuHandler(JTabbedPane tabbedPane)
|
||||
{
|
||||
super(tabbedPane);
|
||||
|
||||
registerPopupEventListener(this);
|
||||
}
|
||||
|
||||
|
@ -39,6 +40,7 @@ public abstract class AbstractJTabbedPanePopupMenuHandler extends JTabbedPanePop
|
|||
public void onTabPopupEvent(JTabbedPane tabbedPane, int index, TabPopupEvent e)
|
||||
{
|
||||
JPopupMenu popupMenu = toBuildTabPopupMenu(tabbedPane, e.getPopupOnTab());
|
||||
|
||||
popupTabMenuWithEvent(popupMenu, e);
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
package the.bytecode.club.uikit.tabpopup;
|
||||
package the.bytecode.club.bytecodeviewer.gui.tabpopup;
|
||||
|
||||
import javax.swing.*;
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
package the.bytecode.club.uikit.tabpopup;
|
||||
package the.bytecode.club.bytecodeviewer.gui.tabpopup;
|
||||
|
||||
import javax.swing.*;
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
package the.bytecode.club.uikit.tabpopup;
|
||||
package the.bytecode.club.bytecodeviewer.gui.tabpopup;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
@ -68,16 +68,16 @@ public class JTabbedPanePopupEventHandler
|
|||
if (e.isPopupTrigger())
|
||||
{
|
||||
int index = tabbedPane.indexAtLocation(e.getX(), e.getY());
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
Component popupOnTab = tabbedPane.getComponentAt(index);
|
||||
|
||||
if (this.tabPopupEventListener != null)
|
||||
{
|
||||
this.tabPopupEventListener.onTabPopupEvent(tabbedPane, index, new TabPopupEvent(e, popupOnTab));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public JTabbedPane getTabbedPane()
|
||||
{
|
|
@ -16,16 +16,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
package the.bytecode.club.uikit.tabpopup;
|
||||
package the.bytecode.club.bytecodeviewer.gui.tabpopup;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
public class TabPopupEvent extends MouseEvent
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 2510164400674753411L;
|
||||
|
||||
private final Component popupOnTab;
|
|
@ -16,9 +16,9 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
package the.bytecode.club.uikit.tabpopup.closer;
|
||||
package the.bytecode.club.bytecodeviewer.gui.tabpopup.closer;
|
||||
|
||||
import the.bytecode.club.uikit.tabpopup.ITabZeroComponentEventListener;
|
||||
import the.bytecode.club.bytecodeviewer.gui.tabpopup.ITabZeroComponentEventListener;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
@ -61,18 +61,16 @@ public class JTabbedPaneCloser
|
|||
protected void removeOtherComponents(Component component, boolean equalStop)
|
||||
{
|
||||
int i = this.tabbedPane.getTabCount();
|
||||
|
||||
while (i-- > 0)
|
||||
{
|
||||
Component c = this.tabbedPane.getComponentAt(i);
|
||||
|
||||
if (c != component)
|
||||
{
|
||||
this.tabbedPane.remove(i);
|
||||
}
|
||||
else if (equalStop)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tryTriggerTabZeroComponentEvent();
|
||||
}
|
||||
|
@ -82,17 +80,15 @@ public class JTabbedPaneCloser
|
|||
int count = this.tabbedPane.getTabCount();
|
||||
int i = 0;
|
||||
List<Component> removeTabs = new ArrayList<>();
|
||||
|
||||
do
|
||||
{
|
||||
Component c = this.tabbedPane.getComponentAt(i);
|
||||
|
||||
if (c != component)
|
||||
{
|
||||
removeTabs.add(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (i++ < count);
|
||||
|
||||
for (Component c : removeTabs)
|
||||
|
@ -117,8 +113,6 @@ public class JTabbedPaneCloser
|
|||
private void tryTriggerTabZeroComponentEvent()
|
||||
{
|
||||
if (this.tabbedPane.getTabCount() == 0 && tabZeroComponentEventListener != null)
|
||||
{
|
||||
tabZeroComponentEventListener.onTabZeroComponent(this.tabbedPane);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,9 +16,9 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
package the.bytecode.club.uikit.tabpopup.closer;
|
||||
package the.bytecode.club.bytecodeviewer.gui.tabpopup.closer;
|
||||
|
||||
import the.bytecode.club.uikit.tabpopup.AbstractJTabbedPanePopupMenuHandler;
|
||||
import the.bytecode.club.bytecodeviewer.gui.tabpopup.AbstractJTabbedPanePopupMenuHandler;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
@ -54,6 +54,7 @@ public class JTabbedPanePopupMenuTabsCloser extends AbstractJTabbedPanePopupMenu
|
|||
public JPopupMenu toBuildTabPopupMenu(JTabbedPane tabbedPane, Component popupOnTab)
|
||||
{
|
||||
JPopupMenu popUpMenu = new JPopupMenu();
|
||||
|
||||
if (closeConfiguration.isClose())
|
||||
addItemCloseTab(popUpMenu, popupOnTab);
|
||||
|
||||
|
@ -79,8 +80,7 @@ public class JTabbedPanePopupMenuTabsCloser extends AbstractJTabbedPanePopupMenu
|
|||
|
||||
protected void addItemCloseOtherTabs(JPopupMenu popUpMenu, Component popupOnTab)
|
||||
{
|
||||
addMenuItem(popUpMenu, "Close Others", e ->
|
||||
{tabbedPaneCloser.removeOtherComponents(popupOnTab);});
|
||||
addMenuItem(popUpMenu, "Close Others", e -> tabbedPaneCloser.removeOtherComponents(popupOnTab));
|
||||
}
|
||||
|
||||
protected void addItemCloseAllTabs(JPopupMenu popUpMenu)
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
package the.bytecode.club.uikit.tabpopup.closer;
|
||||
package the.bytecode.club.bytecodeviewer.gui.tabpopup.closer;
|
||||
|
||||
/**
|
||||
* PopupMenu items configuration of close tabs
|
|
@ -23,15 +23,20 @@ import org.objectweb.asm.tree.ClassNode;
|
|||
import the.bytecode.club.bytecodeviewer.malwarescanner.impl.*;
|
||||
|
||||
/**
|
||||
* All of the installed malware scan modules
|
||||
* All the installed malware scan modules
|
||||
*
|
||||
* @author Konloch
|
||||
* @since 6/27/2021
|
||||
*/
|
||||
public enum MalwareScanModule
|
||||
{
|
||||
URL_SCANNER("Scan String URLs", new URLScanner(), true), REFLECTION_SCANNER("Scan Java Reflection", new ReflectionScanner(), false), JAVA_RUNTIME_SCANNER("Scan Java Runtime", new JavaRuntimeScanner(), true), JAVA_NET_SCANNER("Scan Java Net", new JavaNetScanner(), false), JAVA_IO_SCANNER("Scan Java IO", new JavaIOScanner(), false), AWT_ROBOT_SCANNER("Scan AWT Robot", new AWTRobotScanner(), true), NULL_SECURITY_MANAGER("Scan Null SecurityManager", new NullSecurityManagerScanner(), true),
|
||||
;
|
||||
URL_SCANNER("Scan String URLs", new URLScanner(), true),
|
||||
REFLECTION_SCANNER("Scan Java Reflection", new ReflectionScanner(), false),
|
||||
JAVA_RUNTIME_SCANNER("Scan Java Runtime", new JavaRuntimeScanner(), true),
|
||||
JAVA_NET_SCANNER("Scan Java Net", new JavaNetScanner(), false),
|
||||
JAVA_IO_SCANNER("Scan Java IO", new JavaIOScanner(), false),
|
||||
AWT_ROBOT_SCANNER("Scan AWT Robot", new AWTRobotScanner(), true),
|
||||
NULL_SECURITY_MANAGER("Scan Null SecurityManager", new NullSecurityManagerScanner(), true);
|
||||
|
||||
static
|
||||
{
|
||||
|
|
|
@ -53,6 +53,7 @@ public class AWTRobotScanner extends MalwareCodeScanner
|
|||
if (instruction instanceof MethodInsnNode)
|
||||
{
|
||||
final MethodInsnNode min = (MethodInsnNode) instruction;
|
||||
|
||||
if (min.owner.startsWith("java/awt/Robot"))
|
||||
foundMethod(scan, instructionToString(instruction) + " at " + methodToString(cn, method) + NL);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public class JavaIOScanner extends MalwareCodeScanner
|
|||
if (instruction instanceof MethodInsnNode)
|
||||
{
|
||||
final MethodInsnNode min = (MethodInsnNode) instruction;
|
||||
|
||||
if (min.owner.startsWith("java/io"))
|
||||
foundMethod(scan, instructionToString(instruction) + " at " + methodToString(cn, method) + NL);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ public class JavaNetScanner extends MalwareCodeScanner
|
|||
if (instruction instanceof MethodInsnNode)
|
||||
{
|
||||
final MethodInsnNode min = (MethodInsnNode) instruction;
|
||||
|
||||
if (min.owner.startsWith("java/net"))
|
||||
foundMethod(scan, instructionToString(instruction) + " at " + methodToString(cn, method) + NL);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ public class JavaRuntimeScanner extends MalwareCodeScanner
|
|||
if (instruction instanceof MethodInsnNode)
|
||||
{
|
||||
final MethodInsnNode min = (MethodInsnNode) instruction;
|
||||
|
||||
if (min.owner.startsWith("java/lang/Runtime"))
|
||||
foundMethod(scan, instructionToString(instruction) + " at " + methodToString(cn, method) + NL);
|
||||
}
|
||||
|
|
|
@ -57,11 +57,11 @@ public class NullSecurityManagerScanner extends MalwareCodeScanner
|
|||
final String owner = min.owner;
|
||||
final String name = min.name;
|
||||
|
||||
if (lastInstruction == OpCode.ACONST_NULL.getCode() && owner.equals("java/lang/System") && name.equals("setSecurityManager"))
|
||||
{
|
||||
if (lastInstruction == OpCode.ACONST_NULL.getCode()
|
||||
&& owner.equals("java/lang/System")
|
||||
&& name.equals("setSecurityManager"))
|
||||
found(scan, "Security Manager set to null at method " + methodToString(cn, method) + NL);
|
||||
}
|
||||
}
|
||||
|
||||
lastInstruction = instruction.getOpcode();
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ public class NullSecurityManagerScanner extends MalwareCodeScanner
|
|||
public void scanningClass(MalwareScan scan, ClassNode cn)
|
||||
{
|
||||
lastInstruction = 0;
|
||||
|
||||
super.scanningClass(scan, cn);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ public class ReflectionScanner extends MalwareCodeScanner
|
|||
if (instruction instanceof MethodInsnNode)
|
||||
{
|
||||
final MethodInsnNode min = (MethodInsnNode) instruction;
|
||||
|
||||
if (min.owner.startsWith("java/lang/reflect"))
|
||||
foundMethod(scan, instructionToString(instruction) + " at " + methodToString(cn, method) + NL);
|
||||
}
|
||||
|
|
|
@ -34,12 +34,18 @@ import java.util.List;
|
|||
public abstract class JavaObfuscator extends Thread
|
||||
{
|
||||
|
||||
public static int MAX_STRING_LENGTH = 25;
|
||||
public static int MIN_STRING_LENGTH = 5;
|
||||
private final List<String> names = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
BytecodeViewer.updateBusyStatus(true);
|
||||
Configuration.runningObfuscation = true;
|
||||
|
||||
obfuscate();
|
||||
|
||||
BytecodeViewer.refactorer.run();
|
||||
Configuration.runningObfuscation = false;
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
|
@ -48,24 +54,16 @@ public abstract class JavaObfuscator extends Thread
|
|||
public int getStringLength()
|
||||
{
|
||||
if (BytecodeViewer.viewer.obfuscatorGroup.isSelected(BytecodeViewer.viewer.strongObf.getModel()))
|
||||
{
|
||||
return MAX_STRING_LENGTH;
|
||||
}
|
||||
else
|
||||
{ // if(BytecodeViewer.viewer.obfuscatorGroup.isSelected(BytecodeViewer.viewer.lightObf.getModel()))
|
||||
// {
|
||||
else // if(BytecodeViewer.viewer.obfuscatorGroup.isSelected(BytecodeViewer.viewer.lightObf.getModel()))
|
||||
return MIN_STRING_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
public static int MAX_STRING_LENGTH = 25;
|
||||
public static int MIN_STRING_LENGTH = 5;
|
||||
private final List<String> names = new ArrayList<>();
|
||||
|
||||
protected String generateUniqueName(int length)
|
||||
{
|
||||
boolean found = false;
|
||||
String name = "";
|
||||
|
||||
while (!found)
|
||||
{
|
||||
String nameTry = MiscUtils.randomString(1) + MiscUtils.randomStringNum(length - 1);
|
||||
|
@ -79,6 +77,7 @@ public abstract class JavaObfuscator extends Thread
|
|||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ public class RenameClasses extends JavaObfuscator
|
|||
int stringLength = getStringLength();
|
||||
|
||||
System.out.println("Obfuscating class names...");
|
||||
|
||||
for (ClassNode c : BytecodeViewer.getLoadedClasses())
|
||||
{
|
||||
String newName = generateUniqueName(stringLength);
|
||||
|
|
|
@ -38,6 +38,7 @@ public class RenameFields extends JavaObfuscator
|
|||
int stringLength = getStringLength();
|
||||
|
||||
System.out.println("Obfuscating fields names...");
|
||||
|
||||
for (ClassNode c : BytecodeViewer.getLoadedClasses())
|
||||
{
|
||||
for (Object o : c.fields.toArray())
|
||||
|
|
|
@ -39,6 +39,7 @@ public class RenameMethods extends JavaObfuscator
|
|||
int stringLength = getStringLength();
|
||||
|
||||
System.out.println("Obfuscating method names...");
|
||||
|
||||
for (ClassNode c : BytecodeViewer.getLoadedClasses())
|
||||
{
|
||||
for (Object o : c.methods.toArray())
|
||||
|
|
|
@ -47,6 +47,7 @@ public class RefactorMapper extends Remapper
|
|||
sortedFields = new HashMap<>();
|
||||
mappingList = new ArrayList<>();
|
||||
builder = new StringBuilder();
|
||||
|
||||
for (MappingData hook : hookMap.getClasses())
|
||||
{
|
||||
if (hook.getObfuscatedName().contains("$"))
|
||||
|
@ -56,6 +57,7 @@ public class RefactorMapper extends Remapper
|
|||
sortedClasses.put(obfuscatedName, hook);
|
||||
sortedClasses.put(refactoredName, hook);
|
||||
}
|
||||
|
||||
for (MethodMappingData hook : hookMap.getMethods())
|
||||
{
|
||||
String obfuscatedName = hook.getMethodName().getObfuscatedName();
|
||||
|
@ -63,6 +65,7 @@ public class RefactorMapper extends Remapper
|
|||
String obfuscatedCname = hook.getMethodOwner();
|
||||
sortedMethods.put(obfuscatedCname + "$$$$" + obfuscatedName + "$$$$" + obfuscatedDesc, hook);
|
||||
}
|
||||
|
||||
for (FieldMappingData hook : hookMap.getFields())
|
||||
{
|
||||
String obfuscatedName = hook.getName().getObfuscatedName();
|
||||
|
@ -83,6 +86,7 @@ public class RefactorMapper extends Remapper
|
|||
|
||||
return sortedClasses.get(type).getRefactoredName();
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -90,6 +94,7 @@ public class RefactorMapper extends Remapper
|
|||
public String mapFieldName(String owner, String name, String desc)
|
||||
{
|
||||
String obfKey = owner + "$$$$" + name + "$$$$" + desc;
|
||||
|
||||
if (sortedFields.containsKey(obfKey))
|
||||
{
|
||||
String map = owner + "." + name + " --> " + owner + sortedFields.get(obfKey).getName().getRefactoredName() + "\n";
|
||||
|
@ -97,6 +102,7 @@ public class RefactorMapper extends Remapper
|
|||
mappingList.add(map);
|
||||
name = sortedFields.get(obfKey).getName().getRefactoredName();
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -104,6 +110,7 @@ public class RefactorMapper extends Remapper
|
|||
public String mapMethodName(String owner, String name, String desc)
|
||||
{
|
||||
String obfKey = owner + "$$$$" + name + "$$$$" + desc;
|
||||
|
||||
if (sortedMethods.containsKey(obfKey))
|
||||
{
|
||||
String map = owner + "." + name + " --> " + owner + sortedMethods.get(obfKey).getMethodName().getRefactoredName() + "\n";
|
||||
|
@ -111,6 +118,7 @@ public class RefactorMapper extends Remapper
|
|||
mappingList.add(map);
|
||||
name = sortedMethods.get(obfKey).getMethodName().getRefactoredName();
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -120,6 +128,7 @@ public class RefactorMapper extends Remapper
|
|||
{
|
||||
builder.append(map);
|
||||
}
|
||||
|
||||
System.out.println(builder.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,9 +60,11 @@ public class Refactorer
|
|||
cr.accept(cn, 0);
|
||||
//refactored.put(oldName, cn);
|
||||
}
|
||||
|
||||
/*for (Map.Entry<String, ClassNode> factor : refactored.entrySet()) {
|
||||
BytecodeViewer.relocate(factor.getKey(), factor.getValue());
|
||||
}*/
|
||||
|
||||
mapper.printMap();
|
||||
}
|
||||
|
||||
|
|
|
@ -56,22 +56,26 @@ public abstract class Remapper extends org.objectweb.asm.commons.Remapper
|
|||
public String mapDesc(String desc)
|
||||
{
|
||||
Type t = Type.getType(desc);
|
||||
|
||||
switch (t.getSort())
|
||||
{
|
||||
case Type.ARRAY:
|
||||
StringBuilder s = new StringBuilder(mapDesc(t.getElementType().getDescriptor()));
|
||||
|
||||
for (int i = 0; i < t.getDimensions(); ++i)
|
||||
{
|
||||
s.insert(0, '[');
|
||||
}
|
||||
|
||||
return s.toString();
|
||||
|
||||
case Type.OBJECT:
|
||||
String newType = map(t.getInternalName());
|
||||
|
||||
if (newType != null)
|
||||
{
|
||||
return 'L' + newType + ';';
|
||||
}
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
|
@ -81,17 +85,22 @@ public abstract class Remapper extends org.objectweb.asm.commons.Remapper
|
|||
{
|
||||
case Type.ARRAY:
|
||||
StringBuilder s = new StringBuilder(mapDesc(t.getElementType().getDescriptor()));
|
||||
|
||||
for (int i = 0; i < t.getDimensions(); ++i)
|
||||
{
|
||||
s.insert(0, '[');
|
||||
}
|
||||
|
||||
return Type.getType(s.toString());
|
||||
|
||||
case Type.OBJECT:
|
||||
s = new StringBuilder(map(t.getInternalName()));
|
||||
return Type.getObjectType(s.toString());
|
||||
|
||||
case Type.METHOD:
|
||||
return Type.getMethodType(mapMethodDesc(t.getDescriptor()));
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -99,9 +108,8 @@ public abstract class Remapper extends org.objectweb.asm.commons.Remapper
|
|||
public String mapType(String type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return mapType(Type.getObjectType(type)).getInternalName();
|
||||
}
|
||||
|
||||
|
@ -110,24 +118,26 @@ public abstract class Remapper extends org.objectweb.asm.commons.Remapper
|
|||
{
|
||||
String[] newTypes = null;
|
||||
boolean needMapping = false;
|
||||
|
||||
for (int i = 0; i < types.length; i++)
|
||||
{
|
||||
String type = types[i];
|
||||
String newType = map(type);
|
||||
|
||||
if (newType != null && newTypes == null)
|
||||
{
|
||||
newTypes = new String[types.length];
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
System.arraycopy(types, 0, newTypes, 0, i);
|
||||
}
|
||||
|
||||
needMapping = true;
|
||||
}
|
||||
|
||||
if (needMapping)
|
||||
{
|
||||
newTypes[i] = newType == null ? type : newType;
|
||||
}
|
||||
}
|
||||
|
||||
return needMapping ? newTypes : types;
|
||||
}
|
||||
|
||||
|
@ -135,22 +145,24 @@ public abstract class Remapper extends org.objectweb.asm.commons.Remapper
|
|||
public String mapMethodDesc(String desc)
|
||||
{
|
||||
if ("()V".equals(desc))
|
||||
{
|
||||
return desc;
|
||||
}
|
||||
|
||||
Type[] args = Type.getArgumentTypes(desc);
|
||||
StringBuilder sb = new StringBuilder("(");
|
||||
|
||||
for (Type arg : args)
|
||||
{
|
||||
sb.append(mapDesc(arg.getDescriptor()));
|
||||
}
|
||||
|
||||
Type returnType = Type.getReturnType(desc);
|
||||
|
||||
if (returnType == Type.VOID_TYPE)
|
||||
{
|
||||
sb.append(")V");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
sb.append(')').append(mapDesc(returnType.getDescriptor()));
|
||||
return sb.toString();
|
||||
}
|
||||
|
@ -159,14 +171,14 @@ public abstract class Remapper extends org.objectweb.asm.commons.Remapper
|
|||
public Object mapValue(Object value)
|
||||
{
|
||||
if (value instanceof Type)
|
||||
{
|
||||
return mapType((Type) value);
|
||||
}
|
||||
|
||||
if (value instanceof Handle)
|
||||
{
|
||||
Handle h = (Handle) value;
|
||||
return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName(h.getOwner(), h.getName(), h.getDesc()), mapMethodDesc(h.getDesc()), h.getTag() == Opcodes.H_INVOKEINTERFACE);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -179,20 +191,17 @@ public abstract class Remapper extends org.objectweb.asm.commons.Remapper
|
|||
public String mapSignature(String signature, boolean typeSignature)
|
||||
{
|
||||
if (signature == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
SignatureReader r = new SignatureReader(signature);
|
||||
SignatureWriter w = new SignatureWriter();
|
||||
SignatureVisitor a = createSignatureRemapper(w);
|
||||
|
||||
if (typeSignature)
|
||||
{
|
||||
r.acceptType(a);
|
||||
}
|
||||
else
|
||||
{
|
||||
r.accept(a);
|
||||
}
|
||||
|
||||
return w.toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -106,9 +106,11 @@ public class RemappingMethodAdapter extends LocalVariablesSorter
|
|||
Object t = entries[i];
|
||||
newEntries[i++] = t instanceof String ? remapper.mapType((String) t) : t;
|
||||
} while (i < n);
|
||||
|
||||
return newEntries;
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
|
@ -127,6 +129,7 @@ public class RemappingMethodAdapter extends LocalVariablesSorter
|
|||
super.visitMethodInsn(opcode, owner, name, desc);
|
||||
return;
|
||||
}
|
||||
|
||||
doVisitMethodInsn(opcode, owner, name, desc, opcode == Opcodes.INVOKEINTERFACE);
|
||||
}
|
||||
|
||||
|
@ -138,6 +141,7 @@ public class RemappingMethodAdapter extends LocalVariablesSorter
|
|||
super.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
return;
|
||||
}
|
||||
|
||||
doVisitMethodInsn(opcode, owner, name, desc, itf);
|
||||
}
|
||||
|
||||
|
@ -150,10 +154,8 @@ public class RemappingMethodAdapter extends LocalVariablesSorter
|
|||
// IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
|
||||
// LocalVariableSorter.
|
||||
if (mv != null)
|
||||
{
|
||||
mv.visitMethodInsn(opcode, remapper.mapType(owner), remapper.mapMethodName(owner, name, desc), remapper.mapMethodDesc(desc), itf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs)
|
||||
|
@ -162,6 +164,7 @@ public class RemappingMethodAdapter extends LocalVariablesSorter
|
|||
{
|
||||
bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
|
||||
}
|
||||
|
||||
super.visitInvokeDynamicInsn(remapper.mapInvokeDynamicMethodName(name, desc), remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm), bsmArgs);
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,9 @@ public class FieldMappingData
|
|||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
|
||||
FieldMappingData other = (FieldMappingData) obj;
|
||||
|
||||
if (desc == null)
|
||||
{
|
||||
if (other.desc != null)
|
||||
|
@ -98,6 +100,7 @@ public class FieldMappingData
|
|||
}
|
||||
else if (!desc.equals(other.desc))
|
||||
return false;
|
||||
|
||||
if (fieldOwner == null)
|
||||
{
|
||||
if (other.fieldOwner != null)
|
||||
|
@ -105,10 +108,9 @@ public class FieldMappingData
|
|||
}
|
||||
else if (!fieldOwner.equals(other.fieldOwner))
|
||||
return false;
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
return other.name == null;
|
||||
}
|
||||
else
|
||||
return name.equals(other.name);
|
||||
}
|
||||
|
|
|
@ -76,7 +76,9 @@ public class MappingData
|
|||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
|
||||
MappingData other = (MappingData) obj;
|
||||
|
||||
if (obfuscatedName == null)
|
||||
{
|
||||
if (other.obfuscatedName != null)
|
||||
|
@ -84,10 +86,9 @@ public class MappingData
|
|||
}
|
||||
else if (!obfuscatedName.equals(other.obfuscatedName))
|
||||
return false;
|
||||
|
||||
if (refactoredName == null)
|
||||
{
|
||||
return other.refactoredName == null;
|
||||
}
|
||||
else
|
||||
return refactoredName.equals(other.refactoredName);
|
||||
}
|
||||
|
|
|
@ -90,7 +90,9 @@ public class MethodMappingData
|
|||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
|
||||
MethodMappingData other = (MethodMappingData) obj;
|
||||
|
||||
if (methodDesc == null)
|
||||
{
|
||||
if (other.methodDesc != null)
|
||||
|
@ -98,6 +100,7 @@ public class MethodMappingData
|
|||
}
|
||||
else if (!methodDesc.equals(other.methodDesc))
|
||||
return false;
|
||||
|
||||
if (methodName == null)
|
||||
{
|
||||
if (other.methodName != null)
|
||||
|
@ -105,10 +108,9 @@ public class MethodMappingData
|
|||
}
|
||||
else if (!methodName.equals(other.methodName))
|
||||
return false;
|
||||
|
||||
if (methodOwner == null)
|
||||
{
|
||||
return other.methodOwner == null;
|
||||
}
|
||||
else
|
||||
return methodOwner.equals(other.methodOwner);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,9 @@ public class RenameClasses extends JavaObfuscator
|
|||
BytecodeViewer.showMessage("You're currently running an obfuscation task, wait for this to finish" + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
new RenameClasses().start();
|
||||
|
||||
BytecodeViewer.viewer.workPane.refreshClass.doClick();
|
||||
BytecodeViewer.viewer.resourcePane.tree.updateUI();
|
||||
}
|
||||
|
@ -61,7 +63,8 @@ public class RenameClasses extends JavaObfuscator
|
|||
for (MethodNode o : c.methods)
|
||||
{
|
||||
/* As we dont want to rename any main-classes */
|
||||
if (o.name.equals("main") && o.desc.equals("([Ljava/lang/String;)V") || o.name.equals("init") && c.superName.equals("java/applet/Applet"))
|
||||
if (o.name.equals("main") && o.desc.equals("([Ljava/lang/String;)V")
|
||||
|| o.name.equals("init") && c.superName.equals("java/applet/Applet"))
|
||||
continue classLoop;
|
||||
|
||||
/* As we dont want to rename native dll methods */
|
||||
|
|
|
@ -42,7 +42,9 @@ public class RenameFields extends JavaObfuscator
|
|||
BytecodeViewer.showMessage("You're currently running an obfuscation task, wait for this to finish.");
|
||||
return;
|
||||
}
|
||||
|
||||
new RenameFields().start();
|
||||
|
||||
BytecodeViewer.viewer.workPane.refreshClass.doClick();
|
||||
BytecodeViewer.viewer.resourcePane.tree.updateUI();
|
||||
}
|
||||
|
|
|
@ -43,7 +43,9 @@ public class RenameMethods extends JavaObfuscator
|
|||
BytecodeViewer.showMessage("You're currently running an obfuscation task, wait for this to finish" + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
new RenameMethods().start();
|
||||
|
||||
BytecodeViewer.viewer.workPane.refreshClass.doClick();
|
||||
BytecodeViewer.viewer.resourcePane.tree.updateUI();
|
||||
}
|
||||
|
|
|
@ -219,14 +219,13 @@ public class AllatoriStringDecrypter extends Plugin
|
|||
if (i instanceof MethodInsnNode)
|
||||
{
|
||||
MethodInsnNode methodi = ((MethodInsnNode) i);
|
||||
|
||||
if ("currentThread".equals(methodi.name)) // find code form this instruction
|
||||
{
|
||||
insn = i;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (insn == null)
|
||||
|
@ -241,6 +240,7 @@ public class AllatoriStringDecrypter extends Plugin
|
|||
if ("hashCode".equals(methodi.name)) // to this instruction
|
||||
break;
|
||||
}
|
||||
|
||||
removeInsn = insn;
|
||||
insn = insn.getNext();
|
||||
iList.remove(removeInsn); // and remove it
|
||||
|
|
|
@ -75,6 +75,7 @@ public class ReplaceStrings extends Plugin
|
|||
if (v instanceof String)
|
||||
{
|
||||
String s = (String) v;
|
||||
|
||||
if (contains)
|
||||
{
|
||||
if (s.contains(originalLDC))
|
||||
|
@ -92,6 +93,7 @@ public class ReplaceStrings extends Plugin
|
|||
for (int i = 0; i < ((String[]) v).length; i++)
|
||||
{
|
||||
String s = ((String[]) v)[i];
|
||||
|
||||
if (contains)
|
||||
{
|
||||
if (s.contains(originalLDC))
|
||||
|
@ -118,6 +120,7 @@ public class ReplaceStrings extends Plugin
|
|||
{
|
||||
MethodNode m = (MethodNode) o;
|
||||
InsnList iList = m.instructions;
|
||||
|
||||
for (AbstractInsnNode a : iList.toArray())
|
||||
{
|
||||
if (a instanceof LdcInsnNode)
|
||||
|
@ -125,6 +128,7 @@ public class ReplaceStrings extends Plugin
|
|||
if (((LdcInsnNode) a).cst instanceof String)
|
||||
{
|
||||
final String s = (String) ((LdcInsnNode) a).cst;
|
||||
|
||||
if (contains)
|
||||
{
|
||||
if (s.contains(originalLDC))
|
||||
|
|
|
@ -38,6 +38,7 @@ public class ViewAPKAndroidPermissions extends Plugin
|
|||
frame.setVisible(true);
|
||||
|
||||
byte[] encodedAndroidManifest = activeContainer.getFileContents("AndroidManifest.xml");
|
||||
|
||||
if (encodedAndroidManifest == null)
|
||||
{
|
||||
frame.appendText("This plugin only works on valid Android APKs");
|
||||
|
@ -45,6 +46,7 @@ public class ViewAPKAndroidPermissions extends Plugin
|
|||
}
|
||||
|
||||
byte[] decodedAndroidManifest = activeContainer.getFileContents("Decoded Resources/AndroidManifest.xml");
|
||||
|
||||
if (decodedAndroidManifest != null)
|
||||
{
|
||||
String manifest = new String(decodedAndroidManifest, StandardCharsets.UTF_8);
|
||||
|
|
|
@ -39,6 +39,7 @@ public class ViewManifest extends Plugin
|
|||
|
||||
//TODO android APKs may have AndroidManifests that can be viewed normally, this should be checked
|
||||
byte[] encodedAndroidManifest = activeContainer.getFileContents("AndroidManifest.xml");
|
||||
|
||||
if (encodedAndroidManifest != null)
|
||||
{
|
||||
frame.appendText("Android APK Manifest:\r");
|
||||
|
@ -50,6 +51,7 @@ public class ViewManifest extends Plugin
|
|||
}
|
||||
|
||||
byte[] jarManifest = activeContainer.getFileContents("META-INF/MANIFEST.MF");
|
||||
|
||||
if (jarManifest != null)
|
||||
{
|
||||
if (!frame.getTextArea().getText().isEmpty())
|
||||
|
|
|
@ -52,11 +52,13 @@ public class ZStringArrayDecrypter extends Plugin
|
|||
if (dialog.promptChoice() == 0)
|
||||
{
|
||||
boolean needsWarning = false;
|
||||
|
||||
for (Class<?> cn : Objects.requireNonNull(BCV.loadClassesIntoClassLoader()))
|
||||
{
|
||||
try
|
||||
{
|
||||
Field[] fields = cn.getDeclaredFields();
|
||||
|
||||
for (Field field : fields)
|
||||
{
|
||||
if (field.getName().equals("z"))
|
||||
|
@ -81,9 +83,8 @@ public class ZStringArrayDecrypter extends Plugin
|
|||
}
|
||||
|
||||
if (needsWarning)
|
||||
{
|
||||
BytecodeViewer.showMessage("Some classes failed to decrypt, if you'd like to decrypt all of them" + NL + "makes sure you include ALL the libraries it requires.");
|
||||
}
|
||||
BytecodeViewer.showMessage("Some classes failed to decrypt, if you'd like to decrypt all of them"
|
||||
+ NL + "makes sure you include ALL the libraries it requires.");
|
||||
|
||||
gui.setText(out.toString());
|
||||
gui.setVisible(true);
|
||||
|
|
|
@ -56,15 +56,11 @@ public class CompiledJavaPluginLaunchStrategy implements PluginLaunchStrategy
|
|||
if (Objects.equals(cn.superName, PLUGIN_CLASS_NAME))
|
||||
{
|
||||
if (pdata == null)
|
||||
{
|
||||
pdata = d;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException("Multiple plugin subclasses.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadingClassLoader cl = new LoadingClassLoader(pdata, set);
|
||||
Plugin p = cl.pluginKlass.getDeclaredConstructor().newInstance();
|
||||
|
@ -92,9 +88,11 @@ public class CompiledJavaPluginLaunchStrategy implements PluginLaunchStrategy
|
|||
try
|
||||
{
|
||||
String name = entry.getName();
|
||||
|
||||
if (name.endsWith(".class"))
|
||||
{
|
||||
byte[] bytes = MiscUtils.getBytes(jis);
|
||||
|
||||
if (FileHeaderUtils.doesFileHeaderMatch(bytes, FileHeaderUtils.JAVA_CLASS_FILE_HEADER))
|
||||
{
|
||||
try
|
||||
|
@ -174,20 +172,20 @@ public class CompiledJavaPluginLaunchStrategy implements PluginLaunchStrategy
|
|||
public static class LoadingClassLoader extends ClassLoader
|
||||
{
|
||||
private final LoadedNodeData data;
|
||||
private final Map<String, LoadedNodeData> cache;
|
||||
private final Map<String, Class<?>> ccache;
|
||||
private final Map<String, LoadedNodeData> nodeCache;
|
||||
private final Map<String, Class<?>> classCache;
|
||||
private final Class<? extends Plugin> pluginKlass;
|
||||
|
||||
public LoadingClassLoader(LoadedNodeData data, Set<LoadedNodeData> set) throws Throwable
|
||||
{
|
||||
this.data = data;
|
||||
|
||||
cache = new HashMap<>();
|
||||
ccache = new HashMap<>();
|
||||
nodeCache = new HashMap<>();
|
||||
classCache = new HashMap<>();
|
||||
|
||||
for (LoadedNodeData d : set)
|
||||
{
|
||||
cache.put(d.node.name, d);
|
||||
nodeCache.put(d.node.name, d);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") Class<? extends Plugin> pluginKlass = (Class<? extends Plugin>) loadClass(data.node.name.replace("/", "."));
|
||||
|
@ -205,15 +203,16 @@ public class CompiledJavaPluginLaunchStrategy implements PluginLaunchStrategy
|
|||
|
||||
System.out.println("finding " + name);
|
||||
|
||||
if (ccache.containsKey(name))
|
||||
return ccache.get(name);
|
||||
if (classCache.containsKey(name))
|
||||
return classCache.get(name);
|
||||
|
||||
LoadedNodeData data = nodeCache.get(name);
|
||||
|
||||
LoadedNodeData data = cache.get(name);
|
||||
if (data != null)
|
||||
{
|
||||
byte[] bytes = data.bytes;
|
||||
Class<?> klass = defineClass(data.node.name.replace("/", "."), bytes, 0, bytes.length);
|
||||
ccache.put(name, klass);
|
||||
classCache.put(name, klass);
|
||||
return klass;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,8 @@ public class ResourceDecompiling
|
|||
if (!BytecodeViewer.autoCompileSuccessful())
|
||||
return;
|
||||
|
||||
final JFileChooser fc = new FileChooser(Configuration.getLastSaveDirectory(), "Select Zip Export", "Zip Archives", "zip");
|
||||
final JFileChooser fc = new FileChooser(Configuration.getLastSaveDirectory(),
|
||||
"Select Zip Export", "Zip Archives", "zip");
|
||||
|
||||
//if the user doesn't select a file then we should stop while we're ahead
|
||||
if (fc.showSaveDialog(BytecodeViewer.viewer) != JFileChooser.APPROVE_OPTION)
|
||||
|
@ -87,7 +88,8 @@ public class ResourceDecompiling
|
|||
return;
|
||||
|
||||
//this temporary jar file will be used to store the classes while BCV performs decompilation
|
||||
File temporaryTargetJar = MiscUtils.deleteExistingFile(new File(TEMP_DIRECTORY + FS + "temp_" + MiscUtils.getRandomizedName() + ".jar"));
|
||||
File temporaryTargetJar = MiscUtils.deleteExistingFile(new File(TEMP_DIRECTORY + FS
|
||||
+ "temp_" + MiscUtils.getRandomizedName() + ".jar"));
|
||||
|
||||
//extract all the loaded classes imported into BCV to the temporary target jar
|
||||
JarUtils.saveAsJarClassesOnly(BytecodeViewer.getLoadedClasses(), temporaryTargetJar.getAbsolutePath());
|
||||
|
@ -254,7 +256,8 @@ public class ResourceDecompiling
|
|||
BytecodeViewer.updateBusyStatus(true);
|
||||
|
||||
//decompile all opened classes to zip
|
||||
decompiler.getDecompiler().decompileToZip(targetJar.getAbsolutePath(), saveAll ? MiscUtils.append(outputZip, "-" + decompiler.getDecompilerNameProgrammic() + ".zip") : outputZip.getAbsolutePath());
|
||||
decompiler.getDecompiler().decompileToZip(targetJar.getAbsolutePath(), saveAll ? MiscUtils.append(outputZip,
|
||||
"-" + decompiler.getDecompilerNameProgrammic() + ".zip") : outputZip.getAbsolutePath());
|
||||
|
||||
//signal to the user that BCV is finished performing that action
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
|
@ -266,7 +269,8 @@ public class ResourceDecompiling
|
|||
BytecodeViewer.updateBusyStatus(true);
|
||||
|
||||
//decompile the currently opened resource and save it to the specified file
|
||||
DiskWriter.replaceFile(saveAll ? MiscUtils.append(outputFile, "-" + decompiler.getDecompilerNameProgrammic() + ".java") : outputFile.getAbsolutePath(), BCV.decompileCurrentlyOpenedClassNode(decompiler), false);
|
||||
DiskWriter.replaceFile(saveAll ? MiscUtils.append(outputFile,
|
||||
"-" + decompiler.getDecompilerNameProgrammic() + ".java") : outputFile.getAbsolutePath(), BCV.decompileCurrentlyOpenedClassNode(decompiler), false);
|
||||
|
||||
//signal to the user that BCV is finished performing that action
|
||||
BytecodeViewer.updateBusyStatus(false);
|
||||
|
|
|
@ -33,12 +33,23 @@ public enum ResourceType
|
|||
// TODO add the files icons for the missing files from the.bytecode.club.bytecodeviewer.util.SyntaxLanguage
|
||||
// or from org.fife.ui.rsyntaxtextarea.FileTypeUtil or from org.fife.ui.rsyntaxtextarea.SyntaxConstants
|
||||
|
||||
CLASS_FILE(IconResources.classIcon, "class"), JAVA_ARCHIVE(IconResources.jarIcon, "jar", "war", "ear"), ZIP_ARCHIVE(IconResources.zipIcon, "zip"), ANDROID_ARCHIVE(IconResources.androidIcon, "apk", "wapk", "dex"), IMAGE_FILE(IconResources.imageIcon, "png", "jpg", "jpeg", "bmp", "wbmp", "gif", "tif", "webp"), CONFIG_TEXT_FILE(IconResources.configIcon, "properties", "xml", "jsp", "mf", "config", "csv", "yml", "yaml", "ini", "json", "sql", "gradle", "dockerfile", "htaccess", "plugin", "attachprovider", "transportservice", "connector"), JAVA_FILE(IconResources.javaIcon, "java"), TEXT_FILE(IconResources.textIcon, "txt", "md", "log", "html", "css"), CPP_FILE(IconResources.cplusplusIcon, "c", "cpp", "h"), CSHARP_FILE(IconResources.csharpIcon, "cs"), BAT_FILE(IconResources.batIcon, "bat", "batch"), SH_FILE(IconResources.shIcon, "sh", "bash"),
|
||||
;
|
||||
CLASS_FILE(IconResources.classIcon, "class"),
|
||||
JAVA_ARCHIVE(IconResources.jarIcon, "jar", "war", "ear"),
|
||||
ZIP_ARCHIVE(IconResources.zipIcon, "zip"),
|
||||
ANDROID_ARCHIVE(IconResources.androidIcon, "apk", "wapk", "dex", "xapk"),
|
||||
IMAGE_FILE(IconResources.imageIcon, "png", "jpg", "jpeg", "bmp", "wbmp", "gif", "tif", "webp"),
|
||||
CONFIG_TEXT_FILE(IconResources.configIcon, "properties", "xml", "jsp", "mf", "config", "csv", "yml", "yaml", "ini",
|
||||
"json", "sql", "gradle", "dockerfile", "htaccess", "plugin", "attachprovider", "transportservice", "connector"),
|
||||
JAVA_FILE(IconResources.javaIcon, "java"),
|
||||
TEXT_FILE(IconResources.textIcon, "txt", "md", "log", "html", "css"),
|
||||
CPP_FILE(IconResources.cplusplusIcon, "c", "cpp", "h"),
|
||||
CSHARP_FILE(IconResources.csharpIcon, "cs"),
|
||||
BAT_FILE(IconResources.batIcon, "bat", "batch"),
|
||||
SH_FILE(IconResources.shIcon, "sh", "bash");
|
||||
|
||||
public static final Map<String, ResourceType> extensionMap = new HashMap<>();
|
||||
public static final Map<String, ResourceType> imageExtensionMap = new HashMap<>();
|
||||
public static final Map<String, ResourceType> supportedBCVExtensionMap = new HashMap<>();
|
||||
public static final Map<String, ResourceType> EXTENSION_MAP = new HashMap<>();
|
||||
public static final Map<String, ResourceType> IMAGE_EXTENSION_MAP = new HashMap<>();
|
||||
public static final Map<String, ResourceType> SUPPORTED_BCV_EXTENSION_MAP = new HashMap<>();
|
||||
|
||||
private final Icon icon;
|
||||
private final String[] extensions;
|
||||
|
@ -49,21 +60,21 @@ public enum ResourceType
|
|||
//add all extensions
|
||||
for (ResourceType t : values())
|
||||
for (String extension : t.extensions)
|
||||
extensionMap.put(extension, t);
|
||||
EXTENSION_MAP.put(extension, t);
|
||||
|
||||
//add image extensions
|
||||
for (String extension : IMAGE_FILE.extensions)
|
||||
imageExtensionMap.put(extension, IMAGE_FILE);
|
||||
IMAGE_EXTENSION_MAP.put(extension, IMAGE_FILE);
|
||||
|
||||
//add extensions BCV can be opened with
|
||||
for (String extension : CLASS_FILE.extensions)
|
||||
supportedBCVExtensionMap.put(extension, CLASS_FILE);
|
||||
SUPPORTED_BCV_EXTENSION_MAP.put(extension, CLASS_FILE);
|
||||
for (String extension : JAVA_ARCHIVE.extensions)
|
||||
supportedBCVExtensionMap.put(extension, JAVA_ARCHIVE);
|
||||
SUPPORTED_BCV_EXTENSION_MAP.put(extension, JAVA_ARCHIVE);
|
||||
for (String extension : ZIP_ARCHIVE.extensions)
|
||||
supportedBCVExtensionMap.put(extension, ZIP_ARCHIVE);
|
||||
SUPPORTED_BCV_EXTENSION_MAP.put(extension, ZIP_ARCHIVE);
|
||||
for (String extension : ANDROID_ARCHIVE.extensions)
|
||||
supportedBCVExtensionMap.put(extension, ANDROID_ARCHIVE);
|
||||
SUPPORTED_BCV_EXTENSION_MAP.put(extension, ANDROID_ARCHIVE);
|
||||
}
|
||||
|
||||
ResourceType(Icon icon, String... extensions)
|
||||
|
|
|
@ -60,15 +60,15 @@ public class ClassFileContainer
|
|||
CompilationUnit compilationUnit = StaticJavaParser.parse(this.content);
|
||||
compilationUnit.accept(new MyVoidVisitor(this, compilationUnit), null);
|
||||
}
|
||||
catch (java.lang.ClassCastException | UnsolvedSymbolException | ParseProblemException e)
|
||||
{
|
||||
System.err.println("Parsing error!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Parsing error: " + className);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public String getName()
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
package the.bytecode.club.bytecodeviewer.util;
|
||||
|
||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||
import the.bytecode.club.bytecodeviewer.CommandLineInput;
|
||||
import the.bytecode.club.bytecodeviewer.cli.CLIAction;
|
||||
import the.bytecode.club.bytecodeviewer.cli.CommandLineInput;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.Boot;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.loader.ILoader;
|
||||
import the.bytecode.club.bytecodeviewer.bootloader.resource.external.EmptyExternalResource;
|
||||
|
@ -109,10 +110,9 @@ public class BootCheck implements Runnable
|
|||
|
||||
Boot.hide();
|
||||
|
||||
int CLI = CommandLineInput.parseCommandLine(BytecodeViewer.launchArgs);
|
||||
CLIAction CLI = CommandLineInput.parseCommandLine(BytecodeViewer.launchArgs);
|
||||
|
||||
|
||||
if (CLI == CommandLineInput.GUI)
|
||||
if (CLI == CLIAction.GUI)
|
||||
BytecodeViewer.boot(false);
|
||||
else
|
||||
{
|
||||
|
|
|
@ -64,7 +64,8 @@ public class JarUtils
|
|||
ResourceContainer container = new ResourceContainer(jarFile);
|
||||
Map<String, byte[]> files = new LinkedHashMap<>();
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(jarFile); ZipInputStream jis = new ZipInputStream(fis))
|
||||
try (FileInputStream fis = new FileInputStream(jarFile);
|
||||
ZipInputStream jis = new ZipInputStream(fis))
|
||||
{
|
||||
ZipEntry entry;
|
||||
while ((entry = jis.getNextEntry()) != null)
|
||||
|
@ -184,7 +185,8 @@ public class JarUtils
|
|||
public static List<ClassNode> loadClasses(File jarFile) throws IOException
|
||||
{
|
||||
List<ClassNode> classes = new ArrayList<>();
|
||||
try (FileInputStream fis = new FileInputStream(jarFile); ZipInputStream jis = new ZipInputStream(fis))
|
||||
try (FileInputStream fis = new FileInputStream(jarFile);
|
||||
ZipInputStream jis = new ZipInputStream(fis))
|
||||
{
|
||||
ZipEntry entry;
|
||||
while ((entry = jis.getNextEntry()) != null)
|
||||
|
@ -405,7 +407,8 @@ public class JarUtils
|
|||
*/
|
||||
public static void saveAsJar(List<ClassNode> nodeList, String path)
|
||||
{
|
||||
try (FileOutputStream fos = new FileOutputStream(path); JarOutputStream out = new JarOutputStream(fos))
|
||||
try (FileOutputStream fos = new FileOutputStream(path);
|
||||
JarOutputStream out = new JarOutputStream(fos))
|
||||
{
|
||||
List<String> noDupe = new ArrayList<>();
|
||||
for (ClassNode cn : nodeList)
|
||||
|
|
|
@ -56,8 +56,10 @@ public class MiscUtils
|
|||
public static String randomString(int len)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
sb.append(AB.charAt(RND.nextInt(AB.length())));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
@ -70,9 +72,11 @@ public class MiscUtils
|
|||
{
|
||||
boolean generated = false;
|
||||
String name = "";
|
||||
|
||||
while (!generated)
|
||||
{
|
||||
String randomizedName = MiscUtils.randomString(25);
|
||||
|
||||
if (!CREATED_RANDOMIZED_NAMES.contains(randomizedName))
|
||||
{
|
||||
CREATED_RANDOMIZED_NAMES.add(randomizedName);
|
||||
|
@ -80,6 +84,7 @@ public class MiscUtils
|
|||
generated = true;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -87,7 +92,8 @@ public class MiscUtils
|
|||
{
|
||||
//Read out dir output
|
||||
try (InputStream is = process.getInputStream();
|
||||
InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr))
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
|
@ -117,8 +123,10 @@ public class MiscUtils
|
|||
public static String randomStringNum(int len)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
sb.append(AN.charAt(RND.nextInt(AN.length())));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
@ -135,10 +143,12 @@ public class MiscUtils
|
|||
boolean b = true;
|
||||
File f;
|
||||
String m;
|
||||
|
||||
while (b)
|
||||
{
|
||||
m = MiscUtils.randomString(32);
|
||||
f = new File(start + m + ext);
|
||||
|
||||
if (!f.exists())
|
||||
{
|
||||
s = start + m;
|
||||
|
@ -159,14 +169,17 @@ public class MiscUtils
|
|||
{
|
||||
boolean b = true;
|
||||
int i = 0;
|
||||
|
||||
while (b)
|
||||
{
|
||||
File tempF = new File(start + i + ext);
|
||||
|
||||
if (!tempF.exists())
|
||||
b = false;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -186,14 +199,17 @@ public class MiscUtils
|
|||
public static String append(File file, String extension)
|
||||
{
|
||||
String path = file.getAbsolutePath();
|
||||
|
||||
if (!path.endsWith(extension))
|
||||
path += extension;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public static int fileContainersHash(List<ResourceContainer> resourceContainers)
|
||||
{
|
||||
StringBuilder block = new StringBuilder();
|
||||
|
||||
for (ResourceContainer container : resourceContainers)
|
||||
{
|
||||
block.append(container.name);
|
||||
|
@ -246,6 +262,7 @@ public class MiscUtils
|
|||
public static void deduplicateAndTrim(List<String> list, int maxLength)
|
||||
{
|
||||
List<String> temporaryList = new ArrayList<>();
|
||||
|
||||
for (String s : list)
|
||||
if (!s.isEmpty() && !temporaryList.contains(s))
|
||||
temporaryList.add(s);
|
||||
|
@ -265,6 +282,7 @@ public class MiscUtils
|
|||
{
|
||||
double ascii = 0;
|
||||
double other = 0;
|
||||
|
||||
for (byte b : data)
|
||||
{
|
||||
if (b == 0x09 || b == 0x0A || b == 0x0C || b == 0x0D || (b >= 0x20 && b <= 0x7E))
|
||||
|
@ -272,6 +290,7 @@ public class MiscUtils
|
|||
else
|
||||
other++;
|
||||
}
|
||||
|
||||
return other != 0 && other / (ascii + other) > 0.25;
|
||||
}
|
||||
|
||||
|
@ -345,9 +364,9 @@ public class MiscUtils
|
|||
{
|
||||
try (ByteArrayOutputStream baos = new ByteArrayOutputStream())
|
||||
{
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int a;
|
||||
|
||||
while ((a = is.read(buffer)) != -1)
|
||||
baos.write(buffer, 0, a);
|
||||
|
||||
|
@ -359,9 +378,11 @@ public class MiscUtils
|
|||
{
|
||||
if (file == null)
|
||||
return new File[0];
|
||||
|
||||
File[] list = file.listFiles();
|
||||
if (list != null)
|
||||
return list;
|
||||
|
||||
return new File[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -41,11 +41,14 @@ public class NewlineOutputStream extends FilterOutputStream
|
|||
public NewlineOutputStream(OutputStream os)
|
||||
{
|
||||
super(os);
|
||||
|
||||
if (newline == null)
|
||||
{
|
||||
String s = Constants.NL;
|
||||
|
||||
if (s == null || s.length() <= 0)
|
||||
s = "\n";
|
||||
|
||||
newline = s.getBytes(StandardCharsets.ISO_8859_1); // really us-ascii
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +69,7 @@ public class NewlineOutputStream extends FilterOutputStream
|
|||
{
|
||||
out.write(b);
|
||||
}
|
||||
|
||||
lastByte = b;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,37 @@ public enum SyntaxLanguage
|
|||
XML(SyntaxConstants.SYNTAX_STYLE_XML, (n, c) -> n.endsWith(".xml") || c.startsWith("<?xml") || c.startsWith("<xml")),
|
||||
PYTHON(SyntaxConstants.SYNTAX_STYLE_PYTHON, (n, c) -> n.endsWith(".py") || n.endsWith(".python")),
|
||||
RUBY(SyntaxConstants.SYNTAX_STYLE_RUBY, (n, c) -> n.endsWith(".rb") || n.endsWith(".ruby")),
|
||||
JAVA(SyntaxConstants.SYNTAX_STYLE_JAVA, (n, c) -> n.endsWith(".java")), HTML(SyntaxConstants.SYNTAX_STYLE_HTML, (n, c) -> n.endsWith(".html")), CSS(SyntaxConstants.SYNTAX_STYLE_CSS, (n, c) -> n.endsWith(".css")), PROPERTIES(SyntaxConstants.SYNTAX_STYLE_PROPERTIES_FILE, (n, c) -> n.endsWith(".properties") || n.endsWith(".mf") || n.endsWith(".sf") || n.endsWith(".plugin") || n.endsWith(".attachprovider") || n.endsWith(".transportservice") || n.endsWith(".connector")), PHP(SyntaxConstants.SYNTAX_STYLE_PHP, (n, c) -> n.endsWith(".php") || c.startsWith("<?php")), JS(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT, (n, c) -> n.endsWith(".js")), BATCH(SyntaxConstants.SYNTAX_STYLE_WINDOWS_BATCH, (n, c) -> n.endsWith(".bat")), SHELL(SyntaxConstants.SYNTAX_STYLE_UNIX_SHELL, (n, c) -> n.endsWith(".sh")), C(SyntaxConstants.SYNTAX_STYLE_C, (n, c) -> n.endsWith(".c") || n.endsWith(".h")), CPP(SyntaxConstants.SYNTAX_STYLE_CPLUSPLUS, (n, c) -> n.endsWith(".cpp") || n.endsWith(".hpp")), SCALA(SyntaxConstants.SYNTAX_STYLE_SCALA, (n, c) -> n.endsWith(".scala")), CLOJURE(SyntaxConstants.SYNTAX_STYLE_CLOJURE, (n, c) -> n.endsWith(".clojure")), GROOVY(SyntaxConstants.SYNTAX_STYLE_GROOVY, (n, c) -> n.endsWith(".groovy") || n.endsWith(".gradle")), LUA(SyntaxConstants.SYNTAX_STYLE_LUA, (n, c) -> n.endsWith(".lua")), SQL(SyntaxConstants.SYNTAX_STYLE_SQL, (n, c) -> n.endsWith(".sql")), JSON(SyntaxConstants.SYNTAX_STYLE_JSON, (n, c) -> n.endsWith(".json")), JSP(SyntaxConstants.SYNTAX_STYLE_JSP, (n, c) -> n.endsWith(".jsp")), YAML(SyntaxConstants.SYNTAX_STYLE_YAML, (n, c) -> n.endsWith(".yml") || n.endsWith(".yaml")), CS(SyntaxConstants.SYNTAX_STYLE_CSHARP, (n, c) -> n.endsWith(".cs")), CSV(SyntaxConstants.SYNTAX_STYLE_CSV, (n, c) -> n.endsWith(".csv")), DOCKER(SyntaxConstants.SYNTAX_STYLE_DOCKERFILE, (n, c) -> n.endsWith(".dockerfile")), DART(SyntaxConstants.SYNTAX_STYLE_DART, (n, c) -> n.endsWith(".dart")), GO(SyntaxConstants.SYNTAX_STYLE_GO, (n, c) -> n.endsWith(".go")), HTACCESS(SyntaxConstants.SYNTAX_STYLE_HTACCESS, (n, c) -> n.endsWith(".htaccess")), INI(SyntaxConstants.SYNTAX_STYLE_INI, (n, c) -> n.endsWith(".ini")), KOTLIN(SyntaxConstants.SYNTAX_STYLE_KOTLIN, (n, c) -> n.endsWith(".kt") || n.endsWith(".kts")), LATEX(SyntaxConstants.SYNTAX_STYLE_LATEX, (n, c) -> n.endsWith(".tex")), MARKDOWN(SyntaxConstants.SYNTAX_STYLE_MARKDOWN, (n, c) -> n.endsWith(".md")), PERL(SyntaxConstants.SYNTAX_STYLE_PERL, (n, c) -> n.endsWith(".pl")), TYPESCRIPT(SyntaxConstants.SYNTAX_STYLE_TYPESCRIPT, (n, c) -> n.endsWith(".ts")), NONE(SyntaxConstants.SYNTAX_STYLE_NONE, (n, c) -> false);
|
||||
JAVA(SyntaxConstants.SYNTAX_STYLE_JAVA, (n, c) -> n.endsWith(".java")),
|
||||
HTML(SyntaxConstants.SYNTAX_STYLE_HTML, (n, c) -> n.endsWith(".html")),
|
||||
CSS(SyntaxConstants.SYNTAX_STYLE_CSS, (n, c) -> n.endsWith(".css")),
|
||||
PROPERTIES(SyntaxConstants.SYNTAX_STYLE_PROPERTIES_FILE, (n, c) -> n.endsWith(".properties") || n.endsWith(".mf") || n.endsWith(".sf") || n.endsWith(".plugin") || n.endsWith(".attachprovider") || n.endsWith(".transportservice") || n.endsWith(".connector")),
|
||||
PHP(SyntaxConstants.SYNTAX_STYLE_PHP, (n, c) -> n.endsWith(".php") || c.startsWith("<?php")),
|
||||
JS(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT, (n, c) -> n.endsWith(".js")),
|
||||
BATCH(SyntaxConstants.SYNTAX_STYLE_WINDOWS_BATCH, (n, c) -> n.endsWith(".bat")),
|
||||
SHELL(SyntaxConstants.SYNTAX_STYLE_UNIX_SHELL, (n, c) -> n.endsWith(".sh")),
|
||||
C(SyntaxConstants.SYNTAX_STYLE_C, (n, c) -> n.endsWith(".c") || n.endsWith(".h")),
|
||||
CPP(SyntaxConstants.SYNTAX_STYLE_CPLUSPLUS, (n, c) -> n.endsWith(".cpp") || n.endsWith(".hpp")),
|
||||
SCALA(SyntaxConstants.SYNTAX_STYLE_SCALA, (n, c) -> n.endsWith(".scala")),
|
||||
CLOJURE(SyntaxConstants.SYNTAX_STYLE_CLOJURE, (n, c) -> n.endsWith(".clojure")),
|
||||
GROOVY(SyntaxConstants.SYNTAX_STYLE_GROOVY, (n, c) -> n.endsWith(".groovy") || n.endsWith(".gradle")),
|
||||
LUA(SyntaxConstants.SYNTAX_STYLE_LUA, (n, c) -> n.endsWith(".lua")),
|
||||
SQL(SyntaxConstants.SYNTAX_STYLE_SQL, (n, c) -> n.endsWith(".sql")),
|
||||
JSON(SyntaxConstants.SYNTAX_STYLE_JSON, (n, c) -> n.endsWith(".json")),
|
||||
JSP(SyntaxConstants.SYNTAX_STYLE_JSP, (n, c) -> n.endsWith(".jsp")),
|
||||
YAML(SyntaxConstants.SYNTAX_STYLE_YAML, (n, c) -> n.endsWith(".yml") || n.endsWith(".yaml")),
|
||||
CS(SyntaxConstants.SYNTAX_STYLE_CSHARP, (n, c) -> n.endsWith(".cs")),
|
||||
CSV(SyntaxConstants.SYNTAX_STYLE_CSV, (n, c) -> n.endsWith(".csv")),
|
||||
DOCKER(SyntaxConstants.SYNTAX_STYLE_DOCKERFILE, (n, c) -> n.endsWith(".dockerfile")),
|
||||
DART(SyntaxConstants.SYNTAX_STYLE_DART, (n, c) -> n.endsWith(".dart")),
|
||||
GO(SyntaxConstants.SYNTAX_STYLE_GO, (n, c) -> n.endsWith(".go")),
|
||||
HTACCESS(SyntaxConstants.SYNTAX_STYLE_HTACCESS, (n, c) -> n.endsWith(".htaccess")),
|
||||
INI(SyntaxConstants.SYNTAX_STYLE_INI, (n, c) -> n.endsWith(".ini")),
|
||||
KOTLIN(SyntaxConstants.SYNTAX_STYLE_KOTLIN, (n, c) -> n.endsWith(".kt") || n.endsWith(".kts")),
|
||||
LATEX(SyntaxConstants.SYNTAX_STYLE_LATEX, (n, c) -> n.endsWith(".tex")),
|
||||
MARKDOWN(SyntaxConstants.SYNTAX_STYLE_MARKDOWN, (n, c) -> n.endsWith(".md")),
|
||||
PERL(SyntaxConstants.SYNTAX_STYLE_PERL, (n, c) -> n.endsWith(".pl")),
|
||||
TYPESCRIPT(SyntaxConstants.SYNTAX_STYLE_TYPESCRIPT, (n, c) -> n.endsWith(".ts")),
|
||||
NONE(SyntaxConstants.SYNTAX_STYLE_NONE, (n, c) -> false);
|
||||
|
||||
public static final SyntaxLanguage[] VALUES = values();
|
||||
|
||||
|
@ -68,20 +98,19 @@ public enum SyntaxLanguage
|
|||
for (SyntaxLanguage lang : VALUES)
|
||||
{
|
||||
if (lang.isLanguage(fileName, content))
|
||||
{
|
||||
return lang;
|
||||
}
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
|
||||
public static void setLanguage(RSyntaxTextArea area, String fileName)
|
||||
{
|
||||
String type = FILE_TYPE_UTIL.guessContentType(new File(fileName));
|
||||
|
||||
if (type == null || type.equals(SyntaxConstants.SYNTAX_STYLE_NONE))
|
||||
{
|
||||
type = FILE_TYPE_UTIL.guessContentType(area);
|
||||
}
|
||||
|
||||
area.setSyntaxEditingStyle(type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,12 +50,8 @@ public class WindowStateChangeAdapter extends WindowAdapter
|
|||
}*/
|
||||
|
||||
if ((oldState & Frame.MAXIMIZED_BOTH) == 0 && (newState & Frame.MAXIMIZED_BOTH) != 0)
|
||||
{
|
||||
mainViewerGUI.isMaximized = true;
|
||||
}
|
||||
else if ((oldState & Frame.MAXIMIZED_BOTH) != 0 && (newState & Frame.MAXIMIZED_BOTH) == 0)
|
||||
{
|
||||
mainViewerGUI.isMaximized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,12 +44,14 @@ public final class ZipUtils
|
|||
public static void unzipFilesToPath(String jarPath, String destinationDir) throws IOException
|
||||
{
|
||||
String canonicalDestDir = new File(destinationDir).getCanonicalPath();
|
||||
|
||||
if (!canonicalDestDir.endsWith(File.separator))
|
||||
{
|
||||
canonicalDestDir += File.separator;
|
||||
}
|
||||
|
||||
File file = new File(jarPath);
|
||||
|
||||
try (JarFile jar = new JarFile(file))
|
||||
{
|
||||
|
||||
|
@ -82,6 +84,7 @@ public final class ZipUtils
|
|||
}
|
||||
|
||||
File parent = f.getParentFile();
|
||||
|
||||
if (!parent.exists())
|
||||
{
|
||||
parent.mkdirs();
|
||||
|
@ -110,6 +113,7 @@ public final class ZipUtils
|
|||
{
|
||||
ZipEntry ze = new ZipEntry(inputFile.getName());
|
||||
zos.putNextEntry(ze);
|
||||
|
||||
try (FileInputStream in = new FileInputStream(inputFile))
|
||||
{
|
||||
int len;
|
||||
|
@ -156,14 +160,18 @@ public final class ZipUtils
|
|||
{
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
|
||||
try (FileInputStream in = new FileInputStream(srcFile))
|
||||
{
|
||||
ZipEntry entry;
|
||||
|
||||
if (ignore == null)
|
||||
entry = new ZipEntry(path + "/" + folder.getName());
|
||||
else
|
||||
entry = new ZipEntry(path.replace(ignore, "BCV_Krakatau") + "/" + folder.getName());
|
||||
|
||||
zip.putNextEntry(entry);
|
||||
|
||||
while ((len = in.read(buf)) > 0)
|
||||
{
|
||||
zip.write(buf, 0, len);
|
||||
|
@ -194,6 +202,7 @@ public final class ZipUtils
|
|||
{
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
|
||||
try (FileInputStream in = new FileInputStream(srcFile))
|
||||
{
|
||||
ZipEntry entry;
|
||||
|
@ -216,15 +225,11 @@ public final class ZipUtils
|
|||
for (String fileName : Objects.requireNonNull(folder.list()))
|
||||
{
|
||||
if (path.isEmpty())
|
||||
{
|
||||
addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip, ignore);
|
||||
}
|
||||
else
|
||||
{
|
||||
addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip, ignore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void addFolderToZipAPKTool(String path, String srcFolder, ZipOutputStream zip) throws Exception
|
||||
{
|
||||
|
@ -233,13 +238,9 @@ public final class ZipUtils
|
|||
for (String fileName : Objects.requireNonNull(folder.list()))
|
||||
{
|
||||
if (path.isEmpty())
|
||||
{
|
||||
addFileToZipAPKTool(folder.getName(), srcFolder + "/" + fileName, zip);
|
||||
}
|
||||
else
|
||||
{
|
||||
addFileToZipAPKTool(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,621 @@
|
|||
NONE WHAT THE FUCK BIBL > https://github.com/TheBiblMan/Byte-Engineer-2
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
|
|
@ -1 +1,31 @@
|
|||
http://opensource.org/licenses/BSD-3-Clause
|
||||
Janino - An embedded Java[TM] compiler
|
||||
|
||||
Copyright (c) 2001-2016, Arno Unkrig
|
||||
Copyright (c) 2015-2016 TIBCO Software Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
3. Neither the name of JANINO nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
Loading…
Reference in New Issue
Block a user