// Decompiled with JetBrains decompiler // Type: SmartAssembly.Zip.SimpleZip // Assembly: WinData, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null // MVID: 162322D2-FE3A-45B9-99E4-3519564A1D4D // Assembly location: C:\Users\Administrateur\Downloads\Virusshare.00004-msil\Trojan-Ransom.Win32.Blocker.kkro-82cd479bb60c59525668e5016b400a8cc48f04b14a5c6cad5e2c6046b301e79d.exe using System; using System.IO; using System.Reflection; using System.Security.Cryptography; using System.Text; namespace SmartAssembly.Zip { public sealed class SimpleZip { public static string ExceptionMessage; private static bool PublicKeysMatch(Assembly executingAssembly, Assembly callingAssembly) { byte[] publicKey1 = executingAssembly.GetName().GetPublicKey(); byte[] publicKey2 = callingAssembly.GetName().GetPublicKey(); if (publicKey2 == null != (publicKey1 == null)) return false; if (publicKey2 != null) { for (int index = 0; index < publicKey2.Length; ++index) { if ((int) publicKey2[index] != (int) publicKey1[index]) return false; } } return true; } public static byte[] Unzip(byte[] buffer) { Assembly callingAssembly = Assembly.GetCallingAssembly(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); if ((object) callingAssembly != (object) executingAssembly && !SimpleZip.PublicKeysMatch(executingAssembly, callingAssembly)) return (byte[]) null; SimpleZip.ZipStream zipStream = new SimpleZip.ZipStream(buffer); byte[] buf = new byte[0]; int num1 = zipStream.ReadInt(); if (num1 == 67324752) { short num2 = (short) zipStream.ReadShort(); int num3 = zipStream.ReadShort(); int num4 = zipStream.ReadShort(); if (num1 != 67324752 || num2 != (short) 20 || num3 != 0 || num4 != 8) throw new FormatException("Wrong Header Signature"); zipStream.ReadInt(); zipStream.ReadInt(); zipStream.ReadInt(); int length = zipStream.ReadInt(); int count1 = zipStream.ReadShort(); int count2 = zipStream.ReadShort(); if (count1 > 0) { byte[] buffer1 = new byte[count1]; zipStream.Read(buffer1, 0, count1); } if (count2 > 0) { byte[] buffer2 = new byte[count2]; zipStream.Read(buffer2, 0, count2); } byte[] numArray = new byte[zipStream.Length - zipStream.Position]; zipStream.Read(numArray, 0, numArray.Length); SimpleZip.Inflater inflater = new SimpleZip.Inflater(numArray); buf = new byte[length]; inflater.Inflate(buf, 0, buf.Length); } else { int num5 = num1 >> 24; if (num1 - (num5 << 24) != 8223355) throw new FormatException("Unknown Header"); if (num5 == 1) { int length1 = zipStream.ReadInt(); buf = new byte[length1]; int len; for (int offset = 0; offset < length1; offset += len) { int length2 = zipStream.ReadInt(); len = zipStream.ReadInt(); byte[] numArray = new byte[length2]; zipStream.Read(numArray, 0, numArray.Length); new SimpleZip.Inflater(numArray).Inflate(buf, offset, len); } } if (num5 == 2) { byte[] key = new byte[8] { (byte) 85, (byte) 240, (byte) 125, (byte) 197, (byte) 120, (byte) 224, (byte) 53, (byte) 165 }; byte[] iv = new byte[8] { (byte) 169, (byte) 210, (byte) 146, (byte) 41, (byte) 1, (byte) 34, (byte) 222, (byte) 163 }; using (DESCryptoIndirector cryptoIndirector = new DESCryptoIndirector()) { using (ICryptoTransform desCryptoTransform = cryptoIndirector.GetDESCryptoTransform(key, iv, true)) buf = SimpleZip.Unzip(desCryptoTransform.TransformFinalBlock(buffer, 4, buffer.Length - 4)); } } if (num5 == 3) { byte[] key = new byte[16] { (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1 }; byte[] iv = new byte[16] { (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2, (byte) 2 }; using (AESCryptoIndirector cryptoIndirector = new AESCryptoIndirector()) { using (ICryptoTransform aesCryptoTransform = cryptoIndirector.GetAESCryptoTransform(key, iv, true)) buf = SimpleZip.Unzip(aesCryptoTransform.TransformFinalBlock(buffer, 4, buffer.Length - 4)); } } } zipStream.Close(); return buf; } public static byte[] Zip(byte[] buffer) => SimpleZip.Zip(buffer, 1, (byte[]) null, (byte[]) null); public static byte[] ZipAndEncrypt(byte[] buffer, byte[] key, byte[] iv) => SimpleZip.Zip(buffer, 2, key, iv); public static byte[] ZipAndAES(byte[] buffer, byte[] key, byte[] iv) => SimpleZip.Zip(buffer, 3, key, iv); private static byte[] Zip(byte[] buffer, int version, byte[] key, byte[] iv) { try { SimpleZip.ZipStream zipStream = new SimpleZip.ZipStream(); switch (version) { case 0: SimpleZip.Deflater deflater1 = new SimpleZip.Deflater(); DateTime now = DateTime.Now; long num1 = (long) ((uint) ((now.Year - 1980 & (int) sbyte.MaxValue) << 25 | now.Month << 21 | now.Day << 16 | now.Hour << 11 | now.Minute << 5) | (uint) now.Second >> 1); uint[] numArray1 = new uint[256] { 0U, 1996959894U, 3993919788U, 2567524794U, 124634137U, 1886057615U, 3915621685U, 2657392035U, 249268274U, 2044508324U, 3772115230U, 2547177864U, 162941995U, 2125561021U, 3887607047U, 2428444049U, 498536548U, 1789927666U, 4089016648U, 2227061214U, 450548861U, 1843258603U, 4107580753U, 2211677639U, 325883990U, 1684777152U, 4251122042U, 2321926636U, 335633487U, 1661365465U, 4195302755U, 2366115317U, 997073096U, 1281953886U, 3579855332U, 2724688242U, 1006888145U, 1258607687U, 3524101629U, 2768942443U, 901097722U, 1119000684U, 3686517206U, 2898065728U, 853044451U, 1172266101U, 3705015759U, 2882616665U, 651767980U, 1373503546U, 3369554304U, 3218104598U, 565507253U, 1454621731U, 3485111705U, 3099436303U, 671266974U, 1594198024U, 3322730930U, 2970347812U, 795835527U, 1483230225U, 3244367275U, 3060149565U, 1994146192U, 31158534U, 2563907772U, 4023717930U, 1907459465U, 112637215U, 2680153253U, 3904427059U, 2013776290U, 251722036U, 2517215374U, 3775830040U, 2137656763U, 141376813U, 2439277719U, 3865271297U, 1802195444U, 476864866U, 2238001368U, 4066508878U, 1812370925U, 453092731U, 2181625025U, 4111451223U, 1706088902U, 314042704U, 2344532202U, 4240017532U, 1658658271U, 366619977U, 2362670323U, 4224994405U, 1303535960U, 984961486U, 2747007092U, 3569037538U, 1256170817U, 1037604311U, 2765210733U, 3554079995U, 1131014506U, 879679996U, 2909243462U, 3663771856U, 1141124467U, 855842277U, 2852801631U, 3708648649U, 1342533948U, 654459306U, 3188396048U, 3373015174U, 1466479909U, 544179635U, 3110523913U, 3462522015U, 1591671054U, 702138776U, 2966460450U, 3352799412U, 1504918807U, 783551873U, 3082640443U, 3233442989U, 3988292384U, 2596254646U, 62317068U, 1957810842U, 3939845945U, 2647816111U, 81470997U, 1943803523U, 3814918930U, 2489596804U, 225274430U, 2053790376U, 3826175755U, 2466906013U, 167816743U, 2097651377U, 4027552580U, 2265490386U, 503444072U, 1762050814U, 4150417245U, 2154129355U, 426522225U, 1852507879U, 4275313526U, 2312317920U, 282753626U, 1742555852U, 4189708143U, 2394877945U, 397917763U, 1622183637U, 3604390888U, 2714866558U, 953729732U, 1340076626U, 3518719985U, 2797360999U, 1068828381U, 1219638859U, 3624741850U, 2936675148U, 906185462U, 1090812512U, 3747672003U, 2825379669U, 829329135U, 1181335161U, 3412177804U, 3160834842U, 628085408U, 1382605366U, 3423369109U, 3138078467U, 570562233U, 1426400815U, 3317316542U, 2998733608U, 733239954U, 1555261956U, 3268935591U, 3050360625U, 752459403U, 1541320221U, 2607071920U, 3965973030U, 1969922972U, 40735498U, 2617837225U, 3943577151U, 1913087877U, 83908371U, 2512341634U, 3803740692U, 2075208622U, 213261112U, 2463272603U, 3855990285U, 2094854071U, 198958881U, 2262029012U, 4057260610U, 1759359992U, 534414190U, 2176718541U, 4139329115U, 1873836001U, 414664567U, 2282248934U, 4279200368U, 1711684554U, 285281116U, 2405801727U, 4167216745U, 1634467795U, 376229701U, 2685067896U, 3608007406U, 1308918612U, 956543938U, 2808555105U, 3495958263U, 1231636301U, 1047427035U, 2932959818U, 3654703836U, 1088359270U, 936918000U, 2847714899U, 3736837829U, 1202900863U, 817233897U, 3183342108U, 3401237130U, 1404277552U, 615818150U, 3134207493U, 3453421203U, 1423857449U, 601450431U, 3009837614U, 3294710456U, 1567103746U, 711928724U, 3020668471U, 3272380065U, 1510334235U, 755167117U }; uint maxValue = uint.MaxValue; uint num2 = maxValue; int num3 = 0; int length = buffer.Length; while (--length >= 0) num2 = numArray1[(IntPtr) (uint) (((int) num2 ^ (int) buffer[num3++]) & (int) byte.MaxValue)] ^ num2 >> 8; uint num4 = num2 ^ maxValue; zipStream.WriteInt(67324752); zipStream.WriteShort(20); zipStream.WriteShort(0); zipStream.WriteShort(8); zipStream.WriteInt((int) num1); zipStream.WriteInt((int) num4); long position1 = zipStream.Position; zipStream.WriteInt(0); zipStream.WriteInt(buffer.Length); byte[] bytes = Encoding.UTF8.GetBytes("{data}"); zipStream.WriteShort(bytes.Length); zipStream.WriteShort(0); zipStream.Write(bytes, 0, bytes.Length); deflater1.SetInput(buffer); while (!deflater1.IsNeedingInput) { byte[] numArray2 = new byte[512]; int count = deflater1.Deflate(numArray2); if (count > 0) zipStream.Write(numArray2, 0, count); else break; } deflater1.Finish(); while (!deflater1.IsFinished) { byte[] numArray3 = new byte[512]; int count = deflater1.Deflate(numArray3); if (count > 0) zipStream.Write(numArray3, 0, count); else break; } long totalOut = deflater1.TotalOut; zipStream.WriteInt(33639248); zipStream.WriteShort(20); zipStream.WriteShort(20); zipStream.WriteShort(0); zipStream.WriteShort(8); zipStream.WriteInt((int) num1); zipStream.WriteInt((int) num4); zipStream.WriteInt((int) totalOut); zipStream.WriteInt(buffer.Length); zipStream.WriteShort(bytes.Length); zipStream.WriteShort(0); zipStream.WriteShort(0); zipStream.WriteShort(0); zipStream.WriteShort(0); zipStream.WriteInt(0); zipStream.WriteInt(0); zipStream.Write(bytes, 0, bytes.Length); zipStream.WriteInt(101010256); zipStream.WriteShort(0); zipStream.WriteShort(0); zipStream.WriteShort(1); zipStream.WriteShort(1); zipStream.WriteInt(46 + bytes.Length); zipStream.WriteInt((int) ((long) (30 + bytes.Length) + totalOut)); zipStream.WriteShort(0); zipStream.Seek(position1, SeekOrigin.Begin); zipStream.WriteInt((int) totalOut); break; case 1: zipStream.WriteInt(25000571); zipStream.WriteInt(buffer.Length); byte[] numArray4; for (int srcOffset = 0; srcOffset < buffer.Length; srcOffset += numArray4.Length) { numArray4 = new byte[Math.Min(2097151, buffer.Length - srcOffset)]; Buffer.BlockCopy((Array) buffer, srcOffset, (Array) numArray4, 0, numArray4.Length); long position2 = zipStream.Position; zipStream.WriteInt(0); zipStream.WriteInt(numArray4.Length); SimpleZip.Deflater deflater2 = new SimpleZip.Deflater(); deflater2.SetInput(numArray4); while (!deflater2.IsNeedingInput) { byte[] numArray5 = new byte[512]; int count = deflater2.Deflate(numArray5); if (count > 0) zipStream.Write(numArray5, 0, count); else break; } deflater2.Finish(); while (!deflater2.IsFinished) { byte[] numArray6 = new byte[512]; int count = deflater2.Deflate(numArray6); if (count > 0) zipStream.Write(numArray6, 0, count); else break; } long position3 = zipStream.Position; zipStream.Position = position2; zipStream.WriteInt((int) deflater2.TotalOut); zipStream.Position = position3; } break; case 2: zipStream.WriteInt(41777787); byte[] inputBuffer1 = SimpleZip.Zip(buffer, 1, (byte[]) null, (byte[]) null); using (DESCryptoIndirector cryptoIndirector = new DESCryptoIndirector()) { using (ICryptoTransform desCryptoTransform = cryptoIndirector.GetDESCryptoTransform(key, iv, false)) { byte[] buffer1 = desCryptoTransform.TransformFinalBlock(inputBuffer1, 0, inputBuffer1.Length); zipStream.Write(buffer1, 0, buffer1.Length); break; } } case 3: zipStream.WriteInt(58555003); byte[] inputBuffer2 = SimpleZip.Zip(buffer, 1, (byte[]) null, (byte[]) null); using (AESCryptoIndirector cryptoIndirector = new AESCryptoIndirector()) { using (ICryptoTransform aesCryptoTransform = cryptoIndirector.GetAESCryptoTransform(key, iv, false)) { byte[] buffer2 = aesCryptoTransform.TransformFinalBlock(inputBuffer2, 0, inputBuffer2.Length); zipStream.Write(buffer2, 0, buffer2.Length); break; } } } zipStream.Flush(); zipStream.Close(); return zipStream.ToArray(); } catch (Exception ex) { SimpleZip.ExceptionMessage = "ERR 2003: " + ex.Message; throw; } } internal sealed class Inflater { private const int DECODE_HEADER = 0; private const int DECODE_DICT = 1; private const int DECODE_BLOCKS = 2; private const int DECODE_STORED_LEN1 = 3; private const int DECODE_STORED_LEN2 = 4; private const int DECODE_STORED = 5; private const int DECODE_DYN_HEADER = 6; private const int DECODE_HUFFMAN = 7; private const int DECODE_HUFFMAN_LENBITS = 8; private const int DECODE_HUFFMAN_DIST = 9; private const int DECODE_HUFFMAN_DISTBITS = 10; private const int DECODE_CHKSUM = 11; private const int FINISHED = 12; private static readonly int[] CPLENS = new int[29] { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 }; private static readonly int[] CPLEXT = new int[29] { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; private static readonly int[] CPDIST = new int[30] { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 }; private static readonly int[] CPDEXT = new int[30] { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 }; private int mode; private int neededBits; private int repLength; private int repDist; private int uncomprLen; private bool isLastBlock; private SimpleZip.StreamManipulator input; private SimpleZip.OutputWindow outputWindow; private SimpleZip.InflaterDynHeader dynHeader; private SimpleZip.InflaterHuffmanTree litlenTree; private SimpleZip.InflaterHuffmanTree distTree; public Inflater(byte[] bytes) { this.input = new SimpleZip.StreamManipulator(); this.outputWindow = new SimpleZip.OutputWindow(); this.mode = 2; this.input.SetInput(bytes, 0, bytes.Length); } private bool DecodeHuffman() { int freeSpace = this.outputWindow.GetFreeSpace(); while (freeSpace >= 258) { switch (this.mode) { case 7: int symbol1; while (((symbol1 = this.litlenTree.GetSymbol(this.input)) & -256) == 0) { this.outputWindow.Write(symbol1); if (--freeSpace < 258) return true; } if (symbol1 < 257) { if (symbol1 < 0) return false; this.distTree = (SimpleZip.InflaterHuffmanTree) null; this.litlenTree = (SimpleZip.InflaterHuffmanTree) null; this.mode = 2; return true; } this.repLength = SimpleZip.Inflater.CPLENS[symbol1 - 257]; this.neededBits = SimpleZip.Inflater.CPLEXT[symbol1 - 257]; goto case 8; case 8: if (this.neededBits > 0) { this.mode = 8; int num = this.input.PeekBits(this.neededBits); if (num < 0) return false; this.input.DropBits(this.neededBits); this.repLength += num; } this.mode = 9; goto case 9; case 9: int symbol2 = this.distTree.GetSymbol(this.input); if (symbol2 < 0) return false; this.repDist = SimpleZip.Inflater.CPDIST[symbol2]; this.neededBits = SimpleZip.Inflater.CPDEXT[symbol2]; goto case 10; case 10: if (this.neededBits > 0) { this.mode = 10; int num = this.input.PeekBits(this.neededBits); if (num < 0) return false; this.input.DropBits(this.neededBits); this.repDist += num; } this.outputWindow.Repeat(this.repLength, this.repDist); freeSpace -= this.repLength; this.mode = 7; continue; default: continue; } } return true; } private bool Decode() { switch (this.mode) { case 2: if (this.isLastBlock) { this.mode = 12; return false; } int num = this.input.PeekBits(3); if (num < 0) return false; this.input.DropBits(3); if ((num & 1) != 0) this.isLastBlock = true; switch (num >> 1) { case 0: this.input.SkipToByteBoundary(); this.mode = 3; break; case 1: this.litlenTree = SimpleZip.InflaterHuffmanTree.defLitLenTree; this.distTree = SimpleZip.InflaterHuffmanTree.defDistTree; this.mode = 7; break; case 2: this.dynHeader = new SimpleZip.InflaterDynHeader(); this.mode = 6; break; } return true; case 3: if ((this.uncomprLen = this.input.PeekBits(16)) < 0) return false; this.input.DropBits(16); this.mode = 4; goto case 4; case 4: if (this.input.PeekBits(16) < 0) return false; this.input.DropBits(16); this.mode = 5; goto case 5; case 5: this.uncomprLen -= this.outputWindow.CopyStored(this.input, this.uncomprLen); if (this.uncomprLen != 0) return !this.input.IsNeedingInput; this.mode = 2; return true; case 6: if (!this.dynHeader.Decode(this.input)) return false; this.litlenTree = this.dynHeader.BuildLitLenTree(); this.distTree = this.dynHeader.BuildDistTree(); this.mode = 7; goto case 7; case 7: case 8: case 9: case 10: return this.DecodeHuffman(); case 12: return false; default: return false; } } public int Inflate(byte[] buf, int offset, int len) { int num1 = 0; do { if (this.mode != 11) { int num2 = this.outputWindow.CopyOutput(buf, offset, len); offset += num2; num1 += num2; len -= num2; if (len == 0) return num1; } } while (this.Decode() || this.outputWindow.GetAvailable() > 0 && this.mode != 11); return num1; } } internal sealed class StreamManipulator { private byte[] window; private int window_start = 0; private int window_end = 0; private uint buffer = 0; private int bits_in_buffer = 0; public int PeekBits(int n) { if (this.bits_in_buffer < n) { if (this.window_start == this.window_end) return -1; this.buffer |= (uint) (((int) this.window[this.window_start++] & (int) byte.MaxValue | ((int) this.window[this.window_start++] & (int) byte.MaxValue) << 8) << this.bits_in_buffer); this.bits_in_buffer += 16; } return (int) ((long) this.buffer & (long) ((1 << n) - 1)); } public void DropBits(int n) { this.buffer >>= n; this.bits_in_buffer -= n; } public int AvailableBits => this.bits_in_buffer; public int AvailableBytes => this.window_end - this.window_start + (this.bits_in_buffer >> 3); public void SkipToByteBoundary() { this.buffer >>= this.bits_in_buffer & 7; this.bits_in_buffer &= -8; } public bool IsNeedingInput => this.window_start == this.window_end; public int CopyBytes(byte[] output, int offset, int length) { int num1 = 0; while (this.bits_in_buffer > 0 && length > 0) { output[offset++] = (byte) this.buffer; this.buffer >>= 8; this.bits_in_buffer -= 8; --length; ++num1; } if (length == 0) return num1; int num2 = this.window_end - this.window_start; if (length > num2) length = num2; Array.Copy((Array) this.window, this.window_start, (Array) output, offset, length); this.window_start += length; if ((this.window_start - this.window_end & 1) != 0) { this.buffer = (uint) this.window[this.window_start++] & (uint) byte.MaxValue; this.bits_in_buffer = 8; } return num1 + length; } public void Reset() => this.buffer = (uint) (this.window_start = this.window_end = this.bits_in_buffer = 0); public void SetInput(byte[] buf, int off, int len) { if (this.window_start < this.window_end) throw new InvalidOperationException(); int num = off + len; if (0 > off || off > num || num > buf.Length) throw new ArgumentOutOfRangeException(); if ((len & 1) != 0) { this.buffer |= (uint) (((int) buf[off++] & (int) byte.MaxValue) << this.bits_in_buffer); this.bits_in_buffer += 8; } this.window = buf; this.window_start = off; this.window_end = num; } } internal sealed class OutputWindow { private const int WINDOW_SIZE = 32768; private const int WINDOW_MASK = 32767; private byte[] window = new byte[32768]; private int windowEnd = 0; private int windowFilled = 0; public void Write(int abyte) { if (this.windowFilled++ == 32768) throw new InvalidOperationException(); this.window[this.windowEnd++] = (byte) abyte; this.windowEnd &= (int) short.MaxValue; } private void SlowRepeat(int repStart, int len, int dist) { while (len-- > 0) { this.window[this.windowEnd++] = this.window[repStart++]; this.windowEnd &= (int) short.MaxValue; repStart &= (int) short.MaxValue; } } public void Repeat(int len, int dist) { if ((this.windowFilled += len) > 32768) throw new InvalidOperationException(); int num1 = this.windowEnd - dist & (int) short.MaxValue; int num2 = 32768 - len; if (num1 <= num2 && this.windowEnd < num2) { if (len <= dist) { Array.Copy((Array) this.window, num1, (Array) this.window, this.windowEnd, len); this.windowEnd += len; } else { while (len-- > 0) this.window[this.windowEnd++] = this.window[num1++]; } } else this.SlowRepeat(num1, len, dist); } public int CopyStored(SimpleZip.StreamManipulator input, int len) { len = Math.Min(Math.Min(len, 32768 - this.windowFilled), input.AvailableBytes); int length = 32768 - this.windowEnd; int num; if (len > length) { num = input.CopyBytes(this.window, this.windowEnd, length); if (num == length) num += input.CopyBytes(this.window, 0, len - length); } else num = input.CopyBytes(this.window, this.windowEnd, len); this.windowEnd = this.windowEnd + num & (int) short.MaxValue; this.windowFilled += num; return num; } public void CopyDict(byte[] dict, int offset, int len) { if (this.windowFilled > 0) throw new InvalidOperationException(); if (len > 32768) { offset += len - 32768; len = 32768; } Array.Copy((Array) dict, offset, (Array) this.window, 0, len); this.windowEnd = len & (int) short.MaxValue; } public int GetFreeSpace() => 32768 - this.windowFilled; public int GetAvailable() => this.windowFilled; public int CopyOutput(byte[] output, int offset, int len) { int num1 = this.windowEnd; if (len > this.windowFilled) len = this.windowFilled; else num1 = this.windowEnd - this.windowFilled + len & (int) short.MaxValue; int num2 = len; int length = len - num1; if (length > 0) { Array.Copy((Array) this.window, 32768 - length, (Array) output, offset, length); offset += length; len = num1; } Array.Copy((Array) this.window, num1 - len, (Array) output, offset, len); this.windowFilled -= num2; if (this.windowFilled < 0) throw new InvalidOperationException(); return num2; } public void Reset() => this.windowFilled = this.windowEnd = 0; } internal sealed class InflaterHuffmanTree { private const int MAX_BITLEN = 15; private short[] tree; public static readonly SimpleZip.InflaterHuffmanTree defLitLenTree; public static readonly SimpleZip.InflaterHuffmanTree defDistTree; static InflaterHuffmanTree() { byte[] codeLengths1 = new byte[288]; int num1 = 0; while (num1 < 144) codeLengths1[num1++] = (byte) 8; while (num1 < 256) codeLengths1[num1++] = (byte) 9; while (num1 < 280) codeLengths1[num1++] = (byte) 7; while (num1 < 288) codeLengths1[num1++] = (byte) 8; SimpleZip.InflaterHuffmanTree.defLitLenTree = new SimpleZip.InflaterHuffmanTree(codeLengths1); byte[] codeLengths2 = new byte[32]; int num2 = 0; while (num2 < 32) codeLengths2[num2++] = (byte) 5; SimpleZip.InflaterHuffmanTree.defDistTree = new SimpleZip.InflaterHuffmanTree(codeLengths2); } public InflaterHuffmanTree(byte[] codeLengths) => this.BuildTree(codeLengths); private void BuildTree(byte[] codeLengths) { int[] numArray1 = new int[16]; int[] numArray2 = new int[16]; for (int index = 0; index < codeLengths.Length; ++index) { int codeLength = (int) codeLengths[index]; if (codeLength > 0) ++numArray1[codeLength]; } int num1 = 0; int length = 512; for (int index = 1; index <= 15; ++index) { numArray2[index] = num1; num1 += numArray1[index] << 16 - index; if (index >= 10) { int num2 = numArray2[index] & 130944; int num3 = num1 & 130944; length += num3 - num2 >> 16 - index; } } this.tree = new short[length]; int num4 = 512; for (int index = 15; index >= 10; --index) { int num5 = num1 & 130944; num1 -= numArray1[index] << 16 - index; for (int toReverse = num1 & 130944; toReverse < num5; toReverse += 128) { this.tree[(int) SimpleZip.DeflaterHuffman.BitReverse(toReverse)] = (short) (-num4 << 4 | index); num4 += 1 << index - 9; } } for (int index1 = 0; index1 < codeLengths.Length; ++index1) { int codeLength = (int) codeLengths[index1]; if (codeLength != 0) { int toReverse = numArray2[codeLength]; int index2 = (int) SimpleZip.DeflaterHuffman.BitReverse(toReverse); if (codeLength <= 9) { do { this.tree[index2] = (short) (index1 << 4 | codeLength); index2 += 1 << codeLength; } while (index2 < 512); } else { int num6 = (int) this.tree[index2 & 511]; int num7 = 1 << (num6 & 15); int num8 = -(num6 >> 4); do { this.tree[num8 | index2 >> 9] = (short) (index1 << 4 | codeLength); index2 += 1 << codeLength; } while (index2 < num7); } numArray2[codeLength] = toReverse + (1 << 16 - codeLength); } } } public int GetSymbol(SimpleZip.StreamManipulator input) { int index; if ((index = input.PeekBits(9)) >= 0) { int num1; if ((num1 = (int) this.tree[index]) >= 0) { input.DropBits(num1 & 15); return num1 >> 4; } int num2 = -(num1 >> 4); int n = num1 & 15; int num3; if ((num3 = input.PeekBits(n)) >= 0) { int num4 = (int) this.tree[num2 | num3 >> 9]; input.DropBits(num4 & 15); return num4 >> 4; } int availableBits = input.AvailableBits; int num5 = input.PeekBits(availableBits); int num6 = (int) this.tree[num2 | num5 >> 9]; if ((num6 & 15) > availableBits) return -1; input.DropBits(num6 & 15); return num6 >> 4; } int availableBits1 = input.AvailableBits; int num = (int) this.tree[input.PeekBits(availableBits1)]; if (num < 0 || (num & 15) > availableBits1) return -1; input.DropBits(num & 15); return num >> 4; } } internal sealed class InflaterDynHeader { private const int LNUM = 0; private const int DNUM = 1; private const int BLNUM = 2; private const int BLLENS = 3; private const int LENS = 4; private const int REPS = 5; private static readonly int[] repMin = new int[3] { 3, 3, 11 }; private static readonly int[] repBits = new int[3] { 2, 3, 7 }; private byte[] blLens; private byte[] litdistLens; private SimpleZip.InflaterHuffmanTree blTree; private int mode; private int lnum; private int dnum; private int blnum; private int num; private int repSymbol; private byte lastLen; private int ptr; private static readonly int[] BL_ORDER = new int[19] { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; public bool Decode(SimpleZip.StreamManipulator input) { while (true) { switch (this.mode) { case 0: this.lnum = input.PeekBits(5); if (this.lnum >= 0) { this.lnum += 257; input.DropBits(5); this.mode = 1; goto case 1; } else goto label_2; case 1: this.dnum = input.PeekBits(5); if (this.dnum >= 0) { ++this.dnum; input.DropBits(5); this.num = this.lnum + this.dnum; this.litdistLens = new byte[this.num]; this.mode = 2; goto case 2; } else goto label_5; case 2: this.blnum = input.PeekBits(4); if (this.blnum >= 0) { this.blnum += 4; input.DropBits(4); this.blLens = new byte[19]; this.ptr = 0; this.mode = 3; goto case 3; } else goto label_8; case 3: for (; this.ptr < this.blnum; ++this.ptr) { int num = input.PeekBits(3); if (num < 0) return false; input.DropBits(3); this.blLens[SimpleZip.InflaterDynHeader.BL_ORDER[this.ptr]] = (byte) num; } this.blTree = new SimpleZip.InflaterHuffmanTree(this.blLens); this.blLens = (byte[]) null; this.ptr = 0; this.mode = 4; goto case 4; case 4: int symbol; while (((symbol = this.blTree.GetSymbol(input)) & -16) == 0) { this.litdistLens[this.ptr++] = this.lastLen = (byte) symbol; if (this.ptr == this.num) return true; } if (symbol >= 0) { if (symbol >= 17) this.lastLen = (byte) 0; this.repSymbol = symbol - 16; this.mode = 5; goto case 5; } else goto label_19; case 5: int repBit = SimpleZip.InflaterDynHeader.repBits[this.repSymbol]; int num1 = input.PeekBits(repBit); if (num1 >= 0) { input.DropBits(repBit); int num2 = num1 + SimpleZip.InflaterDynHeader.repMin[this.repSymbol]; while (num2-- > 0) this.litdistLens[this.ptr++] = this.lastLen; if (this.ptr != this.num) { this.mode = 4; continue; } goto label_29; } else goto label_24; default: continue; } } label_2: return false; label_5: return false; label_8: return false; label_19: return false; label_24: return false; label_29: return true; } public SimpleZip.InflaterHuffmanTree BuildLitLenTree() { byte[] numArray = new byte[this.lnum]; Array.Copy((Array) this.litdistLens, 0, (Array) numArray, 0, this.lnum); return new SimpleZip.InflaterHuffmanTree(numArray); } public SimpleZip.InflaterHuffmanTree BuildDistTree() { byte[] numArray = new byte[this.dnum]; Array.Copy((Array) this.litdistLens, this.lnum, (Array) numArray, 0, this.dnum); return new SimpleZip.InflaterHuffmanTree(numArray); } } internal sealed class Deflater { private const int IS_FLUSHING = 4; private const int IS_FINISHING = 8; private const int BUSY_STATE = 16; private const int FLUSHING_STATE = 20; private const int FINISHING_STATE = 28; private const int FINISHED_STATE = 30; private int state = 16; private long totalOut = 0; private SimpleZip.DeflaterPending pending; private SimpleZip.DeflaterEngine engine; public Deflater() { this.pending = new SimpleZip.DeflaterPending(); this.engine = new SimpleZip.DeflaterEngine(this.pending); } public long TotalOut => this.totalOut; public void Finish() => this.state |= 12; public bool IsFinished => this.state == 30 && this.pending.IsFlushed; public bool IsNeedingInput => this.engine.NeedsInput(); public void SetInput(byte[] buffer) => this.engine.SetInput(buffer); public int Deflate(byte[] output) { int offset = 0; int length = output.Length; int num1 = length; while (true) { do { do { int num2 = this.pending.Flush(output, offset, length); offset += num2; this.totalOut += (long) num2; length -= num2; if (length == 0 || this.state == 30) goto label_12; } while (this.engine.Deflate((this.state & 4) != 0, (this.state & 8) != 0)); if (this.state == 16) return num1 - length; if (this.state == 20) { for (int index = 8 + (-this.pending.BitCount & 7); index > 0; index -= 10) this.pending.WriteBits(2, 10); this.state = 16; } } while (this.state != 28); this.pending.AlignToByte(); this.state = 30; } label_12: return num1 - length; } } internal sealed class DeflaterHuffman { private const int BUFSIZE = 16384; private const int LITERAL_NUM = 286; private const int DIST_NUM = 30; private const int BITLEN_NUM = 19; private const int REP_3_6 = 16; private const int REP_3_10 = 17; private const int REP_11_138 = 18; private const int EOF_SYMBOL = 256; private static readonly int[] BL_ORDER = new int[19] { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; private static readonly byte[] bit4Reverse = new byte[16] { (byte) 0, (byte) 8, (byte) 4, (byte) 12, (byte) 2, (byte) 10, (byte) 6, (byte) 14, (byte) 1, (byte) 9, (byte) 5, (byte) 13, (byte) 3, (byte) 11, (byte) 7, (byte) 15 }; private SimpleZip.DeflaterPending pending; private SimpleZip.DeflaterHuffman.Tree literalTree; private SimpleZip.DeflaterHuffman.Tree distTree; private SimpleZip.DeflaterHuffman.Tree blTree; private short[] d_buf; private byte[] l_buf; private int last_lit; private int extra_bits; private static readonly short[] staticLCodes = new short[286]; private static readonly byte[] staticLLength = new byte[286]; private static readonly short[] staticDCodes; private static readonly byte[] staticDLength; public static short BitReverse(int toReverse) => (short) ((int) SimpleZip.DeflaterHuffman.bit4Reverse[toReverse & 15] << 12 | (int) SimpleZip.DeflaterHuffman.bit4Reverse[toReverse >> 4 & 15] << 8 | (int) SimpleZip.DeflaterHuffman.bit4Reverse[toReverse >> 8 & 15] << 4 | (int) SimpleZip.DeflaterHuffman.bit4Reverse[toReverse >> 12]); static DeflaterHuffman() { int index1; for (index1 = 0; index1 < 144; SimpleZip.DeflaterHuffman.staticLLength[index1++] = (byte) 8) SimpleZip.DeflaterHuffman.staticLCodes[index1] = SimpleZip.DeflaterHuffman.BitReverse(48 + index1 << 8); for (; index1 < 256; SimpleZip.DeflaterHuffman.staticLLength[index1++] = (byte) 9) SimpleZip.DeflaterHuffman.staticLCodes[index1] = SimpleZip.DeflaterHuffman.BitReverse(256 + index1 << 7); for (; index1 < 280; SimpleZip.DeflaterHuffman.staticLLength[index1++] = (byte) 7) SimpleZip.DeflaterHuffman.staticLCodes[index1] = SimpleZip.DeflaterHuffman.BitReverse(index1 - 256 << 9); for (; index1 < 286; SimpleZip.DeflaterHuffman.staticLLength[index1++] = (byte) 8) SimpleZip.DeflaterHuffman.staticLCodes[index1] = SimpleZip.DeflaterHuffman.BitReverse(index1 - 88 << 8); SimpleZip.DeflaterHuffman.staticDCodes = new short[30]; SimpleZip.DeflaterHuffman.staticDLength = new byte[30]; for (int index2 = 0; index2 < 30; ++index2) { SimpleZip.DeflaterHuffman.staticDCodes[index2] = SimpleZip.DeflaterHuffman.BitReverse(index2 << 11); SimpleZip.DeflaterHuffman.staticDLength[index2] = (byte) 5; } } public DeflaterHuffman(SimpleZip.DeflaterPending pending) { this.pending = pending; this.literalTree = new SimpleZip.DeflaterHuffman.Tree(this, 286, 257, 15); this.distTree = new SimpleZip.DeflaterHuffman.Tree(this, 30, 1, 15); this.blTree = new SimpleZip.DeflaterHuffman.Tree(this, 19, 4, 7); this.d_buf = new short[16384]; this.l_buf = new byte[16384]; } public void Init() { this.last_lit = 0; this.extra_bits = 0; } private int Lcode(int len) { if (len == (int) byte.MaxValue) return 285; int num = 257; for (; len >= 8; len >>= 1) num += 4; return num + len; } private int Dcode(int distance) { int num = 0; for (; distance >= 4; distance >>= 1) num += 2; return num + distance; } public void SendAllTrees(int blTreeCodes) { this.blTree.BuildCodes(); this.literalTree.BuildCodes(); this.distTree.BuildCodes(); this.pending.WriteBits(this.literalTree.numCodes - 257, 5); this.pending.WriteBits(this.distTree.numCodes - 1, 5); this.pending.WriteBits(blTreeCodes - 4, 4); for (int index = 0; index < blTreeCodes; ++index) this.pending.WriteBits((int) this.blTree.length[SimpleZip.DeflaterHuffman.BL_ORDER[index]], 3); this.literalTree.WriteTree(this.blTree); this.distTree.WriteTree(this.blTree); } public void CompressBlock() { for (int index = 0; index < this.last_lit; ++index) { int num1 = (int) this.l_buf[index] & (int) byte.MaxValue; int num2 = (int) this.d_buf[index]; int distance = num2 - 1; if (num2 != 0) { int code1 = this.Lcode(num1); this.literalTree.WriteSymbol(code1); int count1 = (code1 - 261) / 4; if (count1 > 0 && count1 <= 5) this.pending.WriteBits(num1 & (1 << count1) - 1, count1); int code2 = this.Dcode(distance); this.distTree.WriteSymbol(code2); int count2 = code2 / 2 - 1; if (count2 > 0) this.pending.WriteBits(distance & (1 << count2) - 1, count2); } else this.literalTree.WriteSymbol(num1); } this.literalTree.WriteSymbol(256); } public void FlushStoredBlock( byte[] stored, int storedOffset, int storedLength, bool lastBlock) { this.pending.WriteBits(lastBlock ? 1 : 0, 3); this.pending.AlignToByte(); this.pending.WriteShort(storedLength); this.pending.WriteShort(~storedLength); this.pending.WriteBlock(stored, storedOffset, storedLength); this.Init(); } public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock) { short[] freqs; (freqs = this.literalTree.freqs)[256] = (short) ((int) freqs[256] + 1); this.literalTree.BuildTree(); this.distTree.BuildTree(); this.literalTree.CalcBLFreq(this.blTree); this.distTree.CalcBLFreq(this.blTree); this.blTree.BuildTree(); int blTreeCodes = 4; for (int index = 18; index > blTreeCodes; --index) { if (this.blTree.length[SimpleZip.DeflaterHuffman.BL_ORDER[index]] > (byte) 0) blTreeCodes = index + 1; } int num = 14 + blTreeCodes * 3 + this.blTree.GetEncodedLength() + this.literalTree.GetEncodedLength() + this.distTree.GetEncodedLength() + this.extra_bits; int extraBits = this.extra_bits; for (int index = 0; index < 286; ++index) extraBits += (int) this.literalTree.freqs[index] * (int) SimpleZip.DeflaterHuffman.staticLLength[index]; for (int index = 0; index < 30; ++index) extraBits += (int) this.distTree.freqs[index] * (int) SimpleZip.DeflaterHuffman.staticDLength[index]; if (num >= extraBits) num = extraBits; if (storedOffset >= 0 && storedLength + 4 < num >> 3) this.FlushStoredBlock(stored, storedOffset, storedLength, lastBlock); else if (num == extraBits) { this.pending.WriteBits(2 + (lastBlock ? 1 : 0), 3); this.literalTree.SetStaticCodes(SimpleZip.DeflaterHuffman.staticLCodes, SimpleZip.DeflaterHuffman.staticLLength); this.distTree.SetStaticCodes(SimpleZip.DeflaterHuffman.staticDCodes, SimpleZip.DeflaterHuffman.staticDLength); this.CompressBlock(); this.Init(); } else { this.pending.WriteBits(4 + (lastBlock ? 1 : 0), 3); this.SendAllTrees(blTreeCodes); this.CompressBlock(); this.Init(); } } public bool IsFull() => this.last_lit >= 16384; public bool TallyLit(int lit) { this.d_buf[this.last_lit] = (short) 0; this.l_buf[this.last_lit++] = (byte) lit; short[] freqs; IntPtr index; (freqs = this.literalTree.freqs)[(int) (index = (IntPtr) lit)] = (short) ((int) freqs[index] + 1); return this.IsFull(); } public bool TallyDist(int dist, int len) { this.d_buf[this.last_lit] = (short) dist; this.l_buf[this.last_lit++] = (byte) (len - 3); int num1 = this.Lcode(len - 3); short[] freqs1; IntPtr index1; (freqs1 = this.literalTree.freqs)[(int) (index1 = (IntPtr) num1)] = (short) ((int) freqs1[index1] + 1); if (num1 >= 265 && num1 < 285) this.extra_bits += (num1 - 261) / 4; int num2 = this.Dcode(dist - 1); short[] freqs2; IntPtr index2; (freqs2 = this.distTree.freqs)[(int) (index2 = (IntPtr) num2)] = (short) ((int) freqs2[index2] + 1); if (num2 >= 4) this.extra_bits += num2 / 2 - 1; return this.IsFull(); } public sealed class Tree { public short[] freqs; public byte[] length; public int minNumCodes; public int numCodes; private short[] codes; private int[] bl_counts; private int maxLength; private SimpleZip.DeflaterHuffman dh; public Tree(SimpleZip.DeflaterHuffman dh, int elems, int minCodes, int maxLength) { this.dh = dh; this.minNumCodes = minCodes; this.maxLength = maxLength; this.freqs = new short[elems]; this.bl_counts = new int[maxLength]; } public void WriteSymbol(int code) => this.dh.pending.WriteBits((int) this.codes[code] & (int) ushort.MaxValue, (int) this.length[code]); public void SetStaticCodes(short[] stCodes, byte[] stLength) { this.codes = stCodes; this.length = stLength; } public void BuildCodes() { int length = this.freqs.Length; int[] numArray = new int[this.maxLength]; int num1 = 0; this.codes = new short[this.freqs.Length]; for (int index = 0; index < this.maxLength; ++index) { numArray[index] = num1; num1 += this.bl_counts[index] << 15 - index; } for (int index = 0; index < this.numCodes; ++index) { int num2 = (int) this.length[index]; if (num2 > 0) { this.codes[index] = SimpleZip.DeflaterHuffman.BitReverse(numArray[num2 - 1]); numArray[num2 - 1] += 1 << 16 - num2; } } } private void BuildLength(int[] childs) { this.length = new byte[this.freqs.Length]; int length = childs.Length / 2; int num1 = (length + 1) / 2; int num2 = 0; for (int index = 0; index < this.maxLength; ++index) this.bl_counts[index] = 0; int[] numArray1 = new int[length]; numArray1[length - 1] = 0; for (int index = length - 1; index >= 0; --index) { if (childs[2 * index + 1] != -1) { int num3 = numArray1[index] + 1; if (num3 > this.maxLength) { num3 = this.maxLength; ++num2; } numArray1[childs[2 * index]] = numArray1[childs[2 * index + 1]] = num3; } else { ++this.bl_counts[numArray1[index] - 1]; this.length[childs[2 * index]] = (byte) numArray1[index]; } } if (num2 == 0) return; int index1 = this.maxLength - 1; do { do ; while (this.bl_counts[--index1] == 0); do { --this.bl_counts[index1]; int[] blCounts; int[] numArray2 = blCounts = this.bl_counts; int index2; index1 = index2 = index1 + 1; int index3 = index2; int num4 = numArray2[(IntPtr) index3] + 1; blCounts[index2] = num4; num2 -= 1 << this.maxLength - 1 - index1; } while (num2 > 0 && index1 < this.maxLength - 1); } while (num2 > 0); this.bl_counts[this.maxLength - 1] += num2; this.bl_counts[this.maxLength - 2] -= num2; int num5 = 2 * num1; for (int maxLength = this.maxLength; maxLength != 0; --maxLength) { int blCount = this.bl_counts[maxLength - 1]; while (blCount > 0) { int index4 = 2 * childs[num5++]; if (childs[index4 + 1] == -1) { this.length[childs[index4]] = (byte) maxLength; --blCount; } } } } public void BuildTree() { int length = this.freqs.Length; int[] numArray1 = new int[length]; int num1 = 0; int num2 = 0; for (int index1 = 0; index1 < length; ++index1) { int freq = (int) this.freqs[index1]; if (freq != 0) { int index2; int index3; for (index2 = num1++; index2 > 0 && (int) this.freqs[numArray1[index3 = (index2 - 1) / 2]] > freq; index2 = index3) numArray1[index2] = numArray1[index3]; numArray1[index2] = index1; num2 = index1; } } int num3; for (; num1 < 2; numArray1[num1++] = num3) { int num4; if (num2 >= 2) num4 = 0; else num2 = num4 = num2 + 1; num3 = num4; } this.numCodes = Math.Max(num2 + 1, this.minNumCodes); int num5 = num1; int[] childs = new int[4 * num1 - 2]; int[] numArray2 = new int[2 * num1 - 1]; int num6 = num5; for (int index4 = 0; index4 < num1; ++index4) { int index5 = numArray1[index4]; childs[2 * index4] = index5; childs[2 * index4 + 1] = -1; numArray2[index4] = (int) this.freqs[index5] << 8; numArray1[index4] = index4; } do { int index6 = numArray1[0]; int index7 = numArray1[--num1]; int index8 = 0; for (int index9 = 1; index9 < num1; index9 = index9 * 2 + 1) { if (index9 + 1 < num1 && numArray2[numArray1[index9]] > numArray2[numArray1[index9 + 1]]) ++index9; numArray1[index8] = numArray1[index9]; index8 = index9; } int num7 = numArray2[index7]; int index10; while ((index10 = index8) > 0 && numArray2[numArray1[index8 = (index10 - 1) / 2]] > num7) numArray1[index10] = numArray1[index8]; numArray1[index10] = index7; int index11 = numArray1[0]; int index12 = num6++; childs[2 * index12] = index6; childs[2 * index12 + 1] = index11; int num8 = Math.Min(numArray2[index6] & (int) byte.MaxValue, numArray2[index11] & (int) byte.MaxValue); int num9; numArray2[index12] = num9 = numArray2[index6] + numArray2[index11] - num8 + 1; int index13 = 0; for (int index14 = 1; index14 < num1; index14 = index13 * 2 + 1) { if (index14 + 1 < num1 && numArray2[numArray1[index14]] > numArray2[numArray1[index14 + 1]]) ++index14; numArray1[index13] = numArray1[index14]; index13 = index14; } int index15; while ((index15 = index13) > 0 && numArray2[numArray1[index13 = (index15 - 1) / 2]] > num9) numArray1[index15] = numArray1[index13]; numArray1[index15] = index12; } while (num1 > 1); this.BuildLength(childs); } public int GetEncodedLength() { int encodedLength = 0; for (int index = 0; index < this.freqs.Length; ++index) encodedLength += (int) this.freqs[index] * (int) this.length[index]; return encodedLength; } public void CalcBLFreq(SimpleZip.DeflaterHuffman.Tree blTree) { int num1 = -1; int index1 = 0; while (index1 < this.numCodes) { int num2 = 1; int num3 = (int) this.length[index1]; int num4; int num5; if (num3 == 0) { num4 = 138; num5 = 3; } else { num4 = 6; num5 = 3; if (num1 != num3) { short[] freqs; IntPtr index2; (freqs = blTree.freqs)[(int) (index2 = (IntPtr) num3)] = (short) ((int) freqs[index2] + 1); num2 = 0; } } num1 = num3; ++index1; while (index1 < this.numCodes && num1 == (int) this.length[index1]) { ++index1; if (++num2 >= num4) break; } if (num2 < num5) { short[] freqs; IntPtr index3; (freqs = blTree.freqs)[(int) (index3 = (IntPtr) num1)] = (short) ((int) freqs[index3] + (int) (short) num2); } else if (num1 != 0) { short[] freqs; (freqs = blTree.freqs)[16] = (short) ((int) freqs[16] + 1); } else if (num2 <= 10) { short[] freqs; (freqs = blTree.freqs)[17] = (short) ((int) freqs[17] + 1); } else { short[] freqs; (freqs = blTree.freqs)[18] = (short) ((int) freqs[18] + 1); } } } public void WriteTree(SimpleZip.DeflaterHuffman.Tree blTree) { int code1 = -1; int index = 0; while (index < this.numCodes) { int num1 = 1; int code2 = (int) this.length[index]; int num2; int num3; if (code2 == 0) { num2 = 138; num3 = 3; } else { num2 = 6; num3 = 3; if (code1 != code2) { blTree.WriteSymbol(code2); num1 = 0; } } code1 = code2; ++index; while (index < this.numCodes && code1 == (int) this.length[index]) { ++index; if (++num1 >= num2) break; } if (num1 < num3) { while (num1-- > 0) blTree.WriteSymbol(code1); } else if (code1 != 0) { blTree.WriteSymbol(16); this.dh.pending.WriteBits(num1 - 3, 2); } else if (num1 <= 10) { blTree.WriteSymbol(17); this.dh.pending.WriteBits(num1 - 3, 3); } else { blTree.WriteSymbol(18); this.dh.pending.WriteBits(num1 - 11, 7); } } } } } internal sealed class DeflaterEngine { private const int MAX_MATCH = 258; private const int MIN_MATCH = 3; private const int WSIZE = 32768; private const int WMASK = 32767; private const int HASH_SIZE = 32768; private const int HASH_MASK = 32767; private const int HASH_SHIFT = 5; private const int MIN_LOOKAHEAD = 262; private const int MAX_DIST = 32506; private const int TOO_FAR = 4096; private int ins_h; private short[] head; private short[] prev; private int matchStart; private int matchLen; private bool prevAvailable; private int blockStart; private int strstart; private int lookahead; private byte[] window; private byte[] inputBuf; private int totalIn; private int inputOff; private int inputEnd; private SimpleZip.DeflaterPending pending; private SimpleZip.DeflaterHuffman huffman; public DeflaterEngine(SimpleZip.DeflaterPending pending) { this.pending = pending; this.huffman = new SimpleZip.DeflaterHuffman(pending); this.window = new byte[65536]; this.head = new short[32768]; this.prev = new short[32768]; this.blockStart = this.strstart = 1; } private void UpdateHash() => this.ins_h = (int) this.window[this.strstart] << 5 ^ (int) this.window[this.strstart + 1]; private int InsertString() { int index = (this.ins_h << 5 ^ (int) this.window[this.strstart + 2]) & (int) short.MaxValue; short num; this.prev[this.strstart & (int) short.MaxValue] = num = this.head[index]; this.head[index] = (short) this.strstart; this.ins_h = index; return (int) num & (int) ushort.MaxValue; } private void SlideWindow() { Array.Copy((Array) this.window, 32768, (Array) this.window, 0, 32768); this.matchStart -= 32768; this.strstart -= 32768; this.blockStart -= 32768; for (int index = 0; index < 32768; ++index) { int num = (int) this.head[index] & (int) ushort.MaxValue; this.head[index] = num >= 32768 ? (short) (num - 32768) : (short) 0; } for (int index = 0; index < 32768; ++index) { int num = (int) this.prev[index] & (int) ushort.MaxValue; this.prev[index] = num >= 32768 ? (short) (num - 32768) : (short) 0; } } public void FillWindow() { if (this.strstart >= 65274) this.SlideWindow(); int length; for (; this.lookahead < 262 && this.inputOff < this.inputEnd; this.lookahead += length) { length = 65536 - this.lookahead - this.strstart; if (length > this.inputEnd - this.inputOff) length = this.inputEnd - this.inputOff; Array.Copy((Array) this.inputBuf, this.inputOff, (Array) this.window, this.strstart + this.lookahead, length); this.inputOff += length; this.totalIn += length; } if (this.lookahead < 3) return; this.UpdateHash(); } private bool FindLongestMatch(int curMatch) { int num1 = 128; int num2 = 128; short[] prev = this.prev; int strstart = this.strstart; int index = this.strstart + this.matchLen; int val1 = Math.Max(this.matchLen, 2); int num3 = Math.Max(this.strstart - 32506, 0); int num4 = this.strstart + 258 - 1; byte num5 = this.window[index - 1]; byte num6 = this.window[index]; if (val1 >= 8) num1 >>= 2; if (num2 > this.lookahead) num2 = this.lookahead; do { if ((int) this.window[curMatch + val1] == (int) num6 && (int) this.window[curMatch + val1 - 1] == (int) num5 && (int) this.window[curMatch] == (int) this.window[strstart] && (int) this.window[curMatch + 1] == (int) this.window[strstart + 1]) { int num7 = curMatch + 2; int num8 = strstart + 2; int num9; int num10; int num11; int num12; int num13; int num14; int num15; do ; while ((int) this.window[++num8] == (int) this.window[num9 = num7 + 1] && (int) this.window[++num8] == (int) this.window[num10 = num9 + 1] && (int) this.window[++num8] == (int) this.window[num11 = num10 + 1] && (int) this.window[++num8] == (int) this.window[num12 = num11 + 1] && (int) this.window[++num8] == (int) this.window[num13 = num12 + 1] && (int) this.window[++num8] == (int) this.window[num14 = num13 + 1] && (int) this.window[++num8] == (int) this.window[num15 = num14 + 1] && (int) this.window[++num8] == (int) this.window[num7 = num15 + 1] && num8 < num4); if (num8 > index) { this.matchStart = curMatch; index = num8; val1 = num8 - this.strstart; if (val1 < num2) { num5 = this.window[index - 1]; num6 = this.window[index]; } else break; } strstart = this.strstart; } } while ((curMatch = (int) prev[curMatch & (int) short.MaxValue] & (int) ushort.MaxValue) > num3 && --num1 != 0); this.matchLen = Math.Min(val1, this.lookahead); return this.matchLen >= 3; } private bool DeflateSlow(bool flush, bool finish) { if (this.lookahead < 262 && !flush) return false; while (this.lookahead >= 262 || flush) { if (this.lookahead == 0) { if (this.prevAvailable) this.huffman.TallyLit((int) this.window[this.strstart - 1] & (int) byte.MaxValue); this.prevAvailable = false; this.huffman.FlushBlock(this.window, this.blockStart, this.strstart - this.blockStart, finish); this.blockStart = this.strstart; return false; } if (this.strstart >= 65274) this.SlideWindow(); int matchStart = this.matchStart; int matchLen = this.matchLen; if (this.lookahead >= 3) { int curMatch = this.InsertString(); if (curMatch != 0 && this.strstart - curMatch <= 32506 && this.FindLongestMatch(curMatch) && this.matchLen <= 5 && this.matchLen == 3 && this.strstart - this.matchStart > 4096) this.matchLen = 2; } if (matchLen >= 3 && this.matchLen <= matchLen) { this.huffman.TallyDist(this.strstart - 1 - matchStart, matchLen); int num = matchLen - 2; do { ++this.strstart; --this.lookahead; if (this.lookahead >= 3) this.InsertString(); } while (--num > 0); ++this.strstart; --this.lookahead; this.prevAvailable = false; this.matchLen = 2; } else { if (this.prevAvailable) this.huffman.TallyLit((int) this.window[this.strstart - 1] & (int) byte.MaxValue); this.prevAvailable = true; ++this.strstart; --this.lookahead; } if (this.huffman.IsFull()) { int storedLength = this.strstart - this.blockStart; if (this.prevAvailable) --storedLength; bool lastBlock = finish && this.lookahead == 0 && !this.prevAvailable; this.huffman.FlushBlock(this.window, this.blockStart, storedLength, lastBlock); this.blockStart += storedLength; return !lastBlock; } } return true; } public bool Deflate(bool flush, bool finish) { bool flag; do { this.FillWindow(); flag = this.DeflateSlow(flush && this.inputOff == this.inputEnd, finish); } while (this.pending.IsFlushed && flag); return flag; } public void SetInput(byte[] buffer) { this.inputBuf = buffer; this.inputOff = 0; this.inputEnd = buffer.Length; } public bool NeedsInput() => this.inputEnd == this.inputOff; } internal sealed class DeflaterPending { protected byte[] buf = new byte[65536]; private int start = 0; private int end = 0; private uint bits = 0; private int bitCount = 0; public void WriteShort(int s) { this.buf[this.end++] = (byte) s; this.buf[this.end++] = (byte) (s >> 8); } public void WriteBlock(byte[] block, int offset, int len) { Array.Copy((Array) block, offset, (Array) this.buf, this.end, len); this.end += len; } public int BitCount => this.bitCount; public void AlignToByte() { if (this.bitCount > 0) { this.buf[this.end++] = (byte) this.bits; if (this.bitCount > 8) this.buf[this.end++] = (byte) (this.bits >> 8); } this.bits = 0U; this.bitCount = 0; } public void WriteBits(int b, int count) { this.bits |= (uint) (b << this.bitCount); this.bitCount += count; if (this.bitCount < 16) return; this.buf[this.end++] = (byte) this.bits; this.buf[this.end++] = (byte) (this.bits >> 8); this.bits >>= 16; this.bitCount -= 16; } public bool IsFlushed => this.end == 0; public int Flush(byte[] output, int offset, int length) { if (this.bitCount >= 8) { this.buf[this.end++] = (byte) this.bits; this.bits >>= 8; this.bitCount -= 8; } if (length > this.end - this.start) { length = this.end - this.start; Array.Copy((Array) this.buf, this.start, (Array) output, offset, length); this.start = 0; this.end = 0; } else { Array.Copy((Array) this.buf, this.start, (Array) output, offset, length); this.start += length; } return length; } } internal sealed class ZipStream : MemoryStream { public void WriteShort(int value) { this.WriteByte((byte) (value & (int) byte.MaxValue)); this.WriteByte((byte) (value >> 8 & (int) byte.MaxValue)); } public void WriteInt(int value) { this.WriteShort(value); this.WriteShort(value >> 16); } public int ReadShort() => this.ReadByte() | this.ReadByte() << 8; public int ReadInt() => this.ReadShort() | this.ReadShort() << 16; public ZipStream() { } public ZipStream(byte[] buffer) : base(buffer, false) { } } } }