Autodetect Python CLI

Still a WIP
This commit is contained in:
Konloch 2021-07-12 06:59:26 -07:00
parent 106549658f
commit b81577c6f0
8 changed files with 161 additions and 119 deletions

View file

@ -633,8 +633,6 @@ public class BytecodeViewer
/** /**
* because Smali and Baksmali System.exit if it failed * because Smali and Baksmali System.exit if it failed
*
* @param i
*/ */
public static void exit(int i) { } public static void exit(int i) { }
} }

View file

@ -193,6 +193,8 @@ public class SettingsSerializer
save(BytecodeViewer.viewer.viewPane3.isPaneEditable()); save(BytecodeViewer.viewer.viewPane3.isPaneEditable());
save(Configuration.javaTools); save(Configuration.javaTools);
save(Configuration.python2Extra);
save(Configuration.python3Extra);
} catch (Exception e) { } catch (Exception e) {
BytecodeViewer.handleException(e); BytecodeViewer.handleException(e);
} }
@ -352,6 +354,8 @@ public class SettingsSerializer
BytecodeViewer.viewer.viewPane3.setPaneEditable(asBoolean(133)); BytecodeViewer.viewer.viewPane3.setPaneEditable(asBoolean(133));
Configuration.javaTools = asString(134); Configuration.javaTools = asString(134);
Configuration.python2Extra = asString(135);
Configuration.python3Extra = asString(136);
} catch (Exception e) { } catch (Exception e) {
//ignore because errors are expected, first start up and outdated settings. //ignore because errors are expected, first start up and outdated settings.
e.printStackTrace(); e.printStackTrace();

View file

@ -8,6 +8,7 @@ import java.util.Objects;
import me.konloch.kontainer.io.DiskWriter; import me.konloch.kontainer.io.DiskWriter;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Configuration; import the.bytecode.club.bytecodeviewer.Configuration;
import the.bytecode.club.bytecodeviewer.Constants; import the.bytecode.club.bytecodeviewer.Constants;
@ -46,7 +47,7 @@ public class KrakatauAssembler extends InternalCompiler
@Override @Override
public byte[] compile(String contents, String name) { public byte[] compile(String contents, String name) {
if(!ExternalResources.getSingleton().hasSetPythonCommand()) if(!ExternalResources.getSingleton().hasSetPython2Command())
return null; return null;
String origName = MiscUtils.randomString(20); String origName = MiscUtils.randomString(20);
@ -68,14 +69,19 @@ public class KrakatauAssembler extends InternalCompiler
try try
{ {
BytecodeViewer.sm.pauseBlocking(); BytecodeViewer.sm.pauseBlocking();
ProcessBuilder pb = new ProcessBuilder(
Configuration.python2, String[] pythonCommands = new String[]{Configuration.python2};
if(!Configuration.python2Extra.isEmpty())
pythonCommands = ArrayUtils.addAll(pythonCommands, Configuration.python2Extra);
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
pythonCommands,
"-O", //love you storyyeller <3 "-O", //love you storyyeller <3
krakatauWorkingDirectory + fs + "assemble.py", krakatauWorkingDirectory + fs + "assemble.py",
"-out", "-out",
tempDirectory.getAbsolutePath(), tempDirectory.getAbsolutePath(),
tempJ.getAbsolutePath() tempJ.getAbsolutePath()
); ));
Process process = pb.start(); Process process = pb.start();
BytecodeViewer.createdProcesses.add(process); BytecodeViewer.createdProcesses.add(process);

View file

@ -9,8 +9,8 @@ import java.io.StringWriter;
import java.util.Arrays; import java.util.Arrays;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import me.konloch.kontainer.io.DiskReader; import me.konloch.kontainer.io.DiskReader;
import org.apache.commons.lang3.ArrayUtils;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bootloader.resource.ExternalResource;
import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Configuration; import the.bytecode.club.bytecodeviewer.Configuration;
import the.bytecode.club.bytecodeviewer.Constants; import the.bytecode.club.bytecodeviewer.Constants;
@ -69,7 +69,7 @@ public class KrakatauDecompiler extends InternalDecompiler
public String decompileClassNode(File krakatauTempJar, File krakatauTempDir, ClassNode cn) public String decompileClassNode(File krakatauTempJar, File krakatauTempDir, ClassNode cn)
{ {
if(!ExternalResources.getSingleton().hasSetPythonCommand()) if(!ExternalResources.getSingleton().hasSetPython2Command())
return "You need to set your Python 2.7 path!"; return "You need to set your Python 2.7 path!";
ExternalResources.getSingleton().rtCheck(); ExternalResources.getSingleton().rtCheck();
@ -93,8 +93,13 @@ public class KrakatauDecompiler extends InternalDecompiler
try { try {
BytecodeViewer.sm.pauseBlocking(); BytecodeViewer.sm.pauseBlocking();
ProcessBuilder pb = new ProcessBuilder(
Configuration.python2, String[] pythonCommands = new String[]{Configuration.python2};
if(!Configuration.python2Extra.isEmpty())
pythonCommands = ArrayUtils.addAll(pythonCommands, Configuration.python2Extra);
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
pythonCommands,
"-O", //love you storyyeller <3 "-O", //love you storyyeller <3
krakatauWorkingDirectory + fs + "decompile.py", krakatauWorkingDirectory + fs + "decompile.py",
"-skip", //love you storyyeller <3 "-skip", //love you storyyeller <3
@ -104,7 +109,7 @@ public class KrakatauDecompiler extends InternalDecompiler
"-out", "-out",
krakatauTempDir.getAbsolutePath(), krakatauTempDir.getAbsolutePath(),
cn.name + ".class" cn.name + ".class"
); ));
Process process = pb.start(); Process process = pb.start();
BytecodeViewer.createdProcesses.add(process); BytecodeViewer.createdProcesses.add(process);
@ -149,7 +154,7 @@ public class KrakatauDecompiler extends InternalDecompiler
@Override @Override
public String decompileClassNode(ClassNode cn, byte[] b) { public String decompileClassNode(ClassNode cn, byte[] b) {
if(!ExternalResources.getSingleton().hasSetPythonCommand()) if(!ExternalResources.getSingleton().hasSetPython2Command())
return "You need to set your Python 2.7 path!"; return "You need to set your Python 2.7 path!";
if (Configuration.rt.isEmpty()) { if (Configuration.rt.isEmpty()) {
@ -173,8 +178,13 @@ public class KrakatauDecompiler extends InternalDecompiler
try { try {
BytecodeViewer.sm.pauseBlocking(); BytecodeViewer.sm.pauseBlocking();
ProcessBuilder pb = new ProcessBuilder(
Configuration.python2, String[] pythonCommands = new String[]{Configuration.python2};
if(!Configuration.python2Extra.isEmpty())
pythonCommands = ArrayUtils.addAll(pythonCommands, Configuration.python2Extra);
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
pythonCommands,
"-O", //love you storyyeller <3 "-O", //love you storyyeller <3
krakatauWorkingDirectory + fs + "decompile.py", krakatauWorkingDirectory + fs + "decompile.py",
"-skip", //love you storyyeller <3 "-skip", //love you storyyeller <3
@ -184,7 +194,7 @@ public class KrakatauDecompiler extends InternalDecompiler
"-out", "-out",
tempDirectory.getAbsolutePath(), tempDirectory.getAbsolutePath(),
cn.name + ".class" cn.name + ".class"
); ));
Process process = pb.start(); Process process = pb.start();
BytecodeViewer.createdProcesses.add(process); BytecodeViewer.createdProcesses.add(process);
@ -232,7 +242,7 @@ public class KrakatauDecompiler extends InternalDecompiler
@Override @Override
public void decompileToZip(String sourceJar, String zipName) { public void decompileToZip(String sourceJar, String zipName) {
if(!ExternalResources.getSingleton().hasSetPythonCommand()) if(!ExternalResources.getSingleton().hasSetPython2Command())
return; return;
ExternalResources.getSingleton().rtCheck(); ExternalResources.getSingleton().rtCheck();
@ -250,8 +260,13 @@ public class KrakatauDecompiler extends InternalDecompiler
try { try {
BytecodeViewer.sm.pauseBlocking(); BytecodeViewer.sm.pauseBlocking();
ProcessBuilder pb = new ProcessBuilder(
Configuration.python2, String[] pythonCommands = new String[]{Configuration.python2};
if(!Configuration.python2Extra.isEmpty())
pythonCommands = ArrayUtils.addAll(pythonCommands, Configuration.python2Extra);
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
pythonCommands,
"-O", //love you storyyeller <3 "-O", //love you storyyeller <3
krakatauWorkingDirectory + fs + "decompile.py", krakatauWorkingDirectory + fs + "decompile.py",
"-skip", //love you storyyeller <3 "-skip", //love you storyyeller <3
@ -261,7 +276,7 @@ public class KrakatauDecompiler extends InternalDecompiler
"-out", "-out",
tempDirectory.getAbsolutePath(), tempDirectory.getAbsolutePath(),
tempJar.getAbsolutePath() tempJar.getAbsolutePath()
); ));
Process process = pb.start(); Process process = pb.start();
BytecodeViewer.createdProcesses.add(process); BytecodeViewer.createdProcesses.add(process);

View file

@ -7,6 +7,7 @@ import java.io.InputStreamReader;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import me.konloch.kontainer.io.DiskReader; import me.konloch.kontainer.io.DiskReader;
import org.apache.commons.lang3.ArrayUtils;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Configuration; import the.bytecode.club.bytecodeviewer.Configuration;
@ -48,7 +49,7 @@ public class KrakatauDisassembler extends InternalDecompiler
{ {
@Override @Override
public String decompileClassNode(ClassNode cn, byte[] b) { public String decompileClassNode(ClassNode cn, byte[] b) {
if(!ExternalResources.getSingleton().hasSetPythonCommand()) if(!ExternalResources.getSingleton().hasSetPython2Command())
return "You need to set your Python 2.7 path!"; return "You need to set your Python 2.7 path!";
String s = ExceptionUI.SEND_STACKTRACE_TO_NL; String s = ExceptionUI.SEND_STACKTRACE_TO_NL;
@ -60,8 +61,13 @@ public class KrakatauDisassembler extends InternalDecompiler
try { try {
BytecodeViewer.sm.pauseBlocking(); BytecodeViewer.sm.pauseBlocking();
ProcessBuilder pb = new ProcessBuilder(
Configuration.python2, String[] pythonCommands = new String[]{Configuration.python2};
if(!Configuration.python2Extra.isEmpty())
pythonCommands = ArrayUtils.addAll(pythonCommands, Configuration.python2Extra);
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
pythonCommands,
"-O", //love you storyyeller <3 "-O", //love you storyyeller <3
krakatauWorkingDirectory + fs + "disassemble.py", krakatauWorkingDirectory + fs + "disassemble.py",
"-path", "-path",
@ -69,7 +75,7 @@ public class KrakatauDisassembler extends InternalDecompiler
"-out", "-out",
tempDirectory.getAbsolutePath(), tempDirectory.getAbsolutePath(),
cn.name + ".class" cn.name + ".class"
); ));
Process process = pb.start(); Process process = pb.start();
BytecodeViewer.createdProcesses.add(process); BytecodeViewer.createdProcesses.add(process);
@ -113,7 +119,7 @@ public class KrakatauDisassembler extends InternalDecompiler
@Override @Override
public void decompileToZip(String sourceJar, String zipName) { public void decompileToZip(String sourceJar, String zipName) {
if(!ExternalResources.getSingleton().hasSetPythonCommand()) if(!ExternalResources.getSingleton().hasSetPython2Command())
return; return;
String ran = MiscUtils.randomString(32); String ran = MiscUtils.randomString(32);
@ -124,8 +130,13 @@ public class KrakatauDisassembler extends InternalDecompiler
try { try {
BytecodeViewer.sm.pauseBlocking(); BytecodeViewer.sm.pauseBlocking();
ProcessBuilder pb = new ProcessBuilder(
Configuration.python2, String[] pythonCommands = new String[]{Configuration.python2};
if(!Configuration.python2Extra.isEmpty())
pythonCommands = ArrayUtils.addAll(pythonCommands, Configuration.python2Extra);
ProcessBuilder pb = new ProcessBuilder(ArrayUtils.addAll(
pythonCommands,
"-O", //love you storyyeller <3 "-O", //love you storyyeller <3
krakatauWorkingDirectory + fs + "disassemble.py", krakatauWorkingDirectory + fs + "disassemble.py",
"-path", "-path",
@ -133,7 +144,7 @@ public class KrakatauDisassembler extends InternalDecompiler
"-out", "-out",
tempDirectory.getAbsolutePath(), tempDirectory.getAbsolutePath(),
tempJar.getAbsolutePath() tempJar.getAbsolutePath()
); ));
Process process = pb.start(); Process process = pb.start();
BytecodeViewer.createdProcesses.add(process); BytecodeViewer.createdProcesses.add(process);

View file

@ -34,8 +34,8 @@ public class HTMLPane extends JEditorPane
text = text.replace("{java}", Configuration.java); text = text.replace("{java}", Configuration.java);
text = text.replace("{javac}", Configuration.javac); text = text.replace("{javac}", Configuration.javac);
text = text.replace("{bcvDir}", BCVDir.getAbsolutePath()); text = text.replace("{bcvDir}", BCVDir.getAbsolutePath());
text = text.replace("{python}", Configuration.python2); text = text.replace("{python}", Configuration.python2+" " + Configuration.python2Extra);
text = text.replace("{python3}", Configuration.python3); text = text.replace("{python3}", Configuration.python3 + " " + Configuration.python3Extra);
text = text.replace("{rt}", Configuration.rt); text = text.replace("{rt}", Configuration.rt);
text = text.replace("{lib}", Configuration.library); text = text.replace("{lib}", Configuration.library);
text = text.replace("{krakatauVersion}", krakatauVersion); text = text.replace("{krakatauVersion}", krakatauVersion);

View file

@ -49,36 +49,21 @@ public class ExternalResources
} }
/** /**
* Auto-detect the Java command * Auto-detect Java via command-line
*/ */
public String getJavaCommand(boolean blockTillSelected) public String getJavaCommand(boolean blockTillSelected)
{ {
boolean empty = Configuration.java.isEmpty(); if(!Configuration.java.isEmpty())
if(!empty)
return Configuration.java; return Configuration.java;
try //check CLI for java
{ testCommand(new String[]{"java", "-version"}, "java version", ()->{
BytecodeViewer.sm.pauseBlocking(); Configuration.java = "java";
//read the version output to verify it exists });
ProcessBuilder pb = new ProcessBuilder("java", "-version"); if(!Configuration.java.isEmpty())
Process p = pb.start(); return Configuration.java;
p.waitFor();
if(readProcess(p).toLowerCase().contains("java version"))
{
Configuration.java = "java"; //java is set
return Configuration.java;
}
}
catch (Exception e) { } //ignore
finally
{
BytecodeViewer.sm.resumeBlocking();
}
//TODO auto-detect the Java path //TODO auto-detect the JRE path
boolean block = true; boolean block = true;
while (Configuration.java.isEmpty() && block) while (Configuration.java.isEmpty() && block)
{ {
@ -92,7 +77,7 @@ public class ExternalResources
} }
/** /**
* Check if the python command has been set * Check if java tools has been set
*/ */
public boolean hasJavaToolsSet() public boolean hasJavaToolsSet()
{ {
@ -100,7 +85,7 @@ public class ExternalResources
} }
/** /**
* Auto-detect the Java command * Auto-detect Java tools.jar
*/ */
public String getJavaTools(boolean blockTillSelected) public String getJavaTools(boolean blockTillSelected)
{ {
@ -109,7 +94,7 @@ public class ExternalResources
if(!empty) if(!empty)
return Configuration.javaTools; return Configuration.javaTools;
//TODO auto-detect the Java path //TODO auto-detect the JDK path
boolean block = true; boolean block = true;
while (Configuration.javaTools.isEmpty() && block) while (Configuration.javaTools.isEmpty() && block)
{ {
@ -123,75 +108,44 @@ public class ExternalResources
} }
/** /**
* Check if the python command has been set * Check if the python 2 command has been set
*/ */
public boolean hasSetPythonCommand() public boolean hasSetPython2Command()
{ {
return !getPythonCommand(false).isEmpty(); return !getPython2Command(false).isEmpty();
} }
/** /**
* Auto-detect the Java command * Auto-detect python 2 via command-line
*/ */
public String getPythonCommand(boolean blockTillSelected) public String getPython2Command(boolean blockTillSelected)
{ {
boolean empty = Configuration.java.isEmpty(); if(!Configuration.python2.isEmpty())
return Configuration.python2;
if(!empty)
return Configuration.java;
//check using python CLI flag //check using python CLI flag
try testCommand(new String[]{"python", "-2", "--version"}, "python 2", ()->{
{ Configuration.python2 = "python";
BytecodeViewer.sm.pauseBlocking(); Configuration.python2Extra = "-2";
});
//read the version output to verify python 2 if(!Configuration.python2.isEmpty())
ProcessBuilder pb = new ProcessBuilder("python", "-2", "--version"); return Configuration.python2;
Process p = pb.start();
p.waitFor();
//set python path
if(readProcess(p).toLowerCase().contains("python 2"))
{
Configuration.python2 = "python";
Configuration.python2Extra = "-2";
return Configuration.python2;
}
}
catch (Exception e) { } //ignore
finally
{
BytecodeViewer.sm.resumeBlocking();
}
//check if 'python' command is bound as python 2.X //check if 'python' command is bound as python 2.X
try testCommand(new String[]{"python", "--version"}, "python 2", ()->{
{ Configuration.python2 = "python";
BytecodeViewer.sm.pauseBlocking(); });
if(!Configuration.python2.isEmpty())
//read the version output to verify python 2 return Configuration.python2;
ProcessBuilder pb = new ProcessBuilder("python", "--version");
Process p = pb.start();
p.waitFor();
//set python path
if(readProcess(p).toLowerCase().contains("python 2"))
{
Configuration.python2 = "python";
return Configuration.python2;
}
}
catch (Exception e) { } //ignore
finally
{
BytecodeViewer.sm.resumeBlocking();
}
//TODO auto-detect the Python path
//TODO auto-detect the Python path (C:/Program Files/Python)
boolean block = true; boolean block = true;
while (Configuration.python2.isEmpty() && block) while (Configuration.python2.isEmpty() && block)
{ {
BytecodeViewer.showMessage("You need to set your Python (or PyPy for speed) 2.7 executable path."); BytecodeViewer.showMessage("You need to set your Python 2.7 (or PyPy 2.7 for speed) executable path.");
selectPython2(); selectPython2();
block = !blockTillSelected; //signal block flag off block = !blockTillSelected; //signal block flag off
} }
@ -199,6 +153,39 @@ public class ExternalResources
return Configuration.python2; return Configuration.python2;
} }
/**
* Check if the python 3 command has been set
*/
public boolean hasSetPython3Command()
{
return !getPython3Command(false).isEmpty();
}
/**
* Auto-detect python 3 via command-line
*/
public String getPython3Command(boolean blockTillSelected)
{
//check if 'python' command is bound as python 2.X
testCommand(new String[]{"python", "--version"}, "python 3", ()->{
Configuration.python3 = "python";
});
if(!Configuration.python3.isEmpty())
return Configuration.python3;
//TODO auto-detect the Python path (C:/Program Files/Python)
boolean block = true;
while (Configuration.python3.isEmpty() && block)
{
BytecodeViewer.showMessage("You need to set your Python 3.x (or PyPy 3.x for speed) executable path.");
selectPython3();
block = !blockTillSelected; //signal block flag off
}
return Configuration.python3;
}
//rt.jar check //rt.jar check
public synchronized void rtCheck() public synchronized void rtCheck()
{ {
@ -220,7 +207,7 @@ public class ExternalResources
public void selectPython2() public void selectPython2()
{ {
final File file = DialogueUtils.fileChooser("Select Python 2.7 Executable", final File file = DialogueUtils.fileChooser("Select Python 2.7 Executable",
"Python (Or PyPy for speed) 2.7 Executable", "Python 2.7 (Or PyPy 2.7 for speed) Executable",
"everything"); "everything");
if(file == null) if(file == null)
@ -233,7 +220,7 @@ public class ExternalResources
public void selectPython3() public void selectPython3()
{ {
final File file = DialogueUtils.fileChooser("Select Python 3.x Executable", final File file = DialogueUtils.fileChooser("Select Python 3.x Executable",
"Python (Or PyPy for speed) 3.x Executable", "Python 3.x (Or PyPy 3.x for speed) Executable",
"everything"); "everything");
if(file == null) if(file == null)
@ -344,6 +331,33 @@ public class ExternalResources
return null; return null;
} }
/**
* Used to test the command-line for compatibility
*/
public void testCommand(String[] command, String matchingText, Runnable onMatch)
{
try
{
BytecodeViewer.sm.pauseBlocking();
//read the version output
ProcessBuilder pb = new ProcessBuilder(command);
Process p = pb.start();
p.waitFor();
//check for matching text
if(readProcess(p).toLowerCase().contains(matchingText))
{
onMatch.run();
}
}
catch (Exception e) { } //ignore
finally
{
BytecodeViewer.sm.resumeBlocking();
}
}
/** /**
* @author https://stackoverflow.com/a/16714180 * @author https://stackoverflow.com/a/16714180
*/ */
@ -352,6 +366,7 @@ public class ExternalResources
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
String line; String line;
while ((line = reader.readLine()) != null) while ((line = reader.readLine()) != null)
{ {
builder.append(line); builder.append(line);

View file

@ -40,15 +40,8 @@ public class Enjarify {
* @param output the output .jar file * @param output the output .jar file
*/ */
public static synchronized void apk2Jar(File input, File output) { public static synchronized void apk2Jar(File input, File output) {
if (Configuration.python3.isEmpty()) { if(!ExternalResources.getSingleton().hasSetPython3Command())
BytecodeViewer.showMessage("You need to set your Python (or PyPy for speed) 3.x executable path.");
ExternalResources.getSingleton().selectPython3();
}
if (Configuration.python3.isEmpty()) {
BytecodeViewer.showMessage("You need to set Python!");
return; return;
}
try { try {
BytecodeViewer.sm.pauseBlocking(); BytecodeViewer.sm.pauseBlocking();