mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-10-06 12:37:28 -04:00
124 lines
3.0 KiB
C#
124 lines
3.0 KiB
C#
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
|
using System;
|
|
using System.IO;
|
|
|
|
namespace ClassicalSharp.Network {
|
|
|
|
internal class GZipHeaderReader {
|
|
|
|
enum State {
|
|
Header1, Header2, CompressionMethod, Flags,
|
|
LastModifiedTime, CompressionFlags, OperatingSystem,
|
|
HeaderChecksum, Filename, Comment, Done,
|
|
}
|
|
|
|
State state = State.Header1;
|
|
public bool done;
|
|
int flags;
|
|
int partsRead;
|
|
|
|
public bool ReadHeader( Stream s ) {
|
|
switch( state ) {
|
|
|
|
case State.Header1:
|
|
if( !ReadAndCheckHeaderByte( s, 0x1F ) )
|
|
return false;
|
|
goto case State.Header2;
|
|
|
|
case State.Header2:
|
|
if( !ReadAndCheckHeaderByte( s, 0x8B ) )
|
|
return false;
|
|
goto case State.CompressionMethod;
|
|
|
|
case State.CompressionMethod:
|
|
if( !ReadAndCheckHeaderByte( s, 0x08 ) )
|
|
return false;
|
|
goto case State.Flags;
|
|
|
|
case State.Flags:
|
|
if( !ReadHeaderByte( s, out flags ) )
|
|
return false;
|
|
if( (flags & 0x04) != 0 )
|
|
throw new NotSupportedException( "Unsupported gzip flags: " + flags );
|
|
goto case State.LastModifiedTime;
|
|
|
|
case State.LastModifiedTime:
|
|
for( ; partsRead < 4; partsRead++ ) {
|
|
int part = s.ReadByte();
|
|
if( part == -1 )
|
|
return false;
|
|
}
|
|
partsRead = 0;
|
|
state = State.CompressionFlags;
|
|
goto case State.CompressionFlags;
|
|
|
|
case State.CompressionFlags:
|
|
int comFlags;
|
|
if( !ReadHeaderByte( s, out comFlags ) )
|
|
return false;
|
|
goto case State.OperatingSystem;
|
|
|
|
case State.OperatingSystem:
|
|
int os;
|
|
if( !ReadHeaderByte( s, out os ) )
|
|
return false;
|
|
goto case State.Filename;
|
|
|
|
case State.Filename:
|
|
if( (flags & 0x08) != 0 ) {
|
|
for( ; ; ) {
|
|
int part = s.ReadByte();
|
|
if( part == -1 ) return false;
|
|
if( part == 0 ) break;
|
|
}
|
|
}
|
|
state = State.Comment;
|
|
goto case State.Comment;
|
|
|
|
case State.Comment:
|
|
if( (flags & 0x10) != 0 ) {
|
|
for( ; ; ) {
|
|
int part = s.ReadByte();
|
|
if( part == -1 ) return false;
|
|
if( part == 0 ) break;
|
|
}
|
|
}
|
|
state = State.HeaderChecksum;
|
|
goto case State.HeaderChecksum;
|
|
|
|
case State.HeaderChecksum:
|
|
if( ( flags & 0x02 ) != 0 ) {
|
|
for( ; partsRead < 2; partsRead++ ) {
|
|
int part = s.ReadByte();
|
|
if( part == -1 )
|
|
return false;
|
|
}
|
|
}
|
|
partsRead = 0;
|
|
state = State.Done;
|
|
done = true;
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ReadAndCheckHeaderByte( Stream s, byte expected ) {
|
|
int value;
|
|
if( !ReadHeaderByte( s, out value ) )
|
|
return false;
|
|
|
|
if( value != expected )
|
|
throw new InvalidDataException( "Unepxected constant in GZip header. (" + expected + "-" + value + ")" );
|
|
return true;
|
|
}
|
|
|
|
bool ReadHeaderByte( Stream s, out int value ) {
|
|
value = s.ReadByte();
|
|
if( value == -1 )
|
|
return false;
|
|
|
|
state++;
|
|
return true;
|
|
}
|
|
}
|
|
} |