Files
UnrealEngineUWP/Engine/Build/Android/Prebuilt/ConfigRulesTool/src/ConfigRulesTool.java
Ryan Durand 28d3d740dd (Integrating from Dev-EngineMerge to Main)
Second batch of remaining Engine copyright updates.

#rnx
#rb none
#jira none

[CL 10871196 by Ryan Durand in Main branch]
2019-12-27 07:44:07 -05:00

290 lines
7.5 KiB
Java

// Copyright Epic Games, Inc. All Rights Reserved.
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class ConfigRulesTool
{
public static void writeInt(FileOutputStream outStream, int value)
{
try
{
outStream.write((value >> 24) & 0xff);
outStream.write((value >> 16) & 0xff);
outStream.write((value >> 8) & 0xff);
outStream.write(value & 0xff);
}
catch (Exception e)
{
}
}
public static SecretKey generateKey(String password)
{
byte[] salt = new byte[] { 0x23, 0x71, (byte)0xd3, (byte)0xa3, 0x30, 0x71, 0x63, (byte)0xe3 };
try
{
SecretKey secret = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(new PBEKeySpec(password.toCharArray(), salt, 1000, 128));
return new SecretKeySpec(secret.getEncoded(), "AES");
}
catch (Exception e)
{
}
return new SecretKeySpec(salt, "AES");
}
public static void main(String[] args)
{
String inFilename = "configrules.txt";
String outFilename = "configrules.bin.png";
String key = "";
int headerSize = 2 + 4 + 4;
if (args.length == 0)
{
System.out.println("ConfigRulesTool v1.0\n");
System.out.println("Usage: [op] inputfile outputfile [key]\n");
System.out.println("\tc = compress and encrypt if key provided");
System.out.println("\td = decrypt and decompress");
System.exit(0);
}
if (args.length > 1)
{
inFilename = args[1];
}
if (args.length > 2)
{
outFilename = args[2];
}
if (args.length > 3)
{
key = args[3];
}
if (args[0].equals("c"))
{
byte[] bytesToCompress = null;
Path path = Paths.get(inFilename);
try
{
bytesToCompress = Files.readAllBytes(path);
}
catch (IOException e)
{
System.out.println("Unable to read file: " + inFilename);
System.exit(-1);
}
int sizeUncompressed = bytesToCompress.length;
int version = -1;
try
{
int versionBytes = sizeUncompressed < 80 ? sizeUncompressed : 80;
String versionLine = new String(bytesToCompress, 0, versionBytes, "UTF-8");
if (versionLine.startsWith("// version:"))
{
int eolIndex = versionLine.indexOf("\r");
int newIndex = versionLine.indexOf("\n");
eolIndex = (eolIndex < 0) ? 1000 : eolIndex;
newIndex = (newIndex < 0) ? 1000 : newIndex;
eolIndex = (eolIndex < newIndex) ? eolIndex : newIndex;
try
{
version = Integer.parseInt(versionLine.substring(11, eolIndex));
}
catch (Exception e)
{
System.out.println("Unable to read version: " + inFilename);
System.exit(-1);
}
}
}
catch (UnsupportedEncodingException e)
{
System.out.println("Unable to read version: " + inFilename);
System.exit(-1);
}
if (version == -1)
{
System.out.println("Unable to read version: " + inFilename);
System.exit(-1);
}
Deflater deflater = new Deflater();
deflater.setInput(bytesToCompress);
deflater.finish();
byte[] bytesCompressed = new byte[sizeUncompressed * 3];
int sizeCompressed = deflater.deflate(bytesCompressed);
// encrypt if key provided
if (!key.equals(""))
{
try
{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, generateKey(key));
byte[] encrypted = cipher.doFinal(bytesCompressed, 0, sizeCompressed);
bytesCompressed = encrypted;
sizeCompressed = bytesCompressed.length;
}
catch (Exception e)
{
System.out.println("Unable to encrypt input file: " + inFilename);
System.out.println(e.toString());
System.exit(-1);
}
}
File outFile = new File(outFilename);
FileOutputStream fileOutStream = null;
try
{
fileOutStream = new FileOutputStream(outFile);
byte[] signature = new byte[2];
signature[0] = (byte)0x39;
signature[1] = (byte)0xd8;
fileOutStream.write(signature);
writeInt(fileOutStream, version);
writeInt(fileOutStream, sizeUncompressed);
fileOutStream.write(bytesCompressed, 0, sizeCompressed);
}
catch (IOException e)
{
System.out.println("Error writing file: " + outFilename);
System.exit(-1);
}
try
{
if (fileOutStream != null)
{
fileOutStream.close();
}
}
catch (IOException e)
{
System.out.println("Error writing file: " + outFilename);
System.exit(-1);
}
System.out.println("Version: " + Integer.toString(version) + ", Compressed from " + Integer.toString(sizeUncompressed) +
" bytes to " + Integer.toString(sizeCompressed + headerSize) + " bytes" + (key.equals("") ? "." : " and encrypted."));
System.exit(0);
}
if (args[0].equals("d"))
{
byte[] bytesToDecompress = null;
Path path = Paths.get(inFilename);
try
{
bytesToDecompress = Files.readAllBytes(path);
}
catch (IOException e)
{
System.out.println("Unable to read file: " + inFilename);
System.exit(-1);
}
int sizeCompressed = bytesToDecompress.length - headerSize;
if (bytesToDecompress.length < headerSize)
{
System.out.println("Input file is invalid: " + inFilename);
System.exit(-1);
}
ByteBuffer buffer = ByteBuffer.wrap(bytesToDecompress);
int signature = buffer.getShort();
if (signature != 0x39d8)
{
System.out.println("Input file signature is invalid: " + inFilename + ", " + Integer.toString(signature));
System.exit(-1);
}
int version = buffer.getInt();
int sizeUncompressed = buffer.getInt();
// decrypt if key provided
if (!key.equals(""))
{
try
{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, generateKey(key));
byte[] decrypted = cipher.doFinal(bytesToDecompress, headerSize, sizeCompressed);
sizeCompressed = decrypted.length;
System.arraycopy(decrypted, 0, bytesToDecompress, headerSize, sizeCompressed);
}
catch (Exception e)
{
System.out.println("Unable to decrypt input file: " + inFilename);
System.out.println(e.toString());
System.exit(-1);
}
}
byte[] bytesDecompressed = new byte[sizeUncompressed];
try
{
Inflater inflater = new Inflater();
inflater.setInput(bytesToDecompress, headerSize, sizeCompressed);
int resultLength = inflater.inflate(bytesDecompressed);
inflater.end();
if (resultLength != sizeUncompressed)
{
System.out.println("Error decompressing (size mismatch) file: " + inFilename);
System.exit(-1);
}
}
catch (Exception e)
{
System.out.println("Error decompressing file: " + inFilename);
System.exit(-1);
}
System.out.println("Version: " + Integer.toString(version) + ", Uncompressed size: " + Integer.toString(sizeUncompressed));
File outFile = new File(outFilename);
FileOutputStream fileOutStream = null;
try
{
fileOutStream = new FileOutputStream(outFile);
fileOutStream.write(bytesDecompressed);
}
catch (IOException e)
{
System.out.println("Error writing file: " + outFilename);
System.exit(-1);
}
try
{
if (fileOutStream != null)
{
fileOutStream.close();
}
}
catch (IOException e)
{
System.out.println("Error writing file: " + outFilename);
System.exit(-1);
}
System.out.println("Wrote file: " + outFilename);
System.exit(0);
}
System.out.println("Unknown op: " + args[0]);
System.exit(-1);
}
}