Procyon Decompiler Update

This commit is contained in:
Konloch 2024-10-02 19:16:14 -06:00
parent edd09c0409
commit 1ac293c7b8

AI 샘플 코드 생성 중입니다

Loading...

View File

@ -27,6 +27,7 @@ import com.strobel.decompiler.PlainTextOutput;
import com.strobel.decompiler.languages.java.JavaFormattingOptions; import com.strobel.decompiler.languages.java.JavaFormattingOptions;
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.Constants;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI; import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
import the.bytecode.club.bytecodeviewer.decompilers.AbstractDecompiler; import the.bytecode.club.bytecodeviewer.decompilers.AbstractDecompiler;
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings; import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
@ -42,8 +43,7 @@ import java.util.zip.ZipException;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import static the.bytecode.club.bytecodeviewer.Constants.*; import static the.bytecode.club.bytecodeviewer.Constants.*;
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.ERROR; import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.*;
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.PROCYON;
/** /**
* Procyon Java Decompiler Wrapper * Procyon Java Decompiler Wrapper
@ -51,12 +51,13 @@ import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.PRO
* @author Konloch * @author Konloch
* @author DeathMarine * @author DeathMarine
*/ */
public class ProcyonDecompiler extends AbstractDecompiler public class ProcyonDecompiler extends AbstractDecompiler
{ {
public ProcyonDecompiler() public ProcyonDecompiler()
{ {
super("Procyon Decompiler", "proycon"); super("Procyon Decompiler", "procyon");
} }
@Override @Override
@ -69,34 +70,43 @@ public class ProcyonDecompiler extends AbstractDecompiler
{ {
//create the temporary files //create the temporary files
tempFile = TempFile.createTemporaryFile(false, ".class"); tempFile = TempFile.createTemporaryFile(false, ".class");
File tempClassFile = tempFile.getFile(); File tempInputClassFile = tempFile.getFile();
//write the ClassNode bytes to the temp file //write the ClassNode bytes to the temp file
try (FileOutputStream fos = new FileOutputStream(tempClassFile)) try (FileOutputStream fos = new FileOutputStream(tempInputClassFile))
{ {
fos.write(bytes); fos.write(bytes);
} }
//setup proycon decompiler settings //initialize procyon
DecompilerSettings settings = getDecompilerSettings(); DecompilerSettings settings = getDecompilerSettings();
LuytenTypeLoader typeLoader = new LuytenTypeLoader(); LuytenTypeLoader typeLoader = new LuytenTypeLoader();
MetadataSystem metadataSystem = new MetadataSystem(typeLoader); MetadataSystem metadataSystem = new MetadataSystem(typeLoader);
TypeReference type = metadataSystem.lookupType(tempClassFile.getCanonicalPath());
DecompilationOptions decompilationOptions = new DecompilationOptions(); DecompilationOptions decompilationOptions = new DecompilationOptions();
StringWriter writer = new StringWriter();
//lookup the class-file
TypeReference type = metadataSystem.lookupType(tempInputClassFile.getCanonicalPath());
//configure procyon
decompilationOptions.setSettings(settings); decompilationOptions.setSettings(settings);
decompilationOptions.setFullDecompilation(true); decompilationOptions.setFullDecompilation(true);
//parse class-file
TypeDefinition resolvedType; TypeDefinition resolvedType;
if (type == null || ((resolvedType = type.resolve()) == null)) if (type == null || ((resolvedType = type.resolve()) == null))
throw new Exception("Unable to resolve type."); throw new Exception("Unable to resolve class-filetype.");
StringWriter stringwriter = new StringWriter(); //decompile the class-file
settings.getLanguage().decompileType(resolvedType, new PlainTextOutput(stringwriter), decompilationOptions); settings.getLanguage().decompileType(resolvedType, new PlainTextOutput(writer), decompilationOptions);
return EncodeUtils.unicodeToString(stringwriter.toString()); //handle simulated errors
if(Constants.DEV_FLAG_DECOMPILERS_SIMULATED_ERRORS)
throw new RuntimeException(DEV_MODE_SIMULATED_ERROR.toString());
//return the writer contents
return EncodeUtils.unicodeToString(writer.toString());
} }
catch (Throwable e) catch (Throwable e)
{ {
@ -106,7 +116,7 @@ public class ProcyonDecompiler extends AbstractDecompiler
{ {
//delete all temporary files //delete all temporary files
if(tempFile != null) if(tempFile != null)
tempFile.delete(); tempFile.cleanup();
} }
return PROCYON + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + NL + NL return PROCYON + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + NL + NL
@ -118,7 +128,100 @@ public class ProcyonDecompiler extends AbstractDecompiler
{ {
try try
{ {
doSaveJarDecompiled(new File(sourceJar), new File(zipName)); try (JarFile jarFile = new JarFile(sourceJar);
FileOutputStream destination = new FileOutputStream(zipName);
BufferedOutputStream buffer = new BufferedOutputStream(destination);
ZipOutputStream zip = new ZipOutputStream(buffer))
{
byte[] data = new byte[1024];
//initialize procyon
DecompilerSettings settings = getDecompilerSettings();
LuytenTypeLoader typeLoader = new LuytenTypeLoader();
MetadataSystem metadataSystem = new MetadataSystem(typeLoader);
ITypeLoader jarLoader = new JarTypeLoader(jarFile);
//lookup the jar-file
typeLoader.getTypeLoaders().add(jarLoader);
//configure procyon
DecompilationOptions decompilationOptions = new DecompilationOptions();
decompilationOptions.setSettings(settings);
decompilationOptions.setFullDecompilation(true);
//setup jar output
Enumeration<JarEntry> ent = jarFile.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))
{
zip.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(zip);
settings.getLanguage().decompileType(resolvedType, new PlainTextOutput(writer), decompilationOptions);
writer.flush();
}
finally
{
zip.closeEntry();
}
}
}
else
{
try
{
JarEntry etn = new JarEntry(entry.getName());
if (history.add(etn))
continue;
history.add(etn);
zip.putNextEntry(etn);
try (InputStream in = jarFile.getInputStream(entry))
{
if (in != null)
{
int count;
while ((count = in.read(data, 0, 1024)) != -1)
{
zip.write(data, 0, count);
}
}
}
finally
{
zip.closeEntry();
}
}
catch (ZipException ze)
{
// some jars contain duplicate pom.xml entries: ignore it
if (!ze.getMessage().contains("duplicate"))
throw ze;
}
}
}
}
} }
catch (StackOverflowError | Exception e) catch (StackOverflowError | Exception e)
{ {
@ -126,102 +229,6 @@ public class ProcyonDecompiler extends AbstractDecompiler
} }
} }
/**
* @author DeathMarine
*/
private void doSaveJarDecompiled(File inFile, File outFile) throws Exception
{
try (JarFile jfile = new JarFile(inFile);
FileOutputStream dest = new FileOutputStream(outFile);
BufferedOutputStream buffDest = new BufferedOutputStream(dest);
ZipOutputStream out = new ZipOutputStream(buffDest))
{
byte[] data = new byte[1024];
DecompilerSettings settings = getDecompilerSettings();
LuytenTypeLoader typeLoader = new LuytenTypeLoader();
MetadataSystem metadataSystem = new MetadataSystem(typeLoader);
ITypeLoader jarLoader = new JarTypeLoader(jfile);
typeLoader.getTypeLoaders().add(jarLoader);
DecompilationOptions decompilationOptions = new DecompilationOptions();
decompilationOptions.setSettings(settings);
decompilationOptions.setFullDecompilation(true);
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();
}
finally
{
out.closeEntry();
}
}
}
else
{
try
{
JarEntry etn = new JarEntry(entry.getName());
if (history.add(etn))
continue;
history.add(etn);
out.putNextEntry(etn);
try (InputStream in = jfile.getInputStream(entry))
{
if (in != null)
{
int count;
while ((count = in.read(data, 0, 1024)) != -1)
{
out.write(data, 0, count);
}
}
}
finally
{
out.closeEntry();
}
}
catch (ZipException ze)
{
// some jars contain duplicate pom.xml entries: ignore it
if (!ze.getMessage().contains("duplicate"))
throw ze;
}
}
}
}
}
public DecompilerSettings getDecompilerSettings() public DecompilerSettings getDecompilerSettings()
{ {
DecompilerSettings settings = new DecompilerSettings(); DecompilerSettings settings = new DecompilerSettings();