private bool ReadHeader()

in src/ICSharpCode.SharpZipLib/GZip/GzipInputStream.cs [168:310]


		private bool ReadHeader()
		{
			// Initialize CRC for this block
			crc = new Crc32();

			// Make sure there is data in file. We can't rely on ReadLeByte() to fill the buffer, as this could be EOF,
			// which is fine, but ReadLeByte() throws an exception if it doesn't find data, so we do this part ourselves.
			if (inputBuffer.Available <= 0)
			{
				inputBuffer.Fill();
				if (inputBuffer.Available <= 0)
				{
					// No header, EOF.
					return false;
				}
			}

			var headCRC = new Crc32();

			// 1. Check the two magic bytes

			var magic = inputBuffer.ReadLeByte();
			headCRC.Update(magic);
			if (magic != GZipConstants.ID1)
			{
				throw new GZipException("Error GZIP header, first magic byte doesn't match");
			}

			magic = inputBuffer.ReadLeByte();
			if (magic != GZipConstants.ID2)
			{
				throw new GZipException("Error GZIP header,  second magic byte doesn't match");
			}
			headCRC.Update(magic);

			// 2. Check the compression type (must be 8)
			var compressionType = inputBuffer.ReadLeByte();

			if (compressionType != GZipConstants.CompressionMethodDeflate)
			{
				throw new GZipException("Error GZIP header, data not in deflate format");
			}
			headCRC.Update(compressionType);

			// 3. Check the flags
			var flagsByte = inputBuffer.ReadLeByte();

			headCRC.Update(flagsByte);

			// 3.1 Check the reserved bits are zero

			if ((flagsByte & 0xE0) != 0)
			{
				throw new GZipException("Reserved flag bits in GZIP header != 0");
			}

			var flags = (GZipFlags)flagsByte;

			// 4.-6. Skip the modification time, extra flags, and OS type
			for (int i = 0; i < 6; i++)
			{
				headCRC.Update(inputBuffer.ReadLeByte());
			}

			// 7. Read extra field
			if (flags.HasFlag(GZipFlags.FEXTRA))
			{
				// XLEN is total length of extra subfields, we will skip them all
				var len1 = inputBuffer.ReadLeByte();
				var len2 = inputBuffer.ReadLeByte();

				headCRC.Update(len1);
				headCRC.Update(len2);

				int extraLen = (len2 << 8) | len1;      // gzip is LSB first
				for (int i = 0; i < extraLen; i++)
				{
					headCRC.Update(inputBuffer.ReadLeByte());
				}
			}

			// 8. Read file name
			if (flags.HasFlag(GZipFlags.FNAME))
			{
				var fname = new byte[1024];
				var fnamePos = 0;
				int readByte;
				while ((readByte = inputBuffer.ReadLeByte()) > 0)
				{
					if (fnamePos < 1024)
					{
						fname[fnamePos++] = (byte)readByte;
					}
					headCRC.Update(readByte);
				}

				headCRC.Update(readByte);

				fileName = GZipConstants.Encoding.GetString(fname, 0, fnamePos);
			}
			else
			{
				fileName = null;
			}

			// 9. Read comment
			if (flags.HasFlag(GZipFlags.FCOMMENT))
			{
				int readByte;
				while ((readByte = inputBuffer.ReadLeByte()) > 0)
				{
					headCRC.Update(readByte);
				}

				headCRC.Update(readByte);
			}

			// 10. Read header CRC
			if (flags.HasFlag(GZipFlags.FHCRC))
			{
				int tempByte;
				int crcval = inputBuffer.ReadLeByte();
				if (crcval < 0)
				{
					throw new EndOfStreamException("EOS reading GZIP header");
				}

				tempByte = inputBuffer.ReadLeByte();
				if (tempByte < 0)
				{
					throw new EndOfStreamException("EOS reading GZIP header");
				}

				crcval = (crcval << 8) | tempByte;
				if (crcval != ((int)headCRC.Value & 0xffff))
				{
					throw new GZipException("Header CRC value mismatch");
				}
			}

			readGZIPHeader = true;
			return true;
		}