342 lines
6.9 KiB
C#
342 lines
6.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.IO;
|
|
|
|
using UniversalEditor.Compression.Modules.Deflate.Internal;
|
|
using UniversalEditor.Compression.Common;
|
|
|
|
namespace UniversalEditor.Compression.Modules.Gzip.Internal
|
|
{
|
|
internal class GzipDecoder
|
|
{
|
|
private const int CommentFlag = 16;
|
|
private const int CRCFlag = 2;
|
|
private const int ExtraFieldsFlag = 4;
|
|
private const int FileNameFlag = 8;
|
|
private const int FileText = 1;
|
|
private int gzip_header_flag;
|
|
private int gzip_header_xlen;
|
|
private uint gzipCrc32;
|
|
private GzipHeaderState gzipFooterSubstate;
|
|
private GzipHeaderState gzipHeaderSubstate;
|
|
private uint gzipOutputStreamSize;
|
|
private InputBuffer input;
|
|
private int loopCounter;
|
|
public uint Crc32
|
|
{
|
|
get
|
|
{
|
|
return this.gzipCrc32;
|
|
}
|
|
}
|
|
public uint StreamSize
|
|
{
|
|
get
|
|
{
|
|
return this.gzipOutputStreamSize;
|
|
}
|
|
}
|
|
public GzipDecoder(InputBuffer input)
|
|
{
|
|
this.input = input;
|
|
this.Reset();
|
|
}
|
|
public bool ReadGzipFooter()
|
|
{
|
|
this.input.SkipToByteBoundary();
|
|
bool result;
|
|
if (this.gzipFooterSubstate == GzipHeaderState.ReadingCRC)
|
|
{
|
|
while (this.loopCounter < 4)
|
|
{
|
|
int bits = this.input.GetBits(8);
|
|
if (bits < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
this.gzipCrc32 |= (uint)((uint)bits << 8 * this.loopCounter);
|
|
this.loopCounter++;
|
|
}
|
|
this.gzipFooterSubstate = GzipHeaderState.ReadingFileSize;
|
|
this.loopCounter = 0;
|
|
}
|
|
if (this.gzipFooterSubstate == GzipHeaderState.ReadingFileSize)
|
|
{
|
|
if (this.loopCounter == 0)
|
|
{
|
|
this.gzipOutputStreamSize = 0u;
|
|
}
|
|
while (this.loopCounter < 4)
|
|
{
|
|
int num2 = this.input.GetBits(8);
|
|
if (num2 < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
this.gzipOutputStreamSize |= (uint)((uint)num2 << 8 * this.loopCounter);
|
|
this.loopCounter++;
|
|
}
|
|
}
|
|
result = true;
|
|
return result;
|
|
}
|
|
public bool ReadGzipHeader()
|
|
{
|
|
int bits;
|
|
bool result;
|
|
switch (this.gzipHeaderSubstate)
|
|
{
|
|
case GzipHeaderState.ReadingID1:
|
|
{
|
|
bits = this.input.GetBits(8);
|
|
if (bits < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
if (bits != 31)
|
|
{
|
|
throw new InvalidDataException("CorruptedGZipHeader");
|
|
}
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingID2;
|
|
break;
|
|
}
|
|
case GzipHeaderState.ReadingID2:
|
|
{
|
|
break;
|
|
}
|
|
case GzipHeaderState.ReadingCM:
|
|
{
|
|
goto IL_114;
|
|
}
|
|
case GzipHeaderState.ReadingFLG:
|
|
{
|
|
goto IL_14F;
|
|
}
|
|
case GzipHeaderState.ReadingMMTime:
|
|
{
|
|
goto IL_184;
|
|
}
|
|
case GzipHeaderState.ReadingXFL:
|
|
{
|
|
goto IL_1D1;
|
|
}
|
|
case GzipHeaderState.ReadingOS:
|
|
{
|
|
goto IL_1F6;
|
|
}
|
|
case GzipHeaderState.ReadingXLen1:
|
|
{
|
|
goto IL_21B;
|
|
}
|
|
case GzipHeaderState.ReadingXLen2:
|
|
{
|
|
goto IL_261;
|
|
}
|
|
case GzipHeaderState.ReadingXLenData:
|
|
{
|
|
goto IL_2A0;
|
|
}
|
|
case GzipHeaderState.ReadingFileName:
|
|
{
|
|
goto IL_2F3;
|
|
}
|
|
case GzipHeaderState.ReadingComment:
|
|
{
|
|
goto IL_348;
|
|
}
|
|
case GzipHeaderState.ReadingCRC16Part1:
|
|
{
|
|
goto IL_39B;
|
|
}
|
|
case GzipHeaderState.ReadingCRC16Part2:
|
|
{
|
|
goto IL_3DB;
|
|
}
|
|
case GzipHeaderState.Done:
|
|
{
|
|
goto IL_3FE;
|
|
}
|
|
default:
|
|
{
|
|
throw new InvalidDataException("UnknownState");
|
|
}
|
|
}
|
|
bits = this.input.GetBits(8);
|
|
if (bits < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
if (bits != 139)
|
|
{
|
|
throw new InvalidDataException("CorruptedGZipHeader");
|
|
}
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingCM;
|
|
IL_114:
|
|
bits = this.input.GetBits(8);
|
|
if (bits < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
if (bits != 8)
|
|
{
|
|
throw new InvalidDataException("UnknownCompressionMode");
|
|
}
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingFLG;
|
|
IL_14F:
|
|
bits = this.input.GetBits(8);
|
|
if (bits < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
this.gzip_header_flag = bits;
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingMMTime;
|
|
this.loopCounter = 0;
|
|
IL_184:
|
|
while (this.loopCounter < 4)
|
|
{
|
|
if (this.input.GetBits(8) < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
this.loopCounter++;
|
|
}
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingXFL;
|
|
this.loopCounter = 0;
|
|
IL_1D1:
|
|
if (this.input.GetBits(8) < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingOS;
|
|
IL_1F6:
|
|
if (this.input.GetBits(8) < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingXLen1;
|
|
IL_21B:
|
|
if ((this.gzip_header_flag & 4) == 0)
|
|
{
|
|
goto IL_2F3;
|
|
}
|
|
bits = this.input.GetBits(8);
|
|
if (bits < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
this.gzip_header_xlen = bits;
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingXLen2;
|
|
IL_261:
|
|
bits = this.input.GetBits(8);
|
|
if (bits < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
this.gzip_header_xlen |= bits << 8;
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingXLenData;
|
|
this.loopCounter = 0;
|
|
IL_2A0:
|
|
while (this.loopCounter < this.gzip_header_xlen)
|
|
{
|
|
if (this.input.GetBits(8) < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
this.loopCounter++;
|
|
}
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingFileName;
|
|
this.loopCounter = 0;
|
|
IL_2F3:
|
|
if ((this.gzip_header_flag & 8) == 0)
|
|
{
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingComment;
|
|
}
|
|
else
|
|
{
|
|
while (true)
|
|
{
|
|
bits = this.input.GetBits(8);
|
|
if (bits < 0)
|
|
{
|
|
break;
|
|
}
|
|
if (bits == 0)
|
|
{
|
|
goto Block_20;
|
|
}
|
|
}
|
|
result = false;
|
|
return result;
|
|
Block_20:
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingComment;
|
|
}
|
|
IL_348:
|
|
if ((this.gzip_header_flag & 16) == 0)
|
|
{
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingCRC16Part1;
|
|
}
|
|
else
|
|
{
|
|
while (true)
|
|
{
|
|
bits = this.input.GetBits(8);
|
|
if (bits < 0)
|
|
{
|
|
break;
|
|
}
|
|
if (bits == 0)
|
|
{
|
|
goto Block_23;
|
|
}
|
|
}
|
|
result = false;
|
|
return result;
|
|
Block_23:
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingCRC16Part1;
|
|
}
|
|
IL_39B:
|
|
if ((this.gzip_header_flag & 2) == 0)
|
|
{
|
|
this.gzipHeaderSubstate = GzipHeaderState.Done;
|
|
goto IL_3FE;
|
|
}
|
|
if (this.input.GetBits(8) < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingCRC16Part2;
|
|
IL_3DB:
|
|
if (this.input.GetBits(8) < 0)
|
|
{
|
|
result = false;
|
|
return result;
|
|
}
|
|
this.gzipHeaderSubstate = GzipHeaderState.Done;
|
|
IL_3FE:
|
|
result = true;
|
|
return result;
|
|
}
|
|
public void Reset()
|
|
{
|
|
this.gzipHeaderSubstate = GzipHeaderState.ReadingID1;
|
|
this.gzipFooterSubstate = GzipHeaderState.ReadingCRC;
|
|
this.gzipCrc32 = 0u;
|
|
this.gzipOutputStreamSize = 0u;
|
|
}
|
|
}
|
|
}
|