/// <summary> /// Reads a block of bytes from the current zip entry. /// </summary> /// <returns> /// the number of bytes read (may be smaller, even before EOF), or -1 on EOF. /// </returns> /// <exception name="Exception"> /// IOException if a i/o error occured. /// ZipException if the deflated stream is corrupted. /// </exception> public override int Read(byte[] b, int off, int len) { if (crc == null) { throw new InvalidOperationException("Closed."); } if (entry == null) { return(-1); } bool finished = false; switch (method) { case ZipOutputStream.DEFLATED: len = base.Read(b, off, len); if (len < 0) { if (!inf.IsFinished) { throw new ZipException("Inflater not finished!?"); } avail = inf.RemainingInput; if (inf.TotalIn != csize || inf.TotalOut != size) { throw new ZipException("size mismatch: " + csize + ";" + size + " <-> " + inf.TotalIn + ";" + inf.TotalOut); } inf.Reset(); finished = true; } break; case ZipOutputStream.STORED: if (len > csize && csize >= 0) { len = (int)csize; } len = ReadBuf(b, off, len); if (len > 0) { csize -= len; size -= len; } if (csize == 0) { finished = true; } else { if (len < 0) { throw new ZipException("EOF in stored block"); } } // decrypting crypted data if (cryptbuffer != null) { DecryptBlock(b, off, len); } break; } if (len > 0) { crc.Update(b, off, len); } if (finished) { if ((flags & 8) != 0) { ReadDataDescr(); } //Console.WriteLine("{0:x}",crc.Value & 0xFFFFFFFFL); //Console.WriteLine(entry.Crc); if ((crc.Value & 0xFFFFFFFFL) != entry.Crc && entry.Crc != -1) { throw new ZipException("CRC mismatch"); } crc.Reset(); entry = null; } return(len); }
/// <summary> /// Closes the zip file. /// </summary> /// <exception name="Exception"> /// if a i/o error occured. /// </exception> public override void Close() { base.Close(); crc = null; entry = null; }
/// <summary> /// Open the next entry from the zip archive, and return its description. /// If the previous entry wasn't closed, this method will close it. /// </summary> public ZipEntry GetNextEntry() { if (crc == null) { throw new InvalidOperationException("Closed."); } if (entry != null) { CloseEntry(); } int header = ReadLeInt(); if (header == ZipConstants.CENSIG) { /* Central Header reached. */ Close(); return(null); } if (header != ZipConstants.LOCSIG) { throw new ZipException("Wrong Local header signature: 0x" + String.Format("{0:X}", header)); } short version = (short)ReadLeShort(); flags = ReadLeShort(); method = ReadLeShort(); uint dostime = (uint)ReadLeInt(); int crc2 = ReadLeInt(); csize = ReadLeInt(); size = ReadLeInt(); int nameLen = ReadLeShort(); int extraLen = ReadLeShort(); bool isCrypted = (flags & 1) == 1; if (method == ZipOutputStream.STORED && (!isCrypted && csize != size || (isCrypted && csize - 12 != size))) { throw new ZipException("Stored, but compressed != uncompressed"); } byte[] buffer = new byte[nameLen]; ReadFully(buffer); string name = ZipConstants.ConvertToString(buffer); entry = new ZipEntry(name); entry.IsCrypted = isCrypted; entry.Version = (ushort)version; if (method != 0 && method != 8) { throw new ZipException("unknown compression method " + method); } entry.CompressionMethod = (CompressionMethod)method; if ((flags & 8) == 0) { entry.Crc = crc2 & 0xFFFFFFFFL; entry.Size = size & 0xFFFFFFFFL; entry.CompressedSize = csize & 0xFFFFFFFFL; } entry.DosTime = dostime; if (extraLen > 0) { byte[] extra = new byte[extraLen]; ReadFully(extra); entry.ExtraData = extra; } // test for encryption if (isCrypted) { if (password == null) { throw new ZipException("No password set."); } InitializePassword(password); cryptbuffer = new byte[12]; ReadFully(cryptbuffer); //crc.Update(cryptbuffer); for (int i = 0; i < 12; ++i) { cryptbuffer[i] ^= DecryptByte(); UpdateKeys(cryptbuffer[i]); } //cryptbuffer = cryptbuffer2; csize -= 12; } else { cryptbuffer = null; } if (method == ZipOutputStream.DEFLATED && avail > 0) { System.Array.Copy(buf, len - (int)avail, buf, 0, (int)avail); len = (int)avail; avail = 0; if (isCrypted) { DecryptBlock(buf, 0, len); } inf.SetInput(buf, 0, len); } return(entry); }