/*******************************************************************************
* Copyright (c) 2015 Jeff Martin.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public
* License v3.0 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* Contributors:
* Jeff Martin - initial API and implementation
******************************************************************************/
package cuchaz.enigma;
import java.io.File;
import java.io.FileReader;
import java.util.jar.JarFile;
import cuchaz.enigma.Deobfuscator.ProgressListener;
import cuchaz.enigma.mapping.Mappings;
import cuchaz.enigma.mapping.MappingsReader;
public class CommandMain
{
public static class ConsoleProgressListener implements ProgressListener
{
private static final int ReportTime = 5000; // 5s
private int m_totalWork;
private long m_startTime;
private long m_lastReportTime;
@Override
public void init(int totalWork, String title)
{
m_totalWork = totalWork;
m_startTime = System.currentTimeMillis();
m_lastReportTime = m_startTime;
System.out.println(title);
}
@Override
public void onProgress(int numDone, String message)
{
long now = System.currentTimeMillis();
boolean isLastUpdate = numDone == m_totalWork;
boolean shouldReport =
isLastUpdate || now - m_lastReportTime > ReportTime;
if(shouldReport)
{
int percent = numDone * 100 / m_totalWork;
System.out.println(String.format("\tProgress: %3d%%", percent));
m_lastReportTime = now;
}
if(isLastUpdate)
{
double elapsedSeconds = (now - m_startTime) / 1000;
System.out.println(String.format("Finished in %.1f seconds",
elapsedSeconds));
}
}
}
public static void main(String[] args) throws Exception
{
try
{
// process the command
String command = getArg(args, 0, "command", true);
if(command.equalsIgnoreCase("deobfuscate"))
deobfuscate(args);
else if(command.equalsIgnoreCase("decompile"))
decompile(args);
else if(command.equalsIgnoreCase("protectify"))
protectify(args);
else if(command.equalsIgnoreCase("publify"))
publify(args);
else
throw new IllegalArgumentException("Command not recognized: "
+ command);
}catch(IllegalArgumentException ex)
{
System.out.println(ex.getMessage());
printHelp();
}
}
private static void printHelp()
{
System.out.println(String.format("%s - %s", Constants.Name,
Constants.Version));
System.out.println("Usage:");
System.out
.println("\tjava -cp enigma.jar cuchaz.enigma.CommandMain <command>");
System.out.println("\twhere <command> is one of:");
System.out
.println("\t\tdeobfuscate <in jar> <out jar> [<mappings file>]");
System.out
.println("\t\tdecompile <in jar> <out folder> [<mappings file>]");
System.out.println("\t\tprotectify <in jar> <out jar>");
}
private static void decompile(String[] args) throws Exception
{
File fileJarIn = getReadableFile(getArg(args, 1, "in jar", true));
File fileJarOut =
getWritableFolder(getArg(args, 2, "out folder", true));
File fileMappings =
getReadableFile(getArg(args, 3, "mappings file", false));
Deobfuscator deobfuscator =
getDeobfuscator(fileMappings, new JarFile(fileJarIn));
deobfuscator.writeSources(fileJarOut, new ConsoleProgressListener());
}
private static void deobfuscate(String[] args) throws Exception
{
File fileJarIn = getReadableFile(getArg(args, 1, "in jar", true));
File fileJarOut = getWritableFile(getArg(args, 2, "out jar", true));
File fileMappings =
getReadableFile(getArg(args, 3, "mappings file", false));
Deobfuscator deobfuscator =
getDeobfuscator(fileMappings, new JarFile(fileJarIn));
deobfuscator.writeJar(fileJarOut, new ConsoleProgressListener());
}
private static void protectify(String[] args) throws Exception
{
File fileJarIn = getReadableFile(getArg(args, 1, "in jar", true));
File fileJarOut = getWritableFile(getArg(args, 2, "out jar", true));
Deobfuscator deobfuscator =
getDeobfuscator(null, new JarFile(fileJarIn));
deobfuscator.protectifyJar(fileJarOut, new ConsoleProgressListener());
}
private static void publify(String[] args) throws Exception
{
File fileJarIn = getReadableFile(getArg(args, 1, "in jar", true));
File fileJarOut = getWritableFile(getArg(args, 2, "out jar", true));
Deobfuscator deobfuscator =
getDeobfuscator(null, new JarFile(fileJarIn));
deobfuscator.publifyJar(fileJarOut, new ConsoleProgressListener());
}
private static Deobfuscator getDeobfuscator(File fileMappings, JarFile jar)
throws Exception
{
System.out.println("Reading jar...");
Deobfuscator deobfuscator = new Deobfuscator(jar);
if(fileMappings != null)
{
System.out.println("Reading mappings...");
Mappings mappings =
new MappingsReader().read(new FileReader(fileMappings));
deobfuscator.setMappings(mappings);
}
return deobfuscator;
}
private static String getArg(String[] args, int i, String name,
boolean required)
{
if(i >= args.length)
if(required)
throw new IllegalArgumentException(name + " is required");
else
return null;
return args[i];
}
private static File getWritableFile(String path)
{
if(path == null)
return null;
File file = new File(path).getAbsoluteFile();
File dir = file.getParentFile();
if(dir == null || !dir.exists())
throw new IllegalArgumentException("Cannot write to folder: "
+ file);
return file;
}
private static File getWritableFolder(String path)
{
if(path == null)
return null;
File dir = new File(path).getAbsoluteFile();
if(!dir.exists())
throw new IllegalArgumentException("Cannot write to folder: " + dir);
return dir;
}
private static File getReadableFile(String path)
{
if(path == null)
return null;
File file = new File(path).getAbsoluteFile();
if(!file.exists())
throw new IllegalArgumentException("Cannot find file: "
+ file.getAbsolutePath());
return file;
}
}