mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-10-08 05:27:33 -04:00
124 lines
2.9 KiB
C#
124 lines
2.9 KiB
C#
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
|
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;
|
|
}
|
|
}
|
|
} |