Cleaned up some core files
This commit is contained in:
+1
-1
@@ -145,7 +145,7 @@ public final class Cache {
|
||||
buffer.putInt(0);
|
||||
continue;
|
||||
}
|
||||
buffer.putInt(cacheFileManagers[index].getInformation().getInformationContainer().getCrc());
|
||||
buffer.putInt(cacheFileManagers[index].getInformation().informationContainer.getCrc());
|
||||
buffer.putInt(cacheFileManagers[index].getInformation().getRevision());
|
||||
}
|
||||
return buffer.array();
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ public final class CacheFile {
|
||||
return null;
|
||||
}
|
||||
if (xteaKeys != null && (xteaKeys[0] != 0 || xteaKeys[1] != 0 || xteaKeys[2] != 0 || xteaKeys[3] != 0)) {
|
||||
packedData = XTEACryption.decrypt(xteaKeys, ByteBuffer.wrap(packedData), 5, packedData.length).array();
|
||||
packedData = XTEACryption.Companion.decrypt(xteaKeys, ByteBuffer.wrap(packedData), 5, packedData.length).array();
|
||||
}
|
||||
return ContainersInformation.unpackCacheContainer(packedData);
|
||||
}
|
||||
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
package core.cache;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Represents a file used in the server store.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class StoreFile {
|
||||
|
||||
/**
|
||||
* If the data can change during server runtime.
|
||||
*/
|
||||
private boolean dynamic;
|
||||
|
||||
/**
|
||||
* The file data.
|
||||
*/
|
||||
private byte[] data;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code StoreFile} {@code Object}.
|
||||
*/
|
||||
public StoreFile() {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the data on the buffer.
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
public void put(ByteBuffer buffer) {
|
||||
byte[] data = new byte[buffer.remaining()];
|
||||
buffer.get(data);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a byte buffer containing the file data.
|
||||
* @return The buffer.
|
||||
*/
|
||||
public ByteBuffer data() {
|
||||
return ByteBuffer.wrap(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data.
|
||||
* @param data The data.
|
||||
*/
|
||||
public void setData(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dynamic.
|
||||
* @return The dynamic.
|
||||
*/
|
||||
public boolean isDynamic() {
|
||||
return dynamic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dynamic.
|
||||
* @param dynamic The dynamic to set.
|
||||
*/
|
||||
public void setDynamic(boolean dynamic) {
|
||||
this.dynamic = dynamic;
|
||||
}
|
||||
|
||||
}
|
||||
-271
@@ -1,271 +0,0 @@
|
||||
package core.cache.crypto;
|
||||
|
||||
/**
|
||||
* <p> An implementation of an ISAAC cipher. See <a
|
||||
* href="http://en.wikipedia.org/wiki/ISAAC_(cipher)">
|
||||
* http://en.wikipedia.org/wiki/ISAAC_(cipher)</a> for more information. </p>
|
||||
* <p> This implementation is based on the one written by Bob Jenkins, which is
|
||||
* available at <a href="http://www.burtleburtle.net/bob/java/rand/Rand.java">
|
||||
* http://www.burtleburtle.net/bob/java/rand/Rand.java</a>. </p>
|
||||
* @author Graham Edgecombe
|
||||
*/
|
||||
public class ISAACCipher {
|
||||
|
||||
/**
|
||||
* The golden ratio.
|
||||
*/
|
||||
public static final int RATIO = 0x9e3779b9;
|
||||
|
||||
/**
|
||||
* The log of the size of the results and memory arrays.
|
||||
*/
|
||||
public static final int SIZE_LOG = 8;
|
||||
|
||||
/**
|
||||
* The size of the results and memory arrays.
|
||||
*/
|
||||
public static final int SIZE = 1 << SIZE_LOG;
|
||||
|
||||
/**
|
||||
* For pseudorandom lookup.
|
||||
*/
|
||||
public static final int MASK = (SIZE - 1) << 2;
|
||||
|
||||
/**
|
||||
* The count through the results.
|
||||
*/
|
||||
private int count = 0;
|
||||
|
||||
/**
|
||||
* The results.
|
||||
*/
|
||||
private int results[] = new int[SIZE];
|
||||
|
||||
/**
|
||||
* The internal memory state.
|
||||
*/
|
||||
private int memory[] = new int[SIZE];
|
||||
|
||||
/**
|
||||
* The accumulator.
|
||||
*/
|
||||
private int a;
|
||||
|
||||
/**
|
||||
* The last result.
|
||||
*/
|
||||
private int b;
|
||||
|
||||
/**
|
||||
* The counter.
|
||||
*/
|
||||
private int c;
|
||||
|
||||
/**
|
||||
* Creates the ISAAC cipher.
|
||||
* @param seed The seed.
|
||||
*/
|
||||
public ISAACCipher(int[] seed) {
|
||||
for (int i = 0; i < seed.length; i++) {
|
||||
results[i] = seed[i];
|
||||
}
|
||||
init(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next value.
|
||||
* @return The next value.
|
||||
*/
|
||||
public int getNextValue() {
|
||||
if (count-- == 0) {
|
||||
isaac();
|
||||
count = SIZE - 1;
|
||||
}
|
||||
return 0;//results[count];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates 256 results.
|
||||
*/
|
||||
public void isaac() {
|
||||
int i, j, x, y;
|
||||
b += ++c;
|
||||
for (i = 0, j = SIZE / 2; i < SIZE / 2;) {
|
||||
x = memory[i];
|
||||
a ^= a << 13;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a >>> 6;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a << 2;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a >>> 16;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
}
|
||||
for (j = 0; j < SIZE / 2;) {
|
||||
x = memory[i];
|
||||
a ^= a << 13;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a >>> 6;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a << 2;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
|
||||
x = memory[i];
|
||||
a ^= a >>> 16;
|
||||
a += memory[j++];
|
||||
memory[i] = y = memory[(x & MASK) >> 2] + a + b;
|
||||
results[i++] = b = memory[((y >> SIZE_LOG) & MASK) >> 2] + x;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the ISAAC.
|
||||
* @param flag Flag indicating if we should perform a second pass.
|
||||
*/
|
||||
public void init(boolean flag) {
|
||||
int i;
|
||||
int a, b, c, d, e, f, g, h;
|
||||
a = b = c = d = e = f = g = h = RATIO;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
b ^= c >>> 2;
|
||||
e += b;
|
||||
c += d;
|
||||
c ^= d << 8;
|
||||
f += c;
|
||||
d += e;
|
||||
d ^= e >>> 16;
|
||||
g += d;
|
||||
e += f;
|
||||
e ^= f << 10;
|
||||
h += e;
|
||||
f += g;
|
||||
f ^= g >>> 4;
|
||||
a += f;
|
||||
g += h;
|
||||
g ^= h << 8;
|
||||
b += g;
|
||||
h += a;
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
}
|
||||
for (i = 0; i < SIZE; i += 8) {
|
||||
if (flag) {
|
||||
a += results[i];
|
||||
b += results[i + 1];
|
||||
c += results[i + 2];
|
||||
d += results[i + 3];
|
||||
e += results[i + 4];
|
||||
f += results[i + 5];
|
||||
g += results[i + 6];
|
||||
h += results[i + 7];
|
||||
}
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
b ^= c >>> 2;
|
||||
e += b;
|
||||
c += d;
|
||||
c ^= d << 8;
|
||||
f += c;
|
||||
d += e;
|
||||
d ^= e >>> 16;
|
||||
g += d;
|
||||
e += f;
|
||||
e ^= f << 10;
|
||||
h += e;
|
||||
f += g;
|
||||
f ^= g >>> 4;
|
||||
a += f;
|
||||
g += h;
|
||||
g ^= h << 8;
|
||||
b += g;
|
||||
h += a;
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
memory[i] = a;
|
||||
memory[i + 1] = b;
|
||||
memory[i + 2] = c;
|
||||
memory[i + 3] = d;
|
||||
memory[i + 4] = e;
|
||||
memory[i + 5] = f;
|
||||
memory[i + 6] = g;
|
||||
memory[i + 7] = h;
|
||||
}
|
||||
if (flag) {
|
||||
for (i = 0; i < SIZE; i += 8) {
|
||||
a += memory[i];
|
||||
b += memory[i + 1];
|
||||
c += memory[i + 2];
|
||||
d += memory[i + 3];
|
||||
e += memory[i + 4];
|
||||
f += memory[i + 5];
|
||||
g += memory[i + 6];
|
||||
h += memory[i + 7];
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
b ^= c >>> 2;
|
||||
e += b;
|
||||
c += d;
|
||||
c ^= d << 8;
|
||||
f += c;
|
||||
d += e;
|
||||
d ^= e >>> 16;
|
||||
g += d;
|
||||
e += f;
|
||||
e ^= f << 10;
|
||||
h += e;
|
||||
f += g;
|
||||
f ^= g >>> 4;
|
||||
a += f;
|
||||
g += h;
|
||||
g ^= h << 8;
|
||||
b += g;
|
||||
h += a;
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
memory[i] = a;
|
||||
memory[i + 1] = b;
|
||||
memory[i + 2] = c;
|
||||
memory[i + 3] = d;
|
||||
memory[i + 4] = e;
|
||||
memory[i + 5] = f;
|
||||
memory[i + 6] = g;
|
||||
memory[i + 7] = h;
|
||||
}
|
||||
}
|
||||
isaac();
|
||||
count = SIZE;
|
||||
}
|
||||
|
||||
}
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
package core.cache.crypto
|
||||
|
||||
/**
|
||||
* An implementation of an ISAAC cipher.
|
||||
* See [http://en.wikipedia.org/wiki/ISAAC_(cipher)](http://en.wikipedia.org/wiki/ISAAC_(cipher)) for more information.
|
||||
* Based on the one written by Bob Jenkins, which is available at
|
||||
* [http://www.burtleburtle.net/bob/java/rand/Rand.java](http://www.burtleburtle.net/bob/java/rand/Rand.java).
|
||||
*/
|
||||
class ISAACCipher(seed: IntArray) {
|
||||
companion object {
|
||||
/** Golden ratio in 32 bit unsigned int. */
|
||||
const val RATIO = -0x61c88647
|
||||
/** The base 2 log of the size of the results and memory arrays. */
|
||||
const val SIZE_LOG = 8
|
||||
/** The size of the results and memory arrays. */
|
||||
const val SIZE = 1 shl SIZE_LOG
|
||||
/** For pseudorandom lookup. */
|
||||
const val MASK = SIZE - 1 shl 2
|
||||
}
|
||||
/** The count through the results. */
|
||||
private var count = 0
|
||||
/** The results. */
|
||||
private val results = IntArray(SIZE)
|
||||
/** The internal memory state. */
|
||||
private val memory = IntArray(SIZE)
|
||||
/** The accumulator. */
|
||||
private var a = 0
|
||||
/** The last result. */
|
||||
private var b = 0
|
||||
/** The counter. */
|
||||
private var c = 0
|
||||
|
||||
/**
|
||||
* Creates the ISAAC cipher.
|
||||
* @param seed The seed.
|
||||
*/
|
||||
init {
|
||||
for (i in seed.indices) {
|
||||
results[i] = seed[i]
|
||||
}
|
||||
init(true)
|
||||
}
|
||||
|
||||
val nextValue: Int
|
||||
/**
|
||||
* Gets the next value.
|
||||
* @return The next value.
|
||||
*/
|
||||
get() {
|
||||
if (count-- == 0) {
|
||||
isaac()
|
||||
count = SIZE - 1
|
||||
}
|
||||
return 0 //results[count];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates 256 results.
|
||||
*/
|
||||
fun isaac() {
|
||||
var i: Int
|
||||
var j: Int
|
||||
var x: Int
|
||||
var y: Int
|
||||
b += ++c
|
||||
i = 0
|
||||
j = SIZE / 2
|
||||
while (i < SIZE / 2) {
|
||||
x = memory[i]
|
||||
a = a xor (a shl 13)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a ushr 6)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a shl 2)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a ushr 16)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
}
|
||||
j = 0
|
||||
while (j < SIZE / 2) {
|
||||
x = memory[i]
|
||||
a = a xor (a shl 13)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a ushr 6)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a shl 2)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
x = memory[i]
|
||||
a = a xor (a ushr 16)
|
||||
a += memory[j++]
|
||||
y = memory[x and MASK shr 2] + a + b
|
||||
memory[i] = y
|
||||
b = memory[y shr SIZE_LOG and MASK shr 2] + x
|
||||
results[i++] = b
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the ISAAC.
|
||||
* @param flag Flag indicating if we should perform a second pass.
|
||||
*/
|
||||
fun init(flag: Boolean) {
|
||||
var a = RATIO
|
||||
var b = a; var c = b; var d = c; var e = d; var f = e; var g = f; var h = g
|
||||
var i = 0
|
||||
while (i < 4) {
|
||||
a = a xor (b shl 11); d += a; b += c
|
||||
b = b xor (c ushr 2); e += b; c += d
|
||||
c = c xor (d shl 8); f += c; d += e
|
||||
d = d xor (e ushr 16); g += d; e += f
|
||||
e = e xor (f shl 10); h += e; f += g
|
||||
f = f xor (g ushr 4); a += f; g += h
|
||||
g = g xor (h shl 8); b += g; h += a
|
||||
h = h xor (a ushr 9); c += h; a += b
|
||||
++i
|
||||
}
|
||||
i = 0
|
||||
while (i < SIZE) {
|
||||
if (flag) {
|
||||
a += results[i]
|
||||
b += results[i + 1]
|
||||
c += results[i + 2]
|
||||
d += results[i + 3]
|
||||
e += results[i + 4]
|
||||
f += results[i + 5]
|
||||
g += results[i + 6]
|
||||
h += results[i + 7]
|
||||
}
|
||||
a = a xor (b shl 11); d += a; b += c
|
||||
b = b xor (c ushr 2); e += b; c += d
|
||||
c = c xor (d shl 8); f += c; d += e
|
||||
d = d xor (e ushr 16); g += d; e += f
|
||||
e = e xor (f shl 10); h += e; f += g
|
||||
f = f xor (g ushr 4); a += f; g += h
|
||||
g = g xor (h shl 8); b += g; h += a
|
||||
h = h xor (a ushr 9); c += h; a += b
|
||||
memory[i] = a
|
||||
memory[i + 1] = b
|
||||
memory[i + 2] = c
|
||||
memory[i + 3] = d
|
||||
memory[i + 4] = e
|
||||
memory[i + 5] = f
|
||||
memory[i + 6] = g
|
||||
memory[i + 7] = h
|
||||
i += 8
|
||||
}
|
||||
if (flag) {
|
||||
i = 0
|
||||
while (i < SIZE) {
|
||||
a += memory[i]
|
||||
b += memory[i + 1]
|
||||
c += memory[i + 2]
|
||||
d += memory[i + 3]
|
||||
e += memory[i + 4]
|
||||
f += memory[i + 5]
|
||||
g += memory[i + 6]
|
||||
h += memory[i + 7]
|
||||
a = a xor (b shl 11); d += a; b += c
|
||||
b = b xor (c ushr 2); e += b; c += d
|
||||
c = c xor (d shl 8); f += c; d += e
|
||||
d = d xor (e ushr 16); g += d; e += f
|
||||
e = e xor (f shl 10); h += e; f += g
|
||||
f = f xor (g ushr 4); a += f; g += h
|
||||
g = g xor (h shl 8); b += g; h += a
|
||||
h = h xor (a ushr 9); c += h; a += b
|
||||
memory[i] = a
|
||||
memory[i + 1] = b
|
||||
memory[i + 2] = c
|
||||
memory[i + 3] = d
|
||||
memory[i + 4] = e
|
||||
memory[i + 5] = f
|
||||
memory[i + 6] = g
|
||||
memory[i + 7] = h
|
||||
i += 8
|
||||
}
|
||||
}
|
||||
isaac()
|
||||
count = SIZE
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package core.cache.crypto;
|
||||
|
||||
/**
|
||||
* Represents a ISAAC key pair, for both input and output.
|
||||
* @author `Discardedx2
|
||||
*/
|
||||
public final class ISAACPair {
|
||||
|
||||
/**
|
||||
* The input cipher.
|
||||
*/
|
||||
private ISAACCipher input;
|
||||
|
||||
/**
|
||||
* The output cipher.
|
||||
*/
|
||||
private ISAACCipher output;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ISAACPair} {@code Object}.
|
||||
* @param input The input cipher.
|
||||
* @param output The output cipher.
|
||||
*/
|
||||
public ISAACPair(ISAACCipher input, ISAACCipher output) {
|
||||
this.input = input;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input cipher.
|
||||
* @return The input cipher.
|
||||
*/
|
||||
public ISAACCipher getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the output cipher.
|
||||
* @return The output cipher.
|
||||
*/
|
||||
public ISAACCipher getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package core.cache.crypto
|
||||
|
||||
/**
|
||||
* Represents a ISAAC key pair, for both input and output.
|
||||
*/
|
||||
class ISAACPair(
|
||||
val input: ISAACCipher,
|
||||
val output: ISAACCipher
|
||||
)
|
||||
-124
@@ -1,124 +0,0 @@
|
||||
package core.cache.crypto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Holds XTEA cryption methods.
|
||||
* @author ?
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class XTEACryption {
|
||||
|
||||
/**
|
||||
* The delta value
|
||||
*/
|
||||
private static final int DELTA = -1640531527;
|
||||
|
||||
/**
|
||||
* The sum.
|
||||
*/
|
||||
private static final int SUM = -957401312;
|
||||
|
||||
/**
|
||||
* The amount of "cryption cycles".
|
||||
*/
|
||||
private static final int NUM_ROUNDS = 32;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code XTEACryption}.
|
||||
*/
|
||||
private XTEACryption() {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the contents of the buffer.
|
||||
* @param keys The cryption keys.
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
public static ByteBuffer decrypt(int[] keys, ByteBuffer buffer) {
|
||||
return decrypt(keys, buffer, buffer.position(), buffer.limit());
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the buffer data.
|
||||
* @param keys The keys.
|
||||
* @param buffer The buffer to decrypt.
|
||||
* @param offset The offset of the data to decrypt.
|
||||
* @param length The length.
|
||||
* @return The decrypted data.
|
||||
*/
|
||||
public static ByteBuffer decrypt(int[] keys, ByteBuffer buffer, int offset, int length) {
|
||||
int numBlocks = (length - offset) / 8;
|
||||
int[] block = new int[2];
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
int index = i * 8 + offset;
|
||||
block[0] = buffer.getInt(index);
|
||||
block[1] = buffer.getInt(index + 4);
|
||||
decipher(keys, block);
|
||||
buffer.putInt(index, block[0]);
|
||||
buffer.putInt(index + 4, block[1]);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deciphers the values.
|
||||
* @param keys The cryption key.
|
||||
* @param block The values to decipher.
|
||||
*/
|
||||
private static void decipher(int[] keys, int[] block) {
|
||||
long sum = SUM;
|
||||
for (int i = 0; i < NUM_ROUNDS; i++) {
|
||||
block[1] -= (keys[(int) ((sum & 0x1933) >>> 11)] + sum ^ block[0] + (block[0] << 4 ^ block[0] >>> 5));
|
||||
sum -= DELTA;
|
||||
block[0] -= ((block[1] << 4 ^ block[1] >>> 5) + block[1] ^ keys[(int) (sum & 0x3)] + sum);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the contents of the byte buffer.
|
||||
* @param keys The cryption keys.
|
||||
* @param buffer The buffer to encrypt.
|
||||
*/
|
||||
public static void encrypt(int[] keys, ByteBuffer buffer) {
|
||||
encrypt(keys, buffer, buffer.position(), buffer.limit());
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the buffer data.
|
||||
* @param keys The keys.
|
||||
* @param buffer The buffer to encrypt.
|
||||
* @param offset The offset of the data to encrypt.
|
||||
* @param length The length.
|
||||
* @return The encrypted data.
|
||||
*/
|
||||
public static void encrypt(int[] keys, ByteBuffer buffer, int offset, int length) {
|
||||
int numBlocks = (length - offset) / 8;
|
||||
int[] block = new int[2];
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
int index = i * 8 + offset;
|
||||
block[0] = buffer.getInt(index);
|
||||
block[1] = buffer.getInt(index + 4);
|
||||
encipher(keys, block);
|
||||
buffer.putInt(index, block[0]);
|
||||
buffer.putInt(index + 4, block[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enciphers the values of the block.
|
||||
* @param keys The cryption keys.
|
||||
* @param block The block to encipher.
|
||||
*/
|
||||
private static void encipher(int[] keys, int[] block) {
|
||||
long sum = 0;
|
||||
for (int i = 0; i < NUM_ROUNDS; i++) {
|
||||
block[0] += ((block[1] << 4 ^ block[1] >>> 5) + block[1] ^ keys[(int) (sum & 0x3)] + sum);
|
||||
sum += DELTA;
|
||||
block[1] += (keys[(int) ((sum & 0x1933) >>> 11)] + sum ^ block[0] + (block[0] << 4 ^ block[0] >>> 5));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package core.cache.crypto
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
/** Holds XTEA(eXtended Tiny Encryption Algorithm) encryption/decryption methods. Usually used for RS Map decryption. */
|
||||
class XTEACryption {
|
||||
companion object {
|
||||
// Purely Static Class
|
||||
// XTEA consts https://scispace.com/pdf/xtea-cryptography-implementation-in-android-chatting-app-3pg6ownewx.pdf
|
||||
/** Fibonacci hashing. Math.pow(2,32) * Math.sqrt(5)-1)/2 => 32 bits(int) multiply by reciprocal of golden ratio. */
|
||||
private const val DELTA = -1640531527 // Formula cast to unsigned int.
|
||||
/** DELTA << 5. Essentially multiply DELTA by NUM_ROUNDS or number of rounds. */
|
||||
private const val SUM = -957401312 // 0xC6EF3720
|
||||
/** The amount of "cryption cycles". */
|
||||
private const val NUM_ROUNDS = 32
|
||||
/** Constant to manipulate the key index in decipher/encrypt. This was a magic number randomly selected by RS. */
|
||||
private const val KEY_SCRAMBLE = 0x1933
|
||||
|
||||
/**
|
||||
* Decrypts the buffer data.
|
||||
* @param keys The keys.
|
||||
* @param buffer The buffer to decrypt.
|
||||
* @param offset The offset of the data to decrypt.
|
||||
* @param length The length.
|
||||
* @return The decrypted data.
|
||||
*/
|
||||
fun decrypt(keys: IntArray, buffer: ByteBuffer, offset: Int, length: Int): ByteBuffer {
|
||||
val numBlocks = (length - offset) / 8
|
||||
val block = IntArray(2)
|
||||
for (i in 0 until numBlocks) {
|
||||
val index = i * 8 + offset
|
||||
block[0] = buffer.getInt(index)
|
||||
block[1] = buffer.getInt(index + 4)
|
||||
decipher(keys, block)
|
||||
buffer.putInt(index, block[0])
|
||||
buffer.putInt(index + 4, block[1])
|
||||
}
|
||||
return buffer
|
||||
}
|
||||
|
||||
/**
|
||||
* Deciphers the values of the block using the Tiny Encryption Algorithm (TEA).
|
||||
* This algorithm relies on a Feistel network, using bitwise operations and
|
||||
* modular subtraction to remove confusion(block[0] line) and diffusion(block[1] line).
|
||||
*
|
||||
* @param keys 128-bit key (4x32-bit int).
|
||||
* @param block 64-bit data block (2x32-bit int) to be decrypted.
|
||||
*/
|
||||
private fun decipher(keys: IntArray, block: IntArray) {
|
||||
var sum =
|
||||
SUM.toLong() // Running decreasing sum to ensure different round constants - should become 0 at the end.
|
||||
for (i in 0 until NUM_ROUNDS) {
|
||||
block[1] -= (keys[(sum and KEY_SCRAMBLE.toLong() ushr 11).toInt()] + sum xor (block[0] + (block[0] shl 4 xor (block[0] ushr 5))).toLong()).toInt()
|
||||
sum -= DELTA.toLong()
|
||||
block[0] -= (((block[1] shl 4 xor (block[1] ushr 5)) + block[1]).toLong() xor keys[(sum and 0x3L).toInt()] + sum).toInt()
|
||||
}
|
||||
}
|
||||
/** === Encryption functions below are not used unless you are modifying the cache. === */
|
||||
/**
|
||||
* Encrypts the buffer data.
|
||||
* @param keys The keys.
|
||||
* @param buffer The buffer to encrypt.
|
||||
* @param offset The offset of the data to encrypt.
|
||||
* @param length The length.
|
||||
* @return The encrypted data.
|
||||
*/
|
||||
fun encrypt(keys: IntArray, buffer: ByteBuffer, offset: Int, length: Int) {
|
||||
val numBlocks = (length - offset) / 8
|
||||
val block = IntArray(2)
|
||||
for (i in 0 until numBlocks) {
|
||||
val index = i * 8 + offset
|
||||
block[0] = buffer.getInt(index)
|
||||
block[1] = buffer.getInt(index + 4)
|
||||
encipher(keys, block)
|
||||
buffer.putInt(index, block[0])
|
||||
buffer.putInt(index + 4, block[1])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enciphers the values of the block using the Tiny Encryption Algorithm (TEA).
|
||||
* This algorithm relies on a Feistel network, using bitwise operations and
|
||||
* modular addition to provide confusion(block[0] line) and diffusion(block[1] line).
|
||||
*
|
||||
* @param keys 128-bit key (4x32-bit int).
|
||||
* @param block 64-bit data block (2x32-bit int) to be encrypted.
|
||||
*/
|
||||
private fun encipher(keys: IntArray, block: IntArray) {
|
||||
var sum: Long = 0 // Running sum to ensure different round constants - should match SUM at the end.
|
||||
for (i in 0 until NUM_ROUNDS) {
|
||||
block[0] += (((block[1] shl 4 xor (block[1] ushr 5)) + block[1]).toLong() xor keys[(sum and 0x3L).toInt()] + sum).toInt()
|
||||
sum += DELTA.toLong()
|
||||
block[1] += (keys[(sum and KEY_SCRAMBLE.toLong() ushr 11).toInt()] + sum xor (block[0] + (block[0] shl 4 xor (block[0] ushr 5))).toLong()).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
package core.cache.misc;
|
||||
|
||||
/**
|
||||
* A container.
|
||||
* @author Dragonkk
|
||||
*/
|
||||
public class Container {
|
||||
|
||||
/**
|
||||
* The version.
|
||||
*/
|
||||
private int version;
|
||||
|
||||
/**
|
||||
* The CRC.
|
||||
*/
|
||||
private int crc;
|
||||
|
||||
/**
|
||||
* The name hash.
|
||||
*/
|
||||
private int nameHash;
|
||||
|
||||
/**
|
||||
* If updated.
|
||||
*/
|
||||
private boolean updated;
|
||||
|
||||
/**
|
||||
* Construct a new container.
|
||||
*/
|
||||
public Container() {
|
||||
nameHash = -1;
|
||||
version = -1;
|
||||
crc = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the version.
|
||||
* @param version
|
||||
*/
|
||||
public void setVersion(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the version.
|
||||
*/
|
||||
public void updateVersion() {
|
||||
version++;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version.
|
||||
* @return The version.
|
||||
*/
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next version.
|
||||
* @return The next version.
|
||||
*/
|
||||
public int getNextVersion() {
|
||||
return updated ? version : version + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CRC.
|
||||
* @param crc The cRC.
|
||||
*/
|
||||
public void setCrc(int crc) {
|
||||
this.crc = crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CRC.
|
||||
* @return The CRC.
|
||||
*/
|
||||
public int getCrc() {
|
||||
return crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name hash.
|
||||
* @param nameHash The name hash.
|
||||
*/
|
||||
public void setNameHash(int nameHash) {
|
||||
this.nameHash = nameHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name hash.
|
||||
* @return The name hash.
|
||||
*/
|
||||
public int getNameHash() {
|
||||
return nameHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* If is updated.
|
||||
* @return If is updated.
|
||||
*/
|
||||
public boolean isUpdated() {
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package core.cache.misc
|
||||
|
||||
data class Container(
|
||||
var version: Int = -1,
|
||||
var crc: Int = -1,
|
||||
var nameHash: Int = -1
|
||||
)
|
||||
@@ -1,228 +0,0 @@
|
||||
package core.cache.misc;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import core.cache.bzip2.BZip2Decompressor;
|
||||
import core.cache.gzip.GZipDecompressor;
|
||||
|
||||
/**
|
||||
* A class holding the containers information.
|
||||
* @author Dragonkk
|
||||
*/
|
||||
public final class ContainersInformation {
|
||||
|
||||
/**
|
||||
* The information container.
|
||||
*/
|
||||
private Container informationContainer;
|
||||
|
||||
/**
|
||||
* The protocol.
|
||||
*/
|
||||
private int protocol;
|
||||
|
||||
/**
|
||||
* The revision.
|
||||
*/
|
||||
private int revision;
|
||||
|
||||
/**
|
||||
* The container indexes.
|
||||
*/
|
||||
private int[] containersIndexes;
|
||||
|
||||
/**
|
||||
* The containers.
|
||||
*/
|
||||
private FilesContainer[] containers;
|
||||
|
||||
/**
|
||||
* If files have to be named.
|
||||
*/
|
||||
private boolean filesNamed;
|
||||
|
||||
/**
|
||||
* If it has to be whirpool.
|
||||
*/
|
||||
private boolean whirpool;
|
||||
|
||||
/**
|
||||
* The data.
|
||||
*/
|
||||
private final byte[] data;
|
||||
|
||||
/**
|
||||
* Construct a new containers information.
|
||||
* @param informationContainerPackedData The information container data
|
||||
* packed.
|
||||
*/
|
||||
public ContainersInformation(byte[] informationContainerPackedData) {
|
||||
this.data = Arrays.copyOf(informationContainerPackedData, informationContainerPackedData.length);
|
||||
informationContainer = new Container();
|
||||
informationContainer.setVersion((informationContainerPackedData[informationContainerPackedData.length - 2] << 8 & 0xff00) + (informationContainerPackedData[-1 + informationContainerPackedData.length] & 0xff));
|
||||
CRC32 crc32 = new CRC32();
|
||||
crc32.update(informationContainerPackedData);
|
||||
informationContainer.setCrc((int) crc32.getValue());
|
||||
decodeContainersInformation(unpackCacheContainer(informationContainerPackedData));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpacks a container.
|
||||
* @param packedData The packed container data.
|
||||
* @return The unpacked data.
|
||||
*/
|
||||
public static final byte[] unpackCacheContainer(byte[] packedData) {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(packedData);
|
||||
int compression = buffer.get() & 0xFF;
|
||||
int containerSize = buffer.getInt();
|
||||
if (containerSize < 0 || containerSize > 5000000) {
|
||||
return null;
|
||||
// throw new RuntimeException();
|
||||
}
|
||||
if (compression == 0) {
|
||||
byte unpacked[] = new byte[containerSize];
|
||||
buffer.get(unpacked, 0, containerSize);
|
||||
return unpacked;
|
||||
}
|
||||
int decompressedSize = buffer.getInt();
|
||||
if (decompressedSize < 0 || decompressedSize > 20000000) {
|
||||
return null;
|
||||
// throw new RuntimeException();
|
||||
}
|
||||
byte decompressedData[] = new byte[decompressedSize];
|
||||
if (compression == 1) {
|
||||
BZip2Decompressor.decompress(decompressedData, packedData, containerSize, 9);
|
||||
} else {
|
||||
GZipDecompressor.decompress(buffer, decompressedData);
|
||||
}
|
||||
return decompressedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the container indexes.
|
||||
* @return The container indexes.
|
||||
*/
|
||||
public int[] getContainersIndexes() {
|
||||
return containersIndexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the containers.
|
||||
* @return The containers.
|
||||
*/
|
||||
public FilesContainer[] getContainers() {
|
||||
return containers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the information container.
|
||||
* @return The information container.
|
||||
*/
|
||||
public Container getInformationContainer() {
|
||||
return informationContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the revision.
|
||||
* @return The revision.
|
||||
*/
|
||||
public int getRevision() {
|
||||
return revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the containers information.
|
||||
* @param data The data.
|
||||
*/
|
||||
public void decodeContainersInformation(byte[] data) {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(data);
|
||||
protocol = buffer.get() & 0xFF;
|
||||
if (protocol != 5 && protocol != 6) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
revision = protocol < 6 ? 0 : buffer.getInt();
|
||||
int nameHash = buffer.get() & 0xFF;
|
||||
filesNamed = (0x1 & nameHash) != 0;
|
||||
whirpool = (0x2 & nameHash) != 0;
|
||||
containersIndexes = new int[buffer.getShort() & 0xFFFF];
|
||||
int lastIndex = -1;
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containersIndexes[index] = (buffer.getShort() & 0xFFFF) + (index == 0 ? 0 : containersIndexes[index - 1]);
|
||||
if (containersIndexes[index] > lastIndex) {
|
||||
lastIndex = containersIndexes[index];
|
||||
}
|
||||
}
|
||||
containers = new FilesContainer[lastIndex + 1];
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containers[containersIndexes[index]] = new FilesContainer();
|
||||
}
|
||||
if (filesNamed) {
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containers[containersIndexes[index]].setNameHash(buffer.getInt());
|
||||
}
|
||||
}
|
||||
byte[][] filesHashes = null;
|
||||
if (whirpool) {
|
||||
filesHashes = new byte[containers.length][];
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
filesHashes[containersIndexes[index]] = new byte[64];
|
||||
buffer.get(filesHashes[containersIndexes[index]], 0, 64);
|
||||
}
|
||||
}
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containers[containersIndexes[index]].setCrc(buffer.getInt());
|
||||
}
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containers[containersIndexes[index]].setVersion(buffer.getInt());
|
||||
}
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
containers[containersIndexes[index]].setFilesIndexes(new int[buffer.getShort() & 0xFFFF]);
|
||||
}
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
int lastFileIndex = -1;
|
||||
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
|
||||
containers[containersIndexes[index]].getFilesIndexes()[fileIndex] = (buffer.getShort() & 0xFFFF) + (fileIndex == 0 ? 0 : containers[containersIndexes[index]].getFilesIndexes()[fileIndex - 1]);
|
||||
if (containers[containersIndexes[index]].getFilesIndexes()[fileIndex] > lastFileIndex) {
|
||||
lastFileIndex = containers[containersIndexes[index]].getFilesIndexes()[fileIndex];
|
||||
}
|
||||
}
|
||||
containers[containersIndexes[index]].setFiles(new Container[lastFileIndex + 1]);
|
||||
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
|
||||
containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]] = new Container();
|
||||
}
|
||||
}
|
||||
if (whirpool) {
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
|
||||
containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]].setVersion(filesHashes[containersIndexes[index]][containers[containersIndexes[index]].getFilesIndexes()[fileIndex]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filesNamed) {
|
||||
for (int index = 0; index < containersIndexes.length; index++) {
|
||||
for (int fileIndex = 0; fileIndex < containers[containersIndexes[index]].getFilesIndexes().length; fileIndex++) {
|
||||
containers[containersIndexes[index]].getFiles()[containers[containersIndexes[index]].getFilesIndexes()[fileIndex]].setNameHash(buffer.getInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If is whirpool.
|
||||
* @return If is whirpool {@code true}.
|
||||
*/
|
||||
public boolean isWhirpool() {
|
||||
return whirpool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data.
|
||||
* @return The data.
|
||||
*/
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package core.cache.misc
|
||||
|
||||
import core.cache.bzip2.BZip2Decompressor
|
||||
import core.cache.gzip.GZipDecompressor
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.*
|
||||
import java.util.zip.CRC32
|
||||
|
||||
class ContainersInformation(informationContainerPackedData: ByteArray) {
|
||||
@JvmField
|
||||
val informationContainer: Container
|
||||
private var protocol = 0
|
||||
var revision = 0
|
||||
var containersIndexes: IntArray = intArrayOf()
|
||||
var containers: Array<FilesContainer?> = arrayOf()
|
||||
private var filesNamed = false // If files has to be named
|
||||
private var whirpool = false // Flag for whirpool
|
||||
val data: ByteArray
|
||||
|
||||
init {
|
||||
data = Arrays.copyOf(informationContainerPackedData, informationContainerPackedData.size)
|
||||
informationContainer = Container()
|
||||
informationContainer.version =
|
||||
(informationContainerPackedData[informationContainerPackedData.size - 2].toInt() shl 8 and 0xff00) + (informationContainerPackedData[-1 + informationContainerPackedData.size].toInt() and 0xff)
|
||||
val crc32 = CRC32()
|
||||
crc32.update(informationContainerPackedData)
|
||||
informationContainer.crc = crc32.value.toInt()
|
||||
decodeContainersInformation(unpackCacheContainer(informationContainerPackedData))
|
||||
}
|
||||
|
||||
fun decodeContainersInformation(data: ByteArray?) {
|
||||
val buffer = ByteBuffer.wrap(data)
|
||||
protocol = buffer.get().toInt() and 0xFF
|
||||
if (protocol != 5 && protocol != 6) {
|
||||
throw RuntimeException()
|
||||
}
|
||||
revision = if (protocol < 6) 0 else buffer.getInt()
|
||||
val nameHash = buffer.get().toInt() and 0xFF
|
||||
filesNamed = 0x1 and nameHash != 0
|
||||
whirpool = 0x2 and nameHash != 0
|
||||
containersIndexes = IntArray(buffer.getShort().toInt() and 0xFFFF)
|
||||
var lastIndex = -1
|
||||
for (index in containersIndexes.indices) {
|
||||
val containerIndex =
|
||||
(buffer.getShort().toInt() and 0xFFFF) + if (index == 0) 0 else containersIndexes[index - 1]
|
||||
containersIndexes[index] = containerIndex
|
||||
if (containerIndex > lastIndex) {
|
||||
lastIndex = containerIndex
|
||||
}
|
||||
}
|
||||
containers = arrayOfNulls(lastIndex + 1)
|
||||
for (containerIdx in containersIndexes) {
|
||||
containers[containerIdx] = FilesContainer()
|
||||
}
|
||||
if (filesNamed) {
|
||||
for (containerIdx in containersIndexes) {
|
||||
containers[containerIdx]!!.nameHash = buffer.getInt()
|
||||
}
|
||||
}
|
||||
var filesHashes: Array<ByteArray?>? = null
|
||||
if (whirpool) {
|
||||
filesHashes = arrayOfNulls(containers.size)
|
||||
for (containerIdx in containersIndexes) {
|
||||
filesHashes[containerIdx] = ByteArray(64)
|
||||
buffer[filesHashes[containerIdx], 0, 64]
|
||||
}
|
||||
}
|
||||
for (containerIdx in containersIndexes) {
|
||||
containers[containerIdx]!!.crc = buffer.getInt()
|
||||
}
|
||||
for (containerIdx in containersIndexes) {
|
||||
containers[containerIdx]!!.version = buffer.getInt()
|
||||
}
|
||||
for (containerIdx in containersIndexes) {
|
||||
containers[containerIdx]!!.filesIndexes = IntArray(buffer.getShort().toInt() and 0xFFFF)
|
||||
}
|
||||
for (containerIdx in containersIndexes) {
|
||||
val container = containers[containerIdx]
|
||||
val filesIndexes = container!!.filesIndexes
|
||||
var lastFileIndex = -1
|
||||
for (fileIndex in filesIndexes!!.indices) {
|
||||
val fileIdx =
|
||||
(buffer.getShort().toInt() and 0xFFFF) + if (fileIndex == 0) 0 else filesIndexes[fileIndex - 1]
|
||||
filesIndexes[fileIndex] = fileIdx
|
||||
if (fileIdx > lastFileIndex) {
|
||||
lastFileIndex = fileIdx
|
||||
}
|
||||
}
|
||||
val files = arrayOfNulls<Container>(lastFileIndex + 1)
|
||||
container.files = files
|
||||
for (fileIdx in filesIndexes) {
|
||||
files[fileIdx] = Container()
|
||||
}
|
||||
}
|
||||
if (whirpool) {
|
||||
for (containerIdx in containersIndexes) {
|
||||
val container = containers[containerIdx]
|
||||
val containerHashes = filesHashes!![containerIdx]
|
||||
val files = container!!.files
|
||||
for (fileIdx in container.filesIndexes!!) {
|
||||
files!![fileIdx]!!.version = containerHashes!![fileIdx].toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filesNamed) {
|
||||
for (containerIdx in containersIndexes) {
|
||||
val container = containers[containerIdx]
|
||||
val files = container!!.files
|
||||
for (fileIdx in container.filesIndexes!!) {
|
||||
files!![fileIdx]!!.nameHash = buffer.getInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun unpackCacheContainer(packedData: ByteArray?): ByteArray? {
|
||||
val buffer = ByteBuffer.wrap(packedData)
|
||||
val compression = buffer.get().toInt() and 0xFF
|
||||
val containerSize = buffer.getInt()
|
||||
if (containerSize < 0 || containerSize > 5000000) {
|
||||
return null
|
||||
// throw new RuntimeException();
|
||||
}
|
||||
if (compression == 0) {
|
||||
val unpacked = ByteArray(containerSize)
|
||||
buffer[unpacked, 0, containerSize]
|
||||
return unpacked
|
||||
}
|
||||
val decompressedSize = buffer.getInt()
|
||||
if (decompressedSize < 0 || decompressedSize > 20000000) {
|
||||
return null
|
||||
// throw new RuntimeException();
|
||||
}
|
||||
val decompressedData = ByteArray(decompressedSize)
|
||||
if (compression == 1) {
|
||||
BZip2Decompressor.decompress(decompressedData, packedData, containerSize, 9)
|
||||
} else {
|
||||
GZipDecompressor.decompress(buffer, decompressedData)
|
||||
}
|
||||
return decompressedData
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package core.cache.misc;
|
||||
|
||||
/**
|
||||
* A class holding the file containers.
|
||||
* @author Dragonkk
|
||||
*/
|
||||
public final class FilesContainer extends Container {
|
||||
|
||||
/**
|
||||
* The file indexes.
|
||||
*/
|
||||
private int[] filesIndexes;
|
||||
|
||||
/**
|
||||
* The files.
|
||||
*/
|
||||
private Container[] files;
|
||||
|
||||
/**
|
||||
* Construct a new files container.
|
||||
*/
|
||||
public FilesContainer() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the files.
|
||||
* @param containers The files.
|
||||
*/
|
||||
public void setFiles(Container[] containers) {
|
||||
this.files = containers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the files.
|
||||
* @return The files.
|
||||
*/
|
||||
public Container[] getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file indexes.
|
||||
* @param containersIndexes The file indexes.
|
||||
*/
|
||||
public void setFilesIndexes(int[] containersIndexes) {
|
||||
this.filesIndexes = containersIndexes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file indexes.
|
||||
* @return The file indexes.
|
||||
*/
|
||||
public int[] getFilesIndexes() {
|
||||
return filesIndexes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package core.cache.misc
|
||||
|
||||
data class FilesContainer(
|
||||
var version: Int = -1,
|
||||
var crc: Int = -1,
|
||||
var nameHash: Int = -1,
|
||||
var filesIndexes: IntArray? = null,
|
||||
var files: Array<Container?>? = null
|
||||
)
|
||||
@@ -1,39 +0,0 @@
|
||||
package core.cache.misc.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles the reading of data from a byte buffer.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class BufferInputStream extends InputStream {
|
||||
|
||||
/**
|
||||
* The buffer to write on.
|
||||
*/
|
||||
private final ByteBuffer buffer;
|
||||
|
||||
/**
|
||||
* The buffer input stream.
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
public BufferInputStream(ByteBuffer buffer) throws IOException {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return buffer.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buffer.
|
||||
* @return The buffer.
|
||||
*/
|
||||
public ByteBuffer getBuffer() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package core.cache.misc.buffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles the writing of data on a byte buffer.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class BufferOutputStream extends OutputStream {
|
||||
|
||||
/**
|
||||
* The buffer to write on.
|
||||
*/
|
||||
private final ByteBuffer buffer;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BufferOutputStream} {@code Object}.
|
||||
* @param buffer The buffer to write on.
|
||||
* @throws IOException When an I/O exception occurs.
|
||||
* @throws SecurityException If a security manager exists and its
|
||||
* checkPermission method denies enabling subclassing.
|
||||
*/
|
||||
public BufferOutputStream(ByteBuffer buffer) throws IOException, SecurityException {
|
||||
super();
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
buffer.put((byte) b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buffer.
|
||||
* @return The buffer.
|
||||
*/
|
||||
public ByteBuffer getBuffer() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
package core.cache.misc.buffer;
|
||||
|
||||
import java.io.ObjectInputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Holds utility methods for reading/writing a byte buffer.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class ByteBufferUtils {
|
||||
|
||||
/**
|
||||
* Gets a string from the byte buffer.
|
||||
* @param buffer The byte buffer.
|
||||
* @return The string.
|
||||
*/
|
||||
public static String getString(ByteBuffer buffer) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
byte b;
|
||||
while ((b = buffer.get()) != 0) {
|
||||
sb.append((char) b);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a string on the byte buffer.
|
||||
* @param s The string to put.
|
||||
* @param buffer The byte buffer.
|
||||
*/
|
||||
public static void putString(String s, ByteBuffer buffer) {
|
||||
buffer.put(s.getBytes(StandardCharsets.UTF_8)).put((byte) 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string from the byte buffer.
|
||||
* @param s The string.
|
||||
* @param buffer The byte buffer.
|
||||
* @return The string.
|
||||
*/
|
||||
public static ByteBuffer putGJ2String(String s, ByteBuffer buffer) {
|
||||
byte[] packed = new byte[256];
|
||||
int length = packGJString2(0, packed, s);
|
||||
return buffer.put((byte) 0).put(packed, 0, length).put((byte) 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the XTEA encryption.
|
||||
* @param keys The keys.
|
||||
* @param start The start index.
|
||||
* @param end The end index.
|
||||
* @param buffer The byte buffer.
|
||||
*/
|
||||
public static void decodeXTEA(int[] keys, int start, int end, ByteBuffer buffer) {
|
||||
int l = buffer.position();
|
||||
buffer.position(start);
|
||||
int length = (end - start) / 8;
|
||||
for (int i = 0; i < length; i++) {
|
||||
int firstInt = buffer.getInt();
|
||||
int secondInt = buffer.getInt();
|
||||
int sum = 0xc6ef3720;
|
||||
int delta = 0x9e3779b9;
|
||||
for (int j = 32; j-- > 0;) {
|
||||
secondInt -= keys[(sum & 0x1c84) >>> 11] + sum ^ (firstInt >>> 5 ^ firstInt << 4) + firstInt;
|
||||
sum -= delta;
|
||||
firstInt -= (secondInt >>> 5 ^ secondInt << 4) + secondInt ^ keys[sum & 3] + sum;
|
||||
}
|
||||
buffer.position(buffer.position() - 8);
|
||||
buffer.putInt(firstInt);
|
||||
buffer.putInt(secondInt);
|
||||
}
|
||||
buffer.position(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a String to an Integer?
|
||||
* @param position The position.
|
||||
* @param buffer The buffer used.
|
||||
* @param string The String to convert.
|
||||
* @return The Integer.
|
||||
*/
|
||||
public static int packGJString2(int position, byte[] buffer, String string) {
|
||||
int length = string.length();
|
||||
int offset = position;
|
||||
for (int i = 0; length > i; i++) {
|
||||
int character = string.charAt(i);
|
||||
if (character > 127) {
|
||||
if (character > 2047) {
|
||||
buffer[offset++] = (byte) ((character | 919275) >> 12);
|
||||
buffer[offset++] = (byte) (128 | ((character >> 6) & 63));
|
||||
buffer[offset++] = (byte) (128 | (character & 63));
|
||||
} else {
|
||||
buffer[offset++] = (byte) ((character | 12309) >> 6);
|
||||
buffer[offset++] = (byte) (128 | (character & 63));
|
||||
}
|
||||
} else
|
||||
buffer[offset++] = (byte) character;
|
||||
}
|
||||
return offset - position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a tri-byte from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
public static int getMedium(ByteBuffer buffer) {
|
||||
return ((buffer.get() & 0xFF) << 16) + ((buffer.get() & 0xFF) << 8) + (buffer.get() & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a smart from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
public static int getSmart(ByteBuffer buffer) {
|
||||
int peek = buffer.get() & 0xFF;
|
||||
if (peek <= Byte.MAX_VALUE) {
|
||||
return peek;
|
||||
}
|
||||
return ((peek << 8) | (buffer.get() & 0xFF)) - 32768;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a smart from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
public static int getBigSmart(ByteBuffer buffer) {
|
||||
int value = 0;
|
||||
int current = getSmart(buffer);
|
||||
while (current == 32767) {
|
||||
current = getSmart(buffer);
|
||||
value += 32767;
|
||||
}
|
||||
value += current;
|
||||
return value;
|
||||
}
|
||||
|
||||
/* *//**
|
||||
* Writes an object on the buffer.
|
||||
* @param buffer The buffer to write on.
|
||||
* @param o The object.
|
||||
*/
|
||||
/*
|
||||
* public static void putObject(ByteBuffer buffer, Object o) { ByteBuffer b;
|
||||
* try (ObjectOutputStream out = new ObjectOutputStream(new
|
||||
* BufferOutputStream(b = ByteBuffer.allocate(99999)))) {
|
||||
* out.writeObject(o); b.flip(); } catch (Throwable e) {
|
||||
* e.printStackTrace(); b = (ByteBuffer) ByteBuffer.allocate(0).flip(); }
|
||||
* buffer.putInt(b.remaining()); if (b.remaining() > 0) { buffer.put(b); } }
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets an object from the byte buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The object.
|
||||
*/
|
||||
public static Object getObject(ByteBuffer buffer) {
|
||||
int length = buffer.getInt();
|
||||
if (length > 0) {
|
||||
byte[] bytes = new byte[length];
|
||||
buffer.get(bytes);
|
||||
try (ObjectInputStream str = new ObjectInputStream(new BufferInputStream(ByteBuffer.wrap(bytes)))) {
|
||||
return (Object) str.readObject();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ByteBufferUtils} {@code Object}.
|
||||
*/
|
||||
private ByteBufferUtils() {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package core.cache.misc.buffer
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
object ByteBufferUtils {
|
||||
/**
|
||||
* Gets a string from the byte buffer.
|
||||
* @param buffer The byte buffer.
|
||||
* @return The string.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getString(buffer: ByteBuffer): String {
|
||||
val sb = StringBuilder()
|
||||
var b: Byte
|
||||
while (buffer.get().also { b = it }.toInt() != 0) {
|
||||
sb.append(Char(b.toUShort()))
|
||||
}
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a string on the byte buffer.
|
||||
* @param s The string to put.
|
||||
* @param buffer The byte buffer.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun putString(s: String, buffer: ByteBuffer) {
|
||||
buffer.put(s.toByteArray(StandardCharsets.UTF_8)).put(0.toByte())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string from the byte buffer.
|
||||
* @param s The string.
|
||||
* @param buffer The byte buffer.
|
||||
* @return The string.
|
||||
*/
|
||||
fun putGJ2String(s: String, buffer: ByteBuffer): ByteBuffer {
|
||||
val packed = ByteArray(256)
|
||||
val length = packGJString2(0, packed, s)
|
||||
return buffer.put(0.toByte()).put(packed, 0, length).put(0.toByte())
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the XTEA encryption.
|
||||
* @param keys The keys.
|
||||
* @param start The start index.
|
||||
* @param end The end index.
|
||||
* @param buffer The byte buffer.
|
||||
*/
|
||||
fun decodeXTEA(keys: IntArray, start: Int, end: Int, buffer: ByteBuffer) {
|
||||
val l = buffer.position()
|
||||
buffer.position(start)
|
||||
val length = (end - start) / 8
|
||||
for (i in 0 until length) {
|
||||
var firstInt = buffer.getInt()
|
||||
var secondInt = buffer.getInt()
|
||||
var sum = -0x3910c8e0
|
||||
val delta = -0x61c88647
|
||||
var j = 32
|
||||
while (j-- > 0) {
|
||||
secondInt -= keys[sum and 0x1c84 ushr 11] + sum xor (firstInt ushr 5 xor (firstInt shl 4)) + firstInt
|
||||
sum -= delta
|
||||
firstInt -= (secondInt ushr 5 xor (secondInt shl 4)) + secondInt xor keys[sum and 3] + sum
|
||||
}
|
||||
buffer.position(buffer.position() - 8)
|
||||
buffer.putInt(firstInt)
|
||||
buffer.putInt(secondInt)
|
||||
}
|
||||
buffer.position(l)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a String to an Integer?
|
||||
* @param position The position.
|
||||
* @param buffer The buffer used.
|
||||
* @param string The String to convert.
|
||||
* @return The Integer.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun packGJString2(position: Int, buffer: ByteArray, string: String): Int {
|
||||
val length = string.length
|
||||
var offset = position
|
||||
var i = 0
|
||||
while (length > i) {
|
||||
val character = string[i].code
|
||||
if (character > 127) {
|
||||
if (character > 2047) {
|
||||
buffer[offset++] = (character or 919275 shr 12).toByte()
|
||||
buffer[offset++] = (128 or (character shr 6 and 63)).toByte()
|
||||
buffer[offset++] = (128 or (character and 63)).toByte()
|
||||
} else {
|
||||
buffer[offset++] = (character or 12309 shr 6).toByte()
|
||||
buffer[offset++] = (128 or (character and 63)).toByte()
|
||||
}
|
||||
} else buffer[offset++] = character.toByte()
|
||||
i++
|
||||
}
|
||||
return offset - position
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a tri-byte from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getMedium(buffer: ByteBuffer): Int {
|
||||
return (buffer.get().toInt() and 0xFF shl 16) + (buffer.get().toInt() and 0xFF shl 8) + (buffer.get()
|
||||
.toInt() and 0xFF)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a smart from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getSmart(buffer: ByteBuffer): Int {
|
||||
val peek = buffer.get().toInt() and 0xFF
|
||||
return if (peek <= Byte.MAX_VALUE) {
|
||||
peek
|
||||
} else (peek shl 8 or (buffer.get().toInt() and 0xFF)) - 32768
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a smart from the buffer.
|
||||
* @param buffer The buffer.
|
||||
* @return The value.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getBigSmart(buffer: ByteBuffer): Int {
|
||||
var value = 0
|
||||
var current = getSmart(buffer)
|
||||
while (current == 32767) {
|
||||
current = getSmart(buffer)
|
||||
value += 32767
|
||||
}
|
||||
value += current
|
||||
return value
|
||||
}
|
||||
}
|
||||
@@ -190,15 +190,16 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
|
||||
val dump = File("structs.txt")
|
||||
val writer = BufferedWriter(FileWriter(dump))
|
||||
val index = Cache.getIndexes()[2]
|
||||
val containers = index.information.containers[26].filesIndexes
|
||||
for(fID in containers)
|
||||
{
|
||||
val file = index.getFileData(26, fID)
|
||||
if(file != null){
|
||||
val def = Struct.parse(fID, file)
|
||||
if(def.dataStore.isEmpty()) continue //no data in struct.
|
||||
writer.write(def.toString())
|
||||
writer.newLine()
|
||||
val containers = index.information.containers[26]!!.filesIndexes
|
||||
if (containers != null) {
|
||||
for(fID in containers) {
|
||||
val file = index.getFileData(26, fID)
|
||||
if(file != null){
|
||||
val def = Struct.parse(fID, file)
|
||||
if(def.dataStore.isEmpty()) continue //no data in struct.
|
||||
writer.write(def.toString())
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
writer.flush()
|
||||
@@ -214,15 +215,16 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
|
||||
|
||||
for(cID in containers)
|
||||
{
|
||||
val fileIndexes = index.information.containers[cID].filesIndexes
|
||||
for(fID in fileIndexes)
|
||||
{
|
||||
val file = index.getFileData(cID, fID)
|
||||
if(file != null){
|
||||
val def = DataMap.parse((cID shl 8) or fID, file)
|
||||
if(def.keyType == '?') continue //Empty definition - only a 0 present in the cachefile data.
|
||||
writer.write(def.toString())
|
||||
writer.newLine()
|
||||
val fileIndexes = index.information.containers[cID]!!.filesIndexes
|
||||
if (fileIndexes != null) {
|
||||
for(fID in fileIndexes) {
|
||||
val file = index.getFileData(cID, fID)
|
||||
if(file != null){
|
||||
val def = DataMap.parse((cID shl 8) or fID, file)
|
||||
if(def.keyType == '?') continue //Empty definition - only a 0 present in the cachefile data.
|
||||
writer.write(def.toString())
|
||||
writer.newLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user