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 org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Constants;
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
import the.bytecode.club.bytecodeviewer.decompilers.AbstractDecompiler;
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
@ -42,8 +43,7 @@ import java.util.zip.ZipException;
import java.util.zip.ZipOutputStream;
import static the.bytecode.club.bytecodeviewer.Constants.*;
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.ERROR;
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.PROCYON;
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.*;
/**
* Procyon Java Decompiler Wrapper
@ -51,12 +51,13 @@ import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.PRO
* @author Konloch
* @author DeathMarine
*/
public class ProcyonDecompiler extends AbstractDecompiler
{
public ProcyonDecompiler()
{
super("Procyon Decompiler", "proycon");
super("Procyon Decompiler", "procyon");
}
@Override
@ -69,34 +70,43 @@ public class ProcyonDecompiler extends AbstractDecompiler
{
//create the temporary files
tempFile = TempFile.createTemporaryFile(false, ".class");
File tempClassFile = tempFile.getFile();
File tempInputClassFile = tempFile.getFile();
//write the ClassNode bytes to the temp file
try (FileOutputStream fos = new FileOutputStream(tempClassFile))
try (FileOutputStream fos = new FileOutputStream(tempInputClassFile))
{
fos.write(bytes);
}
//setup proycon decompiler settings
//initialize procyon
DecompilerSettings settings = getDecompilerSettings();
LuytenTypeLoader typeLoader = new LuytenTypeLoader();
MetadataSystem metadataSystem = new MetadataSystem(typeLoader);
TypeReference type = metadataSystem.lookupType(tempClassFile.getCanonicalPath());
DecompilationOptions decompilationOptions = new DecompilationOptions();
StringWriter writer = new StringWriter();
//lookup the class-file
TypeReference type = metadataSystem.lookupType(tempInputClassFile.getCanonicalPath());
//configure procyon
decompilationOptions.setSettings(settings);
decompilationOptions.setFullDecompilation(true);
//parse class-file
TypeDefinition resolvedType;
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();
settings.getLanguage().decompileType(resolvedType, new PlainTextOutput(stringwriter), decompilationOptions);
//decompile the class-file
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)
{
@ -106,7 +116,7 @@ public class ProcyonDecompiler extends AbstractDecompiler
{
//delete all temporary files
if(tempFile != null)
tempFile.delete();
tempFile.cleanup();
}
return PROCYON + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + NL + NL
@ -118,7 +128,100 @@ public class ProcyonDecompiler extends AbstractDecompiler
{
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)
{
@ -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()
{
DecompilerSettings settings = new DecompilerSettings();