Cleaned up some core files
This commit is contained in:
+1
-1
@@ -145,7 +145,7 @@ public final class Cache {
|
|||||||
buffer.putInt(0);
|
buffer.putInt(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
buffer.putInt(cacheFileManagers[index].getInformation().getInformationContainer().getCrc());
|
buffer.putInt(cacheFileManagers[index].getInformation().informationContainer.getCrc());
|
||||||
buffer.putInt(cacheFileManagers[index].getInformation().getRevision());
|
buffer.putInt(cacheFileManagers[index].getInformation().getRevision());
|
||||||
}
|
}
|
||||||
return buffer.array();
|
return buffer.array();
|
||||||
|
|||||||
+1
-1
@@ -66,7 +66,7 @@ public final class CacheFile {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (xteaKeys != null && (xteaKeys[0] != 0 || xteaKeys[1] != 0 || xteaKeys[2] != 0 || xteaKeys[3] != 0)) {
|
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);
|
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 dump = File("structs.txt")
|
||||||
val writer = BufferedWriter(FileWriter(dump))
|
val writer = BufferedWriter(FileWriter(dump))
|
||||||
val index = Cache.getIndexes()[2]
|
val index = Cache.getIndexes()[2]
|
||||||
val containers = index.information.containers[26].filesIndexes
|
val containers = index.information.containers[26]!!.filesIndexes
|
||||||
for(fID in containers)
|
if (containers != null) {
|
||||||
{
|
for(fID in containers) {
|
||||||
val file = index.getFileData(26, fID)
|
val file = index.getFileData(26, fID)
|
||||||
if(file != null){
|
if(file != null){
|
||||||
val def = Struct.parse(fID, file)
|
val def = Struct.parse(fID, file)
|
||||||
if(def.dataStore.isEmpty()) continue //no data in struct.
|
if(def.dataStore.isEmpty()) continue //no data in struct.
|
||||||
writer.write(def.toString())
|
writer.write(def.toString())
|
||||||
writer.newLine()
|
writer.newLine()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.flush()
|
writer.flush()
|
||||||
@@ -214,15 +215,16 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
|
|||||||
|
|
||||||
for(cID in containers)
|
for(cID in containers)
|
||||||
{
|
{
|
||||||
val fileIndexes = index.information.containers[cID].filesIndexes
|
val fileIndexes = index.information.containers[cID]!!.filesIndexes
|
||||||
for(fID in fileIndexes)
|
if (fileIndexes != null) {
|
||||||
{
|
for(fID in fileIndexes) {
|
||||||
val file = index.getFileData(cID, fID)
|
val file = index.getFileData(cID, fID)
|
||||||
if(file != null){
|
if(file != null){
|
||||||
val def = DataMap.parse((cID shl 8) or fID, file)
|
val def = DataMap.parse((cID shl 8) or fID, file)
|
||||||
if(def.keyType == '?') continue //Empty definition - only a 0 present in the cachefile data.
|
if(def.keyType == '?') continue //Empty definition - only a 0 present in the cachefile data.
|
||||||
writer.write(def.toString())
|
writer.write(def.toString())
|
||||||
writer.newLine()
|
writer.newLine()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user