Skip to content

Instantly share code, notes, and snippets.

/C4Group.java Secret

Created February 28, 2013 14:13
Show Gist options
  • Save anonymous/7332f966c4f4d5e26d5e to your computer and use it in GitHub Desktop.
Save anonymous/7332f966c4f4d5e26d5e to your computer and use it in GitHub Desktop.
C4Group reader in Java, still needs Packing/Unpacking but has the main magic done
package de.beheh.lorry;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.BitSet;
import java.util.Date;
import java.util.zip.Inflater;
/**
*
* @author benedict
*/
public class C4Group {
/* C4Group Constants */
private static final int C4GROUP_HEADER_LENGTH = 204;
private static final int C4GROUP_VERSION1 = 0x01;
private static final int C4GROUP_VERSION2 = 0x02;
private static final int INFLATE_BUFFER_SIZE = 1024;
/* C4Group Pointer*/
File group;
DataInputStream groupStream;
/* C4GroupHeader Values */
String groupAuthor = null;
int groupChildCount = 0;
int groupCreation = 0;
Date groupModified = null;
boolean groupIsOriginal = false;
/**
*
* @param path
* @throws FileNotFoundException
*/
public C4Group(String path) throws FileNotFoundException {
this(new File(path));
}
/**
*
* @param group
* @throws FileNotFoundException
*/
public C4Group(File group) throws FileNotFoundException {
this.group = group;
groupStream = new DataInputStream(new BufferedInputStream(new FileInputStream(group)));
try {
if(groupStream.read() != 0x1e || groupStream.read() != 0x8c) {
throw new Exception("file is not a c4group");
}
/* Gzip header */
groupStream.read(); //compression method
BitSet flags = ByteConverter.byteToBitSet((byte) groupStream.read()); //flags
groupStream.readInt();
readBytes(groupStream, 1); //xfl
groupStream.readByte(); //os, should be 11 = ntfs for c4groups
/* deflated Body */
Inflater inflater = new Inflater(true);
ByteArrayOutputStream inflatedData = new ByteArrayOutputStream();
while(!inflater.finished()) {
while(inflater.needsInput()) {
byte[] buffer = new byte[INFLATE_BUFFER_SIZE];
groupStream.mark(1024);
groupStream.read(buffer);
inflater.setInput(buffer);
}
byte[] inflatedBuffer = new byte[INFLATE_BUFFER_SIZE];
int length = inflater.inflate(inflatedBuffer);
inflatedData.write(inflatedBuffer, 0, length);
}
int remaining = inflater.getRemaining();
inflater.end();
//FileOutputStream f = new FileOutputStream("/home/benedict/c4group.hex");
//f.write(scramble(inflatedData.toByteArray()));
LittleEndianDataInputStream groupData = new LittleEndianDataInputStream(new ByteArrayInputStream(scramble(inflatedData.toByteArray())));
inflatedData.close();
/* Gzip footer */
groupStream.reset();
groupStream.skip(INFLATE_BUFFER_SIZE - remaining);
//@TODO footer
groupStream.close();
/* C4GroupHeader */
if(!new String(readBytes(groupData, 25)).equals("RedWolf Design GrpFolder ")) {
throw new Exception("invalid c4group version");
}
groupData.skip(3); //reserved
int groupVersion1 = groupData.readLittleEndianInt();
int groupVersion2 = groupData.readLittleEndianInt();
if(groupVersion1 != C4GROUP_VERSION1 || groupVersion2 != C4GROUP_VERSION2) {
throw new Exception("incorrect c4group version (found " + groupVersion1 + "." + groupVersion2 + ", expected " + C4GROUP_VERSION1 + "." + C4GROUP_VERSION2 + ")");
}
groupChildCount = groupData.readLittleEndianInt();
groupAuthor = new String(readBytes(groupData, 32));
groupData.skip(32); //reserved
groupModified = new Date((long) groupData.readLittleEndianInt() * 1000);
groupIsOriginal = (groupData.readLittleEndianInt() == 1234567) ? true : false;
groupData.skip(92); //reserved
/*for(int i = 0; i < groupChildCount; i++) {
System.out.println(new String(readBytes(groupData, 257)));
readBytes(groupData, 59);
}*/
groupData.close();
} catch(Exception ex) {
ex.printStackTrace(System.err);
}
}
/**
* Scrambles the according to the Clonk source code.
*
* @param input the input to scramble
* @return the scrambled bytes
*/
private byte[] scramble(byte[] input) {
int i;
byte tmp;
for(i = 0; i < C4GROUP_HEADER_LENGTH; i++) {
input[i] ^= 237;
}
for(i = 0; (i + 2) < C4GROUP_HEADER_LENGTH; i += 3) {
tmp = input[i];
input[i] = input[i + 2];
input[i + 2] = tmp;
}
return input;
}
public String getAuthor() {
return groupAuthor;
}
public boolean isOriginal() {
return groupIsOriginal;
}
private byte[] readBytes(InputStream read, int length) throws IOException {
byte[] bytes = new byte[length];
for(int i = 0; i < length; i++) {
bytes[i] = (byte) read.read();
}
return bytes;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment