Initial version

This commit is contained in:
2026-07-04 20:24:40 +02:00
parent 5429339f62
commit b3ae12245b
20 changed files with 1131 additions and 70 deletions
+192
View File
@@ -0,0 +1,192 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
namespace EonaCat.JavaDecompile;
public static class JarProcessor
{
public static List<TreeViewItem> ExtractStructure(string jarPath)
{
using var archive = ZipFile.OpenRead(jarPath);
var root = new TreeViewItem { Header = Path.GetFileName(jarPath), Tag = null, IsExpanded = true };
foreach (var entry in archive.Entries.OrderBy(e => e.FullName))
{
var parts = entry.FullName.Split(new[] { '/' }, System.StringSplitOptions.RemoveEmptyEntries);
TreeViewItem parent = root;
for (int i = 0; i < parts.Length; i++)
{
string part = parts[i];
bool isLast = i == parts.Length - 1;
TreeViewItem? existing = parent.Items.OfType<TreeViewItem>().FirstOrDefault(x => (string)x.Header == part);
if (existing == null)
{
var node = new TreeViewItem { Header = part };
if (isLast && !entry.FullName.EndsWith("/"))
{
node.Tag = entry.FullName;
}
parent.Items.Add(node);
parent = node;
}
else
{
parent = existing;
}
}
}
return new List<TreeViewItem> { root };
}
public static bool IsImage(string path)
{
string[] exts = { ".png", ".jpg", ".jpeg", ".bmp", ".gif", ".ico" };
return exts.Any(e => path.EndsWith(e, System.StringComparison.OrdinalIgnoreCase));
}
public static BitmapImage? ExtractImage(string jarPath, string entryPath)
{
try
{
using var archive = ZipFile.OpenRead(jarPath);
var entry = archive.GetEntry(entryPath);
if (entry == null)
{
return null;
}
using var s = entry.Open();
using var ms = new MemoryStream();
s.CopyTo(ms);
ms.Position = 0;
var img = new BitmapImage();
img.BeginInit();
img.StreamSource = ms;
img.CacheOption = BitmapCacheOption.OnLoad;
img.EndInit();
img.Freeze();
return img;
}
catch
{
return null;
}
}
public static List<TreeViewItem>? ExtractStructureFromInnerJar(string mainJar, string innerJarEntry)
{
try
{
using var outer = ZipFile.OpenRead(mainJar);
var entry = outer.GetEntry(innerJarEntry);
if (entry == null)
{
return null;
}
string temp = Path.Combine(Path.GetTempPath(), "EonaCat.JavaDecompile", Path.GetRandomFileName());
Directory.CreateDirectory(temp);
string innerPath = Path.Combine(temp, Path.GetFileName(innerJarEntry));
using var s = entry.Open();
using var fs = File.Create(innerPath);
s.CopyTo(fs);
fs.Close();
return ExtractStructure(innerPath);
}
catch
{
return null;
}
}
public static string ReadTextFromJar(string jarPath, string entryPath)
{
try
{
using var archive = ZipFile.OpenRead(jarPath);
var entry = archive.GetEntry(entryPath);
if (entry == null)
{
return "// File not found";
}
using var stream = entry.Open();
if (IsBinary(entry.FullName))
{
return $"[{entry.FullName}] Binary file ({entry.Length} bytes)";
}
using var reader = new StreamReader(stream, Encoding.UTF8, true);
return reader.ReadToEnd();
}
catch
{
return "// Error reading file";
}
}
static bool IsBinary(string path)
{
string[] exts = { ".class", ".jar" };
return exts.Any(e => path.EndsWith(e, System.StringComparison.OrdinalIgnoreCase));
}
public static string DecompileClass(string jarPath, string classPath)
{
try
{
string tmp = Path.Combine(Path.GetTempPath(), "EonaCat.JavaDecompile", Path.GetRandomFileName());
Directory.CreateDirectory(tmp);
string cls = Path.Combine(tmp, Path.GetFileName(classPath));
string outDir = Path.Combine(tmp, "out");
Directory.CreateDirectory(outDir);
using (var arc = ZipFile.OpenRead(jarPath))
{
var entry = arc.GetEntry(classPath);
if (entry == null)
{
return "// Class not found";
}
using var s = entry.Open();
using var fs = File.Create(cls);
s.CopyTo(fs);
}
string cfr = Path.Combine(AppContext.BaseDirectory, "assets", "external", "cfr.jar");
if (!File.Exists(cfr))
{
return "// CFR not found";
}
var psi = new ProcessStartInfo
{
FileName = "java",
Arguments = $"-jar \"{cfr}\" \"{cls}\" --outputdir \"{outDir}\"",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
using var p = Process.Start(psi);
p?.WaitForExit();
string baseName = Path.GetFileNameWithoutExtension(classPath);
string f = Directory.GetFiles(outDir, $"{baseName}.java", SearchOption.AllDirectories).FirstOrDefault();
return f != null ? File.ReadAllText(f, Encoding.UTF8) : "// Decompiled file not found";
}
catch
{
return "// Error decompiling class";
}
}
}