mirror of
				https://github.com/ClassiCube/ClassiCube.git
				synced 2025-10-30 18:13:56 -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;
 | |
| 		}
 | |
| 	}
 | |
| } | 
