Esempio n. 1
0
 public ZipEntry PutNextEntry(string entryName)
 {
     if (string.IsNullOrEmpty(entryName))
     {
         throw new ArgumentNullException("entryName");
     }
     if (_disposed)
     {
         _exceptionPending = true;
         throw new InvalidOperationException("The stream has been closed.");
     }
     _FinishCurrentEntry();
     _currentEntry            = ZipEntry.CreateForZipOutputStream(entryName);
     _currentEntry._container = new ZipContainer(this);
     _currentEntry._BitField |= 8;
     _currentEntry.SetEntryTimes(DateTime.Now, DateTime.Now, DateTime.Now);
     _currentEntry.CompressionLevel       = CompressionLevel;
     _currentEntry.CompressionMethod      = CompressionMethod;
     _currentEntry.Password               = _password;
     _currentEntry.Encryption             = Encryption;
     _currentEntry.AlternateEncoding      = AlternateEncoding;
     _currentEntry.AlternateEncodingUsage = AlternateEncodingUsage;
     if (entryName.EndsWith("/"))
     {
         _currentEntry.MarkAsDirectory();
     }
     _currentEntry.EmitTimesInWindowsFormatWhenSaving = ((_timestamp & ZipEntryTimestamp.Windows) != 0);
     _currentEntry.EmitTimesInUnixFormatWhenSaving    = ((_timestamp & ZipEntryTimestamp.Unix) != 0);
     InsureUniqueEntry(_currentEntry);
     _needToWriteEntryHeader = true;
     return(_currentEntry);
 }
//         private string DictionaryKeyForEntry(ZipEntry ze1)
//         {
//             var filename = SharedUtilities.NormalizePathForUseInZipFile(ze1.FileName);
//             return filename;
//         }



        /// <summary>
        ///   Creates a directory in the zip archive.
        /// </summary>
        ///
        /// <remarks>
        ///
        /// <para>
        ///   Use this when you want to create a directory in the archive but there is
        ///   no corresponding filesystem representation for that directory.
        /// </para>
        ///
        /// <para>
        ///   You will probably not need to do this in your code. One of the only times
        ///   you will want to do this is if you want an empty directory in the zip
        ///   archive.  The reason: if you add a file to a zip archive that is stored
        ///   within a multi-level directory, all of the directory tree is implicitly
        ///   created in the zip archive.
        /// </para>
        ///
        /// </remarks>
        ///
        /// <param name="directoryNameInArchive">
        ///   The name of the directory to create in the archive.
        /// </param>
        /// <returns>The <c>ZipEntry</c> added.</returns>
        public ZipEntry AddDirectoryByName(string directoryNameInArchive)
        {
            // workitem 9073
            ZipEntry dir = ZipEntry.CreateFromNothing(directoryNameInArchive);

            dir._container = new ZipContainer(this);
            dir.MarkAsDirectory();
            dir.AlternateEncoding      = this.AlternateEncoding; // workitem 8984
            dir.AlternateEncodingUsage = this.AlternateEncodingUsage;
            dir.SetEntryTimes(DateTime.Now, DateTime.Now, DateTime.Now);
            dir.EmitTimesInWindowsFormatWhenSaving = _emitNtfsTimes;
            dir.EmitTimesInUnixFormatWhenSaving    = _emitUnixTimes;
            dir._Source = ZipEntrySource.Stream;
            //string key = DictionaryKeyForEntry(dir);
            InternalAddEntry(dir.FileName, dir);
            AfterAddEntry(dir);
            return(dir);
        }
Esempio n. 3
0
        // build the TOC by reading each entry in the file.
        private static void ReadIntoInstance_Orig(ZipFile zf)
        {
            zf.OnReadStarted();
            //zf._entries = new System.Collections.Generic.List<ZipEntry>();
            zf._entries = new System.Collections.Generic.Dictionary <String, ZipEntry>();

            ZipEntry e;

            if (zf.Verbose)
            {
                if (zf.Name == null)
                {
                    zf.StatusMessageTextWriter.WriteLine("Reading zip from stream...");
                }
                else
                {
                    zf.StatusMessageTextWriter.WriteLine("Reading zip {0}...", zf.Name);
                }
            }

            // work item 6647:  PK00 (packed to removable disk)
            bool         firstEntry = true;
            ZipContainer zc         = new ZipContainer(zf);

            while ((e = ZipEntry.ReadEntry(zc, firstEntry)) != null)
            {
                if (zf.Verbose)
                {
                    zf.StatusMessageTextWriter.WriteLine("  {0}", e.FileName);
                }

                zf._entries.Add(e.FileName, e);
                firstEntry = false;
            }

            // read the zipfile's central directory structure here.
            // workitem 9912
            // But, because it may be corrupted, ignore errors.
            try
            {
                ZipEntry de;
                while ((de = ZipEntry.ReadDirEntry(zf)) != null)
                {
                    // Housekeeping: Since ZipFile exposes ZipEntry elements in the enumerator,
                    // we need to copy the comment that we grab from the ZipDirEntry
                    // into the ZipEntry, so the application can access the comment.
                    // Also since ZipEntry is used to Write zip files, we need to copy the
                    // file attributes to the ZipEntry as appropriate.
                    ZipEntry e1 = zf._entries[de.FileName];
                    if (e1 != null)
                    {
                        e1._Comment = de.Comment;
                        if (de.IsDirectory)
                        {
                            e1.MarkAsDirectory();
                        }
                    }
                }

                // workitem 8299
                if (zf._locEndOfCDS > 0)
                {
                    zf.ReadStream.Seek(zf._locEndOfCDS, SeekOrigin.Begin);
                }

                ReadCentralDirectoryFooter(zf);

                if (zf.Verbose && !String.IsNullOrEmpty(zf.Comment))
                {
                    zf.StatusMessageTextWriter.WriteLine("Zip file Comment: {0}", zf.Comment);
                }
            }
            catch
            {
            }

            zf.OnReadCompleted();
        }
Esempio n. 4
0
        internal static ZipEntry ReadDirEntry(ZipFile zf,
                                              Dictionary <String, Object> previouslySeen)
        {
            System.IO.Stream     s = zf.ReadStream;
            System.Text.Encoding expectedEncoding = (zf.AlternateEncodingUsage == ZipOption.Always)
                ? zf.AlternateEncoding
                : ZipFile.DefaultEncoding;

            while (true)
            {
                int signature = Ionic.Zip.SharedUtilities.ReadSignature(s);
                // return null if this is not a local file header signature
                if (IsNotValidZipDirEntrySig(signature))
                {
                    s.Seek(-4, System.IO.SeekOrigin.Current);

                    // Getting "not a ZipDirEntry signature" here is not always wrong or an
                    // error.  This can happen when walking through a zipfile.  After the
                    // last ZipDirEntry, we expect to read an
                    // EndOfCentralDirectorySignature.  When we get this is how we know
                    // we've reached the end of the central directory.
                    if (signature != ZipConstants.EndOfCentralDirectorySignature &&
                        signature != ZipConstants.Zip64EndOfCentralDirectoryRecordSignature &&
                        signature != ZipConstants.ZipEntrySignature  // workitem 8299
                        )
                    {
                        throw new BadReadException(String.Format("  Bad signature (0x{0:X8}) at position 0x{1:X8}", signature, s.Position));
                    }
                    return(null);
                }

                int    bytesRead = 42 + 4;
                byte[] block     = new byte[42];
                int    n         = s.Read(block, 0, block.Length);
                if (n != block.Length)
                {
                    return(null);
                }

                int      i   = 0;
                ZipEntry zde = new ZipEntry();
                zde.AlternateEncoding = expectedEncoding;
                zde._Source           = ZipEntrySource.ZipFile;
                zde._container        = new ZipContainer(zf);

                unchecked
                {
                    zde._VersionMadeBy     = (short)(block[i++] + block[i++] * 256);
                    zde._VersionNeeded     = (short)(block[i++] + block[i++] * 256);
                    zde._BitField          = (short)(block[i++] + block[i++] * 256);
                    zde._CompressionMethod = (Int16)(block[i++] + block[i++] * 256);
                    zde._TimeBlob          = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
                    zde._LastModified      = Ionic.Zip.SharedUtilities.PackedToDateTime(zde._TimeBlob);
                    zde._timestamp        |= ZipEntryTimestamp.DOS;

                    zde._Crc32            = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
                    zde._CompressedSize   = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                    zde._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                }

                // preserve
                zde._CompressionMethod_FromZipFile = zde._CompressionMethod;

                zde._filenameLength   = (short)(block[i++] + block[i++] * 256);
                zde._extraFieldLength = (short)(block[i++] + block[i++] * 256);
                zde._commentLength    = (short)(block[i++] + block[i++] * 256);
                zde._diskNumber       = (UInt32)(block[i++] + block[i++] * 256);

                zde._InternalFileAttrs = (short)(block[i++] + block[i++] * 256);
                zde._ExternalFileAttrs = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;

                zde._RelativeOffsetOfLocalHeader = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);

                // workitem 7801
                zde.IsText = ((zde._InternalFileAttrs & 0x01) == 0x01);

                block      = new byte[zde._filenameLength];
                n          = s.Read(block, 0, block.Length);
                bytesRead += n;
                if ((zde._BitField & 0x0800) == 0x0800)
                {
                    // UTF-8 is in use
                    zde._FileNameInArchive = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block);
                }
                else
                {
                    zde._FileNameInArchive = Ionic.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding);
                }

                // workitem 10330
                // insure unique entry names
                while (!zf.IgnoreDuplicateFiles && previouslySeen.ContainsKey(zde._FileNameInArchive))
                {
                    zde._FileNameInArchive = CopyHelper.AppendCopyToFileName(zde._FileNameInArchive);
                    zde._metadataChanged   = true;
                }

                if (zde.AttributesIndicateDirectory)
                {
                    zde.MarkAsDirectory();  // may append a slash to filename if nec.
                }
                // workitem 6898
                else if (zde._FileNameInArchive.EndsWith("/"))
                {
                    zde.MarkAsDirectory();
                }

                zde._CompressedFileDataSize = zde._CompressedSize;
                if ((zde._BitField & 0x01) == 0x01)
                {
                    // this may change after processing the Extra field
                    zde._Encryption_FromZipFile = zde._Encryption =
                        EncryptionAlgorithm.PkzipWeak;
                    zde._sourceIsEncrypted = true;
                }

                if (zde._extraFieldLength > 0)
                {
                    zde._InputUsesZip64 = (zde._CompressedSize == 0xFFFFFFFF ||
                                           zde._UncompressedSize == 0xFFFFFFFF ||
                                           zde._RelativeOffsetOfLocalHeader == 0xFFFFFFFF);

                    // Console.WriteLine("  Input uses Z64?:      {0}", zde._InputUsesZip64);

                    bytesRead += zde.ProcessExtraField(s, zde._extraFieldLength);
                    zde._CompressedFileDataSize = zde._CompressedSize;
                }

                // we've processed the extra field, so we know the encryption method is set now.
                if (zde._Encryption == EncryptionAlgorithm.PkzipWeak)
                {
                    // the "encryption header" of 12 bytes precedes the file data
                    zde._CompressedFileDataSize -= 12;
                }


                // tally the trailing descriptor
                if ((zde._BitField & 0x0008) == 0x0008)
                {
                    // sig, CRC, Comp and Uncomp sizes
                    if (zde._InputUsesZip64)
                    {
                        zde._LengthOfTrailer += 24;
                    }
                    else
                    {
                        zde._LengthOfTrailer += 16;
                    }
                }

                // workitem 12744
                zde.AlternateEncoding = ((zde._BitField & 0x0800) == 0x0800)
                    ? System.Text.Encoding.UTF8
                    :expectedEncoding;

                zde.AlternateEncodingUsage = ZipOption.Always;

                if (zde._commentLength > 0)
                {
                    block      = new byte[zde._commentLength];
                    n          = s.Read(block, 0, block.Length);
                    bytesRead += n;
                    if ((zde._BitField & 0x0800) == 0x0800)
                    {
                        // UTF-8 is in use
                        zde._Comment = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block);
                    }
                    else
                    {
                        zde._Comment = Ionic.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding);
                    }
                }
                //zde._LengthOfDirEntry = bytesRead;
                if (zf.IgnoreDuplicateFiles && previouslySeen.ContainsKey(zde._FileNameInArchive))
                {
                    continue;
                }
                return(zde);
            }
        }
        /// <summary>
        /// Reads one entry from the zip directory structure in the zip file.
        /// </summary>
        /// <param name="zf">
        /// The zipfile for which a directory entry will be read.  From this param, the
        /// method gets the ReadStream and the expected text encoding
        /// (ProvisionalAlternateEncoding) which is used if the entry is not marked
        /// UTF-8.
        /// </param>
        /// <returns>the entry read from the archive.</returns>
        internal static ZipEntry ReadDirEntry(ZipFile zf)
        {
            System.IO.Stream s = zf.ReadStream;
            System.Text.Encoding expectedEncoding = zf.ProvisionalAlternateEncoding;

            int signature = Ionic.Zip.SharedUtilities.ReadSignature(s);
            // return null if this is not a local file header signature
            if (IsNotValidZipDirEntrySig(signature))
            {
                s.Seek(-4, System.IO.SeekOrigin.Current);
                // workitem 10178
                Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s);

                // Getting "not a ZipDirEntry signature" here is not always wrong or an
                // error.  This can happen when walking through a zipfile.  After the
                // last ZipDirEntry, we expect to read an
                // EndOfCentralDirectorySignature.  When we get this is how we know
                // we've reached the end of the central directory.
                if (signature != ZipConstants.EndOfCentralDirectorySignature &&
                    signature != ZipConstants.Zip64EndOfCentralDirectoryRecordSignature &&
                    signature != ZipConstants.ZipEntrySignature  // workitem 8299
                    )
                {
                    throw new BadReadException(String.Format("  ZipEntry::ReadDirEntry(): Bad signature (0x{0:X8}) at position 0x{1:X8}", signature, s.Position));
                }
                return null;
            }

            int bytesRead = 42 + 4;
            byte[] block = new byte[42];
            int n = s.Read(block, 0, block.Length);
            if (n != block.Length) return null;

            int i = 0;
            ZipEntry zde = new ZipEntry();
            zde.ProvisionalAlternateEncoding = expectedEncoding;
            zde._Source = ZipEntrySource.ZipFile;
            zde._container = new ZipContainer(zf);

            unchecked
            {
                zde._VersionMadeBy = (short)(block[i++] + block[i++] * 256);
                zde._VersionNeeded = (short)(block[i++] + block[i++] * 256);
                zde._BitField = (short)(block[i++] + block[i++] * 256);
                zde._CompressionMethod = (Int16)(block[i++] + block[i++] * 256);
                zde._TimeBlob = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
                zde._LastModified = Ionic.Zip.SharedUtilities.PackedToDateTime(zde._TimeBlob);
                zde._timestamp |= ZipEntryTimestamp.DOS;

                zde._Crc32 = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
                zde._CompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                zde._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
            }

            // preserve
            zde._CompressionMethod_FromZipFile = zde._CompressionMethod;

            zde._filenameLength = (short)(block[i++] + block[i++] * 256);
            zde._extraFieldLength = (short)(block[i++] + block[i++] * 256);
            zde._commentLength = (short)(block[i++] + block[i++] * 256);
            zde._diskNumber = (UInt32)(block[i++] + block[i++] * 256);

            zde._InternalFileAttrs = (short)(block[i++] + block[i++] * 256);
            zde._ExternalFileAttrs = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;

            zde._RelativeOffsetOfLocalHeader = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);

            // workitem 7801
            zde.IsText = ((zde._InternalFileAttrs & 0x01) == 0x01);

            block = new byte[zde._filenameLength];
            n = s.Read(block, 0, block.Length);
            bytesRead += n;
            if ((zde._BitField & 0x0800) == 0x0800)
            {
                // UTF-8 is in use
                zde._FileNameInArchive = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block);
            }
            else
            {
                zde._FileNameInArchive = Ionic.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding);
            }

            // Console.WriteLine("\nEntry : {0}", zde._LocalFileName);
            // Console.WriteLine("  V Madeby/Needed:      0x{0:X4} / 0x{1:X4}", zde._VersionMadeBy, zde._VersionNeeded);
            // Console.WriteLine("  BitField/Compression: 0x{0:X4} / 0x{1:X4}", zde._BitField, zde._CompressionMethod);
            // Console.WriteLine("  Lastmod:              {0}", zde._LastModified.ToString("u"));
            // Console.WriteLine("  CRC:                  0x{0:X8}", zde._Crc32);
            // Console.WriteLine("  Comp / Uncomp:        0x{0:X8} ({0})   0x{1:X8} ({1})", zde._CompressedSize, zde._UncompressedSize);

            //zde._FileNameInArchive = zde._LocalFileName;

            if (zde.AttributesIndicateDirectory) zde.MarkAsDirectory();  // may append a slash to filename if nec.
            // workitem 6898
            else if (zde._FileNameInArchive.EndsWith("/")) zde.MarkAsDirectory();

            zde._CompressedFileDataSize = zde._CompressedSize;
            if ((zde._BitField & 0x01) == 0x01)
            {
                zde._Encryption_FromZipFile = zde._Encryption = EncryptionAlgorithm.PkzipWeak; // this may change after processing the Extra field
                zde._sourceIsEncrypted = true;
            }

            if (zde._extraFieldLength > 0)
            {
                zde._InputUsesZip64 = (zde._CompressedSize == 0xFFFFFFFF ||
                      zde._UncompressedSize == 0xFFFFFFFF ||
                      zde._RelativeOffsetOfLocalHeader == 0xFFFFFFFF);

                // Console.WriteLine("  Input uses Z64?:      {0}", zde._InputUsesZip64);

                bytesRead += zde.ProcessExtraField(s, zde._extraFieldLength);
                zde._CompressedFileDataSize = zde._CompressedSize;
            }

            // we've processed the extra field, so we know the encryption method is set now.
            if (zde._Encryption == EncryptionAlgorithm.PkzipWeak)
            {
                // the "encryption header" of 12 bytes precedes the file data
                zde._CompressedFileDataSize -= 12;
            }
#if AESCRYPTO
            else if (zde.Encryption == EncryptionAlgorithm.WinZipAes128 ||
                        zde.Encryption == EncryptionAlgorithm.WinZipAes256)
            {
                zde._CompressedFileDataSize = zde.CompressedSize -
                    (ZipEntry.GetLengthOfCryptoHeaderBytes(zde.Encryption) + 10);
                zde._LengthOfTrailer = 10;
            }
#endif

            // tally the trailing descriptor
            if ((zde._BitField & 0x0008) == 0x0008)
            {
                // sig, CRC, Comp and Uncomp sizes
                if (zde._InputUsesZip64)
                    zde._LengthOfTrailer += 24;
                else
                    zde._LengthOfTrailer += 16;
            }

            if (zde._commentLength > 0)
            {
                block = new byte[zde._commentLength];
                n = s.Read(block, 0, block.Length);
                bytesRead += n;
                if ((zde._BitField & 0x0800) == 0x0800)
                {
                    // UTF-8 is in use
                    zde._Comment = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block);
                }
                else
                {
                    zde._Comment = Ionic.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding);
                }
            }
            //zde._LengthOfDirEntry = bytesRead;
            return zde;
        }
Esempio n. 6
0
        private static bool ReadHeader(ZipEntry ze, System.Text.Encoding defaultEncoding)
        {
            int bytesRead = 0;

            // change for workitem 8098
            ze._RelativeOffsetOfLocalHeader = ze.ArchiveStream.Position;

            int signature = Ionic.Zip.SharedUtilities.ReadEntrySignature(ze.ArchiveStream);
            bytesRead += 4;

            // Return false if this is not a local file header signature.
            if (ZipEntry.IsNotValidSig(signature))
            {
                // Getting "not a ZipEntry signature" is not always wrong or an error.
                // This will happen after the last entry in a zipfile.  In that case, we
                // expect to read :
                //    a ZipDirEntry signature (if a non-empty zip file) or
                //    a ZipConstants.EndOfCentralDirectorySignature.
                //
                // Anything else is a surprise.

                ze.ArchiveStream.Seek(-4, SeekOrigin.Current); // unread the signature
                // workitem 10178
                Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(ze.ArchiveStream);
                if (ZipEntry.IsNotValidZipDirEntrySig(signature) && (signature != ZipConstants.EndOfCentralDirectorySignature))
                {
                    throw new BadReadException(String.Format("  ZipEntry::ReadHeader(): Bad signature (0x{0:X8}) at position  0x{1:X8}", signature, ze.ArchiveStream.Position));
                }
                return false;
            }

            byte[] block = new byte[26];
            int n = ze.ArchiveStream.Read(block, 0, block.Length);
            if (n != block.Length) return false;
            bytesRead += n;

            int i = 0;
            ze._VersionNeeded = (Int16)(block[i++] + block[i++] * 256);
            ze._BitField = (Int16)(block[i++] + block[i++] * 256);
            ze._CompressionMethod_FromZipFile = ze._CompressionMethod = (Int16)(block[i++] + block[i++] * 256);
            ze._TimeBlob = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
            // transform the time data into something usable (a DateTime)
            ze._LastModified = Ionic.Zip.SharedUtilities.PackedToDateTime(ze._TimeBlob);
            ze._timestamp |= ZipEntryTimestamp.DOS;

            if ((ze._BitField & 0x01) == 0x01)
            {
                ze._Encryption_FromZipFile = ze._Encryption = EncryptionAlgorithm.PkzipWeak; // this *may* change after processing the Extra field
                ze._sourceIsEncrypted = true;
            }

            // NB: if ((ze._BitField & 0x0008) != 0x0008), then the Compressed, uncompressed and
            // CRC values are not true values; the true values will follow the entry data.
            // But, regardless of the status of bit 3 in the bitfield, the slots for
            // the three amigos may contain marker values for ZIP64.  So we must read them.
            {
                ze._Crc32 = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                ze._CompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                ze._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);

                if ((uint)ze._CompressedSize == 0xFFFFFFFF ||
                    (uint)ze._UncompressedSize == 0xFFFFFFFF)

                    ze._InputUsesZip64 = true;
            }

            Int16 filenameLength = (short)(block[i++] + block[i++] * 256);
            Int16 extraFieldLength = (short)(block[i++] + block[i++] * 256);

            block = new byte[filenameLength];
            n = ze.ArchiveStream.Read(block, 0, block.Length);
            bytesRead += n;

            // if the UTF8 bit is set for this entry, override the encoding the application requested.
            ze._actualEncoding = ((ze._BitField & 0x0800) == 0x0800)
                ? System.Text.Encoding.UTF8
                : defaultEncoding;

            // need to use this form of GetString() for .NET CF
            ze._FileNameInArchive = ze._actualEncoding.GetString(block, 0, block.Length);

            // when creating an entry by reading, the LocalFileName is the same as the FileNameInArchive
            // No, on second thought, I think it should be empty (null).
            //ze._LocalFileName = ze._FileNameInArchive;

            // workitem 6898
            if (ze._FileNameInArchive.EndsWith("/")) ze.MarkAsDirectory();

            bytesRead += ze.ProcessExtraField(ze.ArchiveStream, extraFieldLength);

            ze._LengthOfTrailer = 0;

            // workitem 6607 - don't read for directories
            // actually get the compressed size and CRC if necessary
            if (!ze._FileNameInArchive.EndsWith("/") && (ze._BitField & 0x0008) == 0x0008)
            {
                // This descriptor exists only if bit 3 of the general
                // purpose bit flag is set (see below).  It is byte aligned
                // and immediately follows the last byte of compressed data,
                // as well as any encryption trailer, as with AES.
                // This descriptor is used only when it was not possible to
                // seek in the output .ZIP file, e.g., when the output .ZIP file
                // was standard output or a non-seekable device.  For ZIP64(tm) format
                // archives, the compressed and uncompressed sizes are 8 bytes each.

                // workitem 8098: ok (restore)
                long posn = ze.ArchiveStream.Position;

                // Here, we're going to loop until we find a ZipEntryDataDescriptorSignature and
                // a consistent data record after that.   To be consistent, the data record must
                // indicate the length of the entry data.
                bool wantMore = true;
                long SizeOfDataRead = 0;
                int tries = 0;
                while (wantMore)
                {
                    tries++;
                    // We call the FindSignature shared routine to find the specified signature
                    // in the already-opened zip archive, starting from the current cursor
                    // position in that filestream.  If we cannot find the signature, then the
                    // routine returns -1, and the ReadHeader() method returns false,
                    // indicating we cannot read a legal entry header.  If we have found it,
                    // then the FindSignature() method returns the number of bytes in the
                    // stream we had to seek forward, to find the sig.  We need this to
                    // determine if the zip entry is valid, later.

                    if (ze._container.ZipFile != null)
                        ze._container.ZipFile.OnReadBytes(ze);

                    long d = Ionic.Zip.SharedUtilities.FindSignature(ze.ArchiveStream, ZipConstants.ZipEntryDataDescriptorSignature);
                    if (d == -1) return false;

                    // total size of data read (through all loops of this).
                    SizeOfDataRead += d;

                    if (ze._InputUsesZip64)
                    {
                        // read 1x 4-byte (CRC) and 2x 8-bytes (Compressed Size, Uncompressed Size)
                        block = new byte[20];
                        n = ze.ArchiveStream.Read(block, 0, block.Length);
                        if (n != 20) return false;

                        // do not increment bytesRead - it is for entry header only.
                        // the data we have just read is a footer (falls after the file data)
                        //bytesRead += n;

                        i = 0;
                        ze._Crc32 = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                        ze._CompressedSize = BitConverter.ToInt64(block, i);
                        i += 8;
                        ze._UncompressedSize = BitConverter.ToInt64(block, i);
                        i += 8;

                        ze._LengthOfTrailer += 24;  // bytes including sig, CRC, Comp and Uncomp sizes
                    }
                    else
                    {
                        // read 3x 4-byte fields (CRC, Compressed Size, Uncompressed Size)
                        block = new byte[12];
                        n = ze.ArchiveStream.Read(block, 0, block.Length);
                        if (n != 12) return false;

                        // do not increment bytesRead - it is for entry header only.
                        // the data we have just read is a footer (falls after the file data)
                        //bytesRead += n;

                        i = 0;
                        ze._Crc32 = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                        ze._CompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                        ze._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);

                        ze._LengthOfTrailer += 16;  // bytes including sig, CRC, Comp and Uncomp sizes

                    }

                    wantMore = (SizeOfDataRead != ze._CompressedSize);

                    if (wantMore)
                    {
                        // Seek back to un-read the last 12 bytes  - maybe THEY contain
                        // the ZipEntryDataDescriptorSignature.
                        // (12 bytes for the CRC, Comp and Uncomp size.)
                        ze.ArchiveStream.Seek(-12, SeekOrigin.Current);
                        // workitem 10178
                        Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(ze.ArchiveStream);

                        // Adjust the size to account for the false signature read in
                        // FindSignature().
                        SizeOfDataRead += 4;
                    }
                }

                // seek back to previous position, to prepare to read file data
                // workitem 8098: ok (restore)
                ze.ArchiveStream.Seek(posn, SeekOrigin.Begin);
                // workitem 10178
                Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(ze.ArchiveStream);
            }

            ze._CompressedFileDataSize = ze._CompressedSize;


            // bit 0 set indicates that some kind of encryption is in use
            if ((ze._BitField & 0x01) == 0x01)
            {
#if AESCRYPTO
                if (ze.Encryption == EncryptionAlgorithm.WinZipAes128 ||
                    ze.Encryption == EncryptionAlgorithm.WinZipAes256)
                {
                    int bits = ZipEntry.GetKeyStrengthInBits(ze._Encryption_FromZipFile);
                    // read in the WinZip AES metadata: salt + PV. 18 bytes for AES256. 10 bytes for AES128.
                    ze._aesCrypto_forExtract = WinZipAesCrypto.ReadFromStream(null, bits, ze.ArchiveStream);
                    bytesRead += ze._aesCrypto_forExtract.SizeOfEncryptionMetadata - 10; // MAC (follows crypto bytes)
                    // according to WinZip, the CompressedSize includes the AES Crypto framing data.
                    ze._CompressedFileDataSize -= ze._aesCrypto_forExtract.SizeOfEncryptionMetadata;
                    ze._LengthOfTrailer += 10;  // MAC
                }
                else
#endif
                {
                    // read in the header data for "weak" encryption
                    ze._WeakEncryptionHeader = new byte[12];
                    bytesRead += ZipEntry.ReadWeakEncryptionHeader(ze._archiveStream, ze._WeakEncryptionHeader);
                    // decrease the filedata size by 12 bytes
                    ze._CompressedFileDataSize -= 12;
                }
            }

            // Remember the size of the blob for this entry.
            // We also have the starting position in the stream for this entry.
            ze._LengthOfHeader = bytesRead;
            ze._TotalEntrySize = ze._LengthOfHeader + ze._CompressedFileDataSize + ze._LengthOfTrailer;


            // We've read in the regular entry header, the extra field, and any encryption
            // header.  The pointer in the file is now at the start of the filedata, which is
            // potentially compressed and encrypted.  Just ahead in the file, there are
            // _CompressedFileDataSize bytes of data, followed by potentially a non-zero length
            // trailer, consisting of optionally, some encryption stuff (10 byte MAC for AES),
            // and the bit-3 trailer (16 or 24 bytes).

            return true;
        }
Esempio n. 7
0
        /// <summary>
        ///   Specify the name of the next entry that will be written to the zip file.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   Call this method just before calling <see cref="Write(byte[], int, int)"/>, to
        ///   specify the name of the entry that the next set of bytes written to
        ///   the <c>ZipOutputStream</c> belongs to. All subsequent calls to <c>Write</c>,
        ///   until the next call to <c>PutNextEntry</c>,
        ///   will be inserted into the named entry in the zip file.
        /// </para>
        ///
        /// <para>
        ///   If the <paramref name="entryName"/> used in <c>PutNextEntry()</c> ends in
        ///   a slash, then the entry added is marked as a directory. Because directory
        ///   entries do not contain data, a call to <c>Write()</c>, before an
        ///   intervening additional call to <c>PutNextEntry()</c>, will throw an
        ///   exception.
        /// </para>
        ///
        /// <para>
        ///   If you don't call <c>Write()</c> between two calls to
        ///   <c>PutNextEntry()</c>, the first entry is inserted into the zip file as a
        ///   file of zero size.  This may be what you want.
        /// </para>
        ///
        /// <para>
        ///   Because <c>PutNextEntry()</c> closes out the prior entry, if any, this
        ///   method may throw if there is a problem with the prior entry.
        /// </para>
        ///
        /// <para>
        ///   This method returns the <c>ZipEntry</c>.  You can modify public properties
        ///   on the <c>ZipEntry</c>, such as <see cref="ZipEntry.Encryption"/>, <see
        ///   cref="ZipEntry.Password"/>, and so on, until the first call to
        ///   <c>ZipOutputStream.Write()</c>, or until the next call to
        ///   <c>PutNextEntry()</c>.  If you modify the <c>ZipEntry</c> <em>after</em>
        ///   having called <c>Write()</c>, you may get a runtime exception, or you may
        ///   silently get an invalid zip archive.
        /// </para>
        ///
        /// </remarks>
        ///
        /// <example>
        ///
        ///   This example shows how to create a zip file, using the
        ///   <c>ZipOutputStream</c> class.
        ///
        /// <code>
        /// private void Zipup()
        /// {
        ///     using (FileStream fs raw = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite ))
        ///     {
        ///         using (var output= new ZipOutputStream(fs))
        ///         {
        ///             output.Password = "******";
        ///             output.Encryption = EncryptionAlgorithm.WinZipAes256;
        ///             output.PutNextEntry("entry1.txt");
        ///             byte[] buffer= System.Text.Encoding.ASCII.GetBytes("This is the content for entry #1.");
        ///             output.Write(buffer,0,buffer.Length);
        ///             output.PutNextEntry("entry2.txt");  // this will be zero length
        ///             output.PutNextEntry("entry3.txt");
        ///             buffer= System.Text.Encoding.ASCII.GetBytes("This is the content for entry #3.");
        ///             output.Write(buffer,0,buffer.Length);
        ///         }
        ///     }
        /// }
        /// </code>
        /// </example>
        ///
        /// <param name="entryName">
        ///   The name of the entry to be added, including any path to be used
        ///   within the zip file.
        /// </param>
        ///
        /// <returns>
        ///   The ZipEntry created.
        /// </returns>
        ///
        public ZipEntry PutNextEntry(String entryName)
        {
            if (_disposed)
            {
                _exceptionPending = true;
                throw new System.InvalidOperationException("The stream has been closed.");
            }

            _FinishCurrentEntry();
            _currentEntry = ZipEntry.CreateForZipOutputStream(entryName);
            _currentEntry._container = new ZipContainer(this);
            _currentEntry._BitField |= 0x0008;  // workitem 8932
            _currentEntry.SetEntryTimes(DateTime.Now, DateTime.Now, DateTime.Now);
            _currentEntry.CompressionLevel = CompressionLevel;
            _currentEntry.Encryption = Encryption;
            _currentEntry.Password = _password;

            if (entryName.EndsWith("/"))  _currentEntry.MarkAsDirectory();

            _currentEntry.EmitTimesInWindowsFormatWhenSaving = ((_timestamp & ZipEntryTimestamp.Windows) != 0);
            _currentEntry.EmitTimesInUnixFormatWhenSaving = ((_timestamp & ZipEntryTimestamp.Unix) != 0);
            InsureUniqueEntry(_currentEntry);
            _needToWriteEntryHeader = true;

            return _currentEntry;
        }
        private static bool ReadHeader(ZipEntry ze, System.Text.Encoding defaultEncoding)
        {
            int bytesRead = 0;

            // change for workitem 8098
            ze._RelativeOffsetOfLocalHeader = ze.ArchiveStream.Position;

            int signature = Ionic.Zip.SharedUtilities.ReadEntrySignature(ze.ArchiveStream);

            bytesRead += 4;

            // Return false if this is not a local file header signature.
            if (ZipEntry.IsNotValidSig(signature))
            {
                // Getting "not a ZipEntry signature" is not always wrong or an error.
                // This will happen after the last entry in a zipfile.  In that case, we
                // expect to read :
                //    a ZipDirEntry signature (if a non-empty zip file) or
                //    a ZipConstants.EndOfCentralDirectorySignature.
                //
                // Anything else is a surprise.

                ze.ArchiveStream.Seek(-4, SeekOrigin.Current); // unread the signature
                if (ZipEntry.IsNotValidZipDirEntrySig(signature) && (signature != ZipConstants.EndOfCentralDirectorySignature))
                {
                    throw new BadReadException(String.Format("  Bad signature (0x{0:X8}) at position  0x{1:X8}", signature, ze.ArchiveStream.Position));
                }
                return(false);
            }

            byte[] block = new byte[26];
            int    n     = ze.ArchiveStream.Read(block, 0, block.Length);

            if (n != block.Length)
            {
                return(false);
            }
            bytesRead += n;

            int i = 0;

            ze._VersionNeeded = (Int16)(block[i++] + block[i++] * 256);
            ze._BitField      = (Int16)(block[i++] + block[i++] * 256);
            ze._CompressionMethod_FromZipFile = ze._CompressionMethod = (Int16)(block[i++] + block[i++] * 256);
            ze._TimeBlob = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
            // transform the time data into something usable (a DateTime)
            ze._LastModified = Ionic.Zip.SharedUtilities.PackedToDateTime(ze._TimeBlob);
            ze._timestamp   |= ZipEntryTimestamp.DOS;

            if ((ze._BitField & 0x01) == 0x01)
            {
                ze._Encryption_FromZipFile = ze._Encryption = EncryptionAlgorithm.PkzipWeak; // this *may* change after processing the Extra field
                ze._sourceIsEncrypted      = true;
            }

            // NB: if ((ze._BitField & 0x0008) != 0x0008), then the Compressed, uncompressed and
            // CRC values are not true values; the true values will follow the entry data.
            // But, regardless of the status of bit 3 in the bitfield, the slots for
            // the three amigos may contain marker values for ZIP64.  So we must read them.
            {
                ze._Crc32            = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                ze._CompressedSize   = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                ze._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);

                if ((uint)ze._CompressedSize == 0xFFFFFFFF ||
                    (uint)ze._UncompressedSize == 0xFFFFFFFF)
                {
                    ze._InputUsesZip64 = true;
                }
            }

            Int16 filenameLength   = (short)(block[i++] + block[i++] * 256);
            Int16 extraFieldLength = (short)(block[i++] + block[i++] * 256);

            block      = new byte[filenameLength];
            n          = ze.ArchiveStream.Read(block, 0, block.Length);
            bytesRead += n;

            // if the UTF8 bit is set for this entry, override the
            // encoding the application requested.

            if ((ze._BitField & 0x0800) == 0x0800)
            {
                // workitem 12744
                ze.AlternateEncoding      = System.Text.Encoding.UTF8;
                ze.AlternateEncodingUsage = ZipOption.Always;
            }

            ze._FileNameInArchive = ze.AlternateEncoding.GetString(block);

            // workitem 6898
            if (ze._FileNameInArchive.EndsWith("/"))
            {
                ze.MarkAsDirectory();
            }

            bytesRead += ze.ProcessExtraField(ze.ArchiveStream, extraFieldLength);

            ze._LengthOfTrailer = 0;

            // workitem 6607 - don't read for directories
            // actually get the compressed size and CRC if necessary
            if (!ze._FileNameInArchive.EndsWith("/") && (ze._BitField & 0x0008) == 0x0008)
            {
                // workitem 8098: ok (restore)
                long posn = ze.ArchiveStream.Position;

                // Here, we're going to loop until we find a ZipEntryDataDescriptorSignature and
                // a consistent data record after that.   To be consistent, the data record must
                // indicate the length of the entry data.
                bool wantMore       = true;
                long SizeOfDataRead = 0;
                int  tries          = 0;
                while (wantMore)
                {
                    tries++;
                    // We call the FindSignature shared routine to find the specified signature
                    // in the already-opened zip archive, starting from the current cursor
                    // position in that filestream.  If we cannot find the signature, then the
                    // routine returns -1, and the ReadHeader() method returns false,
                    // indicating we cannot read a legal entry header.  If we have found it,
                    // then the FindSignature() method returns the number of bytes in the
                    // stream we had to seek forward, to find the sig.  We need this to
                    // determine if the zip entry is valid, later.

                    if (ze._container.ZipFile != null)
                    {
                        ze._container.ZipFile.OnReadBytes(ze);
                    }

                    long d = Ionic.Zip.SharedUtilities.FindSignature(ze.ArchiveStream, ZipConstants.ZipEntryDataDescriptorSignature);
                    if (d == -1)
                    {
                        return(false);
                    }

                    // total size of data read (through all loops of this).
                    SizeOfDataRead += d;

                    if (ze._InputUsesZip64)
                    {
                        // read 1x 4-byte (CRC) and 2x 8-bytes (Compressed Size, Uncompressed Size)
                        block = new byte[20];
                        n     = ze.ArchiveStream.Read(block, 0, block.Length);
                        if (n != 20)
                        {
                            return(false);
                        }

                        // do not increment bytesRead - it is for entry header only.
                        // the data we have just read is a footer (falls after the file data)
                        //bytesRead += n;

                        i                    = 0;
                        ze._Crc32            = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                        ze._CompressedSize   = BitConverter.ToInt64(block, i);
                        i                   += 8;
                        ze._UncompressedSize = BitConverter.ToInt64(block, i);
                        i                   += 8;
                    }
                    else
                    {
                        // read 3x 4-byte fields (CRC, Compressed Size, Uncompressed Size)
                        block = new byte[12];
                        n     = ze.ArchiveStream.Read(block, 0, block.Length);
                        if (n != 12)
                        {
                            return(false);
                        }

                        // do not increment bytesRead - it is for entry header only.
                        // the data we have just read is a footer (falls after the file data)
                        //bytesRead += n;

                        i                    = 0;
                        ze._Crc32            = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                        ze._CompressedSize   = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                        ze._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                    }

                    wantMore = (SizeOfDataRead != ze._CompressedSize);

                    if (wantMore)
                    {
                        // Seek back to un-read the last 12 bytes  - maybe THEY contain
                        // the ZipEntryDataDescriptorSignature.
                        // (12 bytes for the CRC, Comp and Uncomp size.)
                        ze.ArchiveStream.Seek(-12, SeekOrigin.Current);

                        // Adjust the size to account for the false signature read in
                        // FindSignature().
                        SizeOfDataRead += 4;
                    }
                }

                // seek back to previous position, to prepare to read file data
                // workitem 8098: ok (restore)
                ze.ArchiveStream.Seek(posn, SeekOrigin.Begin);

                ze._LengthOfTrailer += ze._InputUsesZip64 ? 24 : 16;  // bytes including sig, CRC, Comp and Uncomp sizes
            }

            ze._CompressedFileDataSize = ze._CompressedSize;


            // bit 0 set indicates that some kind of encryption is in use
            if ((ze._BitField & 0x01) == 0x01)
            {
                {
                    // read in the header data for "weak" encryption
                    ze._WeakEncryptionHeader = new byte[12];
                    bytesRead += ZipEntry.ReadWeakEncryptionHeader(ze._archiveStream, ze._WeakEncryptionHeader);
                    // decrease the filedata size by 12 bytes
                    ze._CompressedFileDataSize -= 12;
                }
            }

            // Remember the size of the blob for this entry.
            // We also have the starting position in the stream for this entry.
            ze._LengthOfHeader = bytesRead;
            ze._TotalEntrySize = ze._LengthOfHeader + ze._CompressedFileDataSize + ze._LengthOfTrailer;


            // We've read in the regular entry header, the extra field, and any
            // encryption header.  The pointer in the file is now at the start of the
            // filedata, which is potentially compressed and encrypted.  Just ahead in
            // the file, there are _CompressedFileDataSize bytes of data, followed by
            // potentially a non-zero length trailer, consisting of optionally, some
            // encryption stuff (10 byte MAC for AES), and the bit-3 trailer (16 or 24
            // bytes).

            return(true);
        }
Esempio n. 9
0
        /// <summary>
        /// Reads one entry from the zip directory structure in the zip file.
        /// </summary>
        /// <param name="zf">
        /// The zipfile for which a directory entry will be read.  From this param, the
        /// method gets the ReadStream and the expected text encoding
        /// (ProvisionalAlternateEncoding) which is used if the entry is not marked
        /// UTF-8.
        /// </param>
        /// <returns>the entry read from the archive.</returns>
        internal static ZipEntry ReadDirEntry(ZipFile zf)
        {
            System.IO.Stream     s = zf.ReadStream;
            System.Text.Encoding expectedEncoding = zf.ProvisionalAlternateEncoding;

            int signature = Ionic.Zip.SharedUtilities.ReadSignature(s);

            // return null if this is not a local file header signature
            if (IsNotValidZipDirEntrySig(signature))
            {
                s.Seek(-4, System.IO.SeekOrigin.Current);

                // Getting "not a ZipDirEntry signature" here is not always wrong or an
                // error.  This can happen when walking through a zipfile.  After the
                // last ZipDirEntry, we expect to read an
                // EndOfCentralDirectorySignature.  When we get this is how we know
                // we've reached the end of the central directory.
                if (signature != ZipConstants.EndOfCentralDirectorySignature &&
                    signature != ZipConstants.Zip64EndOfCentralDirectoryRecordSignature &&
                    signature != ZipConstants.ZipEntrySignature  // workitem 8299
                    )
                {
                    throw new BadReadException(String.Format("  ZipEntry::ReadDirEntry(): Bad signature (0x{0:X8}) at position 0x{1:X8}", signature, s.Position));
                }
                return(null);
            }

            int bytesRead = 42 + 4;

            byte[] block = new byte[42];
            int    n     = s.Read(block, 0, block.Length);

            if (n != block.Length)
            {
                return(null);
            }

            int      i   = 0;
            ZipEntry zde = new ZipEntry();

            zde._Source    = ZipEntrySource.ZipFile;
            zde._container = new ZipContainer(zf);

            unchecked
            {
                zde._VersionMadeBy     = (short)(block[i++] + block[i++] * 256);
                zde._VersionNeeded     = (short)(block[i++] + block[i++] * 256);
                zde._BitField          = (short)(block[i++] + block[i++] * 256);
                zde._CompressionMethod = (Int16)(block[i++] + block[i++] * 256);
                zde._TimeBlob          = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
                zde._LastModified      = Ionic.Zip.SharedUtilities.PackedToDateTime(zde._TimeBlob);
                zde._timestamp        |= ZipEntryTimestamp.DOS;

                zde._Crc32            = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
                zde._CompressedSize   = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                zde._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
            }

            // preserve
            zde._CompressionMethod_FromZipFile = zde._CompressionMethod;

            zde._filenameLength   = (short)(block[i++] + block[i++] * 256);
            zde._extraFieldLength = (short)(block[i++] + block[i++] * 256);
            zde._commentLength    = (short)(block[i++] + block[i++] * 256);
            zde._diskNumber       = (UInt32)(block[i++] + block[i++] * 256);

            zde._InternalFileAttrs = (short)(block[i++] + block[i++] * 256);
            zde._ExternalFileAttrs = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;

            zde._RelativeOffsetOfLocalHeader = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);

            // workitem 7801
            zde.IsText = ((zde._InternalFileAttrs & 0x01) == 0x01);

            block      = new byte[zde._filenameLength];
            n          = s.Read(block, 0, block.Length);
            bytesRead += n;
            if ((zde._BitField & 0x0800) == 0x0800)
            {
                // UTF-8 is in use
                zde._FileNameInArchive = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block);
            }
            else
            {
                zde._FileNameInArchive = Ionic.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding);
            }

            // Console.WriteLine("\nEntry : {0}", zde._LocalFileName);
            // Console.WriteLine("  V Madeby/Needed:      0x{0:X4} / 0x{1:X4}", zde._VersionMadeBy, zde._VersionNeeded);
            // Console.WriteLine("  BitField/Compression: 0x{0:X4} / 0x{1:X4}", zde._BitField, zde._CompressionMethod);
            // Console.WriteLine("  Lastmod:              {0}", zde._LastModified.ToString("u"));
            // Console.WriteLine("  CRC:                  0x{0:X8}", zde._Crc32);
            // Console.WriteLine("  Comp / Uncomp:        0x{0:X8} ({0})   0x{1:X8} ({1})", zde._CompressedSize, zde._UncompressedSize);

            //zde._FileNameInArchive = zde._LocalFileName;

            if (zde.AttributesIndicateDirectory)
            {
                zde.MarkAsDirectory();                                   // may append a slash to filename if nec.
            }
            // workitem 6898
            else if (zde._FileNameInArchive.EndsWith("/"))
            {
                zde.MarkAsDirectory();
            }

            zde._CompressedFileDataSize = zde._CompressedSize;
            if ((zde._BitField & 0x01) == 0x01)
            {
                zde._Encryption_FromZipFile = zde._Encryption = EncryptionAlgorithm.PkzipWeak; // this may change after processing the Extra field
                zde._sourceIsEncrypted      = true;
            }

            if (zde._extraFieldLength > 0)
            {
                zde._InputUsesZip64 = (zde._CompressedSize == 0xFFFFFFFF ||
                                       zde._UncompressedSize == 0xFFFFFFFF ||
                                       zde._RelativeOffsetOfLocalHeader == 0xFFFFFFFF);

                // Console.WriteLine("  Input uses Z64?:      {0}", zde._InputUsesZip64);

                bytesRead += zde.ProcessExtraField(s, zde._extraFieldLength);
                zde._CompressedFileDataSize = zde._CompressedSize;
            }

            // we've processed the extra field, so we know the encryption method is set now.
            if (zde._Encryption == EncryptionAlgorithm.PkzipWeak)
            {
                // the "encryption header" of 12 bytes precedes the file data
                zde._CompressedFileDataSize -= 12;
            }
#if AESCRYPTO
            else if (zde.Encryption == EncryptionAlgorithm.WinZipAes128 ||
                     zde.Encryption == EncryptionAlgorithm.WinZipAes256)
            {
                zde._CompressedFileDataSize = zde.CompressedSize -
                                              (ZipEntry.GetLengthOfCryptoHeaderBytes(zde.Encryption) + 10);
                zde._LengthOfTrailer = 10;
            }
#endif

            // tally the trailing descriptor
            if ((zde._BitField & 0x0008) == 0x0008)
            {
                // sig, CRC, Comp and Uncomp sizes
                if (zde._InputUsesZip64)
                {
                    zde._LengthOfTrailer += 24;
                }
                else
                {
                    zde._LengthOfTrailer += 16;
                }
            }

            if (zde._commentLength > 0)
            {
                block      = new byte[zde._commentLength];
                n          = s.Read(block, 0, block.Length);
                bytesRead += n;
                if ((zde._BitField & 0x0800) == 0x0800)
                {
                    // UTF-8 is in use
                    zde._Comment = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block);
                }
                else
                {
                    zde._Comment = Ionic.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding);
                }
            }
            //zde._LengthOfDirEntry = bytesRead;
            return(zde);
        }
        private ZipEntry AddOrUpdateDirectoryImpl(string directoryName,
                                                  string rootDirectoryPathInArchive,
                                                  AddOrUpdateAction action,
                                                  bool recurse,
                                                  int level)
        {
            if (Verbose)
            {
                StatusMessageTextWriter.WriteLine("{0} {1}...",
                                                  (action == AddOrUpdateAction.AddOnly) ? "adding" : "Adding or updating",
                                                  directoryName);
            }

            if (level == 0)
            {
                _addOperationCanceled = false;
                OnAddStarted();
            }

            // workitem 13371
            if (_addOperationCanceled)
            {
                return(null);
            }

            string   dirForEntries = rootDirectoryPathInArchive;
            ZipEntry baseDir       = null;

            if (level > 0)
            {
                int f = directoryName.Length;
                for (int i = level; i > 0; i--)
                {
                    f = directoryName.LastIndexOfAny("/\\".ToCharArray(), f - 1, f - 1);
                }

                dirForEntries = directoryName.Substring(f + 1);
                dirForEntries = Path.Combine(rootDirectoryPathInArchive, dirForEntries);
            }

            // if not top level, or if the root is non-empty, then explicitly add the directory
            if (level > 0 || rootDirectoryPathInArchive != "")
            {
                baseDir                        = ZipEntry.CreateFromFile(directoryName, dirForEntries);
                baseDir._container             = new ZipContainer(this);
                baseDir.AlternateEncoding      = this.AlternateEncoding; // workitem 6410
                baseDir.AlternateEncodingUsage = this.AlternateEncodingUsage;
                baseDir.MarkAsDirectory();
                baseDir.EmitTimesInWindowsFormatWhenSaving = _emitNtfsTimes;
                baseDir.EmitTimesInUnixFormatWhenSaving    = _emitUnixTimes;

                // add the directory only if it does not exist.
                // It's not an error if it already exists.
                if (!_entries.ContainsKey(baseDir.FileName))
                {
                    InternalAddEntry(baseDir.FileName, baseDir);
                    AfterAddEntry(baseDir);
                }
                dirForEntries = baseDir.FileName;
            }

            if (!_addOperationCanceled)
            {
                String[] filenames = Directory.GetFiles(directoryName);

                if (recurse)
                {
                    // add the files:
                    foreach (String filename in filenames)
                    {
                        if (_addOperationCanceled)
                        {
                            break;
                        }
                        if (action == AddOrUpdateAction.AddOnly)
                        {
                            AddFile(filename, dirForEntries);
                        }
                        else
                        {
                            UpdateFile(filename, dirForEntries);
                        }
                    }

                    if (!_addOperationCanceled)
                    {
                        // add the subdirectories:
                        String[] dirnames = Directory.GetDirectories(directoryName);
                        foreach (String dir in dirnames)
                        {
                            // workitem 8617: Optionally traverse reparse points
                            FileAttributes fileAttrs = System.IO.File.GetAttributes(dir);
                            if (this.AddDirectoryWillTraverseReparsePoints ||
                                ((fileAttrs & FileAttributes.ReparsePoint) == 0)
                                )
                            {
                                AddOrUpdateDirectoryImpl(dir, rootDirectoryPathInArchive, action, recurse, level + 1);
                            }
                        }
                    }
                }
            }

            if (level == 0)
            {
                OnAddCompleted();
            }

            return(baseDir);
        }
Esempio n. 11
0
        /// <summary>
        /// Reads one entry from the zip directory structure in the zip file.
        /// </summary>
        /// <param name="s">the stream from which to read.</param>
        /// <param name="expectedEncoding">
        /// The text encoding to use if the entry is not marked UTF-8.
        /// </param>
        /// <returns>the entry read from the archive.</returns>
        public static ZipEntry ReadDirEntry(System.IO.Stream s, System.Text.Encoding expectedEncoding)
        {
            long cdrPosition = s.Position;
            int  signature   = Ionic.Zip.SharedUtilities.ReadSignature(s);

            // return null if this is not a local file header signature
            if (IsNotValidZipDirEntrySig(signature))
            {
                s.Seek(-4, System.IO.SeekOrigin.Current);

                // Getting "not a ZipDirEntry signature" here is not always wrong or an error.
                // This can happen when walking through a zipfile.  After the last ZipDirEntry,
                // we expect to read an EndOfCentralDirectorySignature.  When we get this is how we
                // know we've reached the end of the central directory.
                if (signature != ZipConstants.EndOfCentralDirectorySignature &&
                    signature != ZipConstants.Zip64EndOfCentralDirectoryRecordSignature)
                {
                    throw new BadReadException(String.Format("  ZipEntry::ReadDirEntry(): Bad signature (0x{0:X8}) at position 0x{1:X8}", signature, s.Position));
                }
                return(null);
            }

            int bytesRead = 42 + 4;

            byte[] block = new byte[42];
            int    n     = s.Read(block, 0, block.Length);

            if (n != block.Length)
            {
                return(null);
            }

            int      i   = 0;
            ZipEntry zde = new ZipEntry();

            zde._archiveStream = s;
            zde._cdrPosition   = cdrPosition;

            zde._VersionMadeBy     = (short)(block[i++] + block[i++] * 256);
            zde._VersionNeeded     = (short)(block[i++] + block[i++] * 256);
            zde._BitField          = (short)(block[i++] + block[i++] * 256);
            zde._CompressionMethod = (short)(block[i++] + block[i++] * 256);
            zde._TimeBlob          = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
            zde._LastModified      = Ionic.Zip.SharedUtilities.PackedToDateTime(zde._TimeBlob);
            zde._Crc32             = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;


            zde._CompressedSize   = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
            zde._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);

            //DateTime lastModified = Ionic.Utils.Zip.SharedUtilities.PackedToDateTime(lastModDateTime);
            //i += 24;



            zde._filenameLength   = (short)(block[i++] + block[i++] * 256);
            zde._extraFieldLength = (short)(block[i++] + block[i++] * 256);
            zde._commentLength    = (short)(block[i++] + block[i++] * 256);
            //Int16 diskNumber = (short)(block[i++] + block[i++] * 256);
            i += 2;

            zde._InternalFileAttrs = (short)(block[i++] + block[i++] * 256);
            zde._ExternalFileAttrs = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;

            zde._RelativeOffsetOfLocalHeader = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);

            block      = new byte[zde._filenameLength];
            n          = s.Read(block, 0, block.Length);
            bytesRead += n;
            if ((zde._BitField & 0x0800) == 0x0800)
            {
                // UTF-8 is in use
                zde._LocalFileName = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block, block.Length);
            }
            else
            {
                zde._LocalFileName = Ionic.Zip.SharedUtilities.StringFromBuffer(block, block.Length, expectedEncoding);
            }


//             Console.WriteLine("\nEntry : {0}", zde._LocalFileName);
//             Console.WriteLine("  V Madeby:    0x{0:X4}", zde._VersionMadeBy);
//             Console.WriteLine("  V Needed:    0x{0:X4}", zde._VersionNeeded);
//             Console.WriteLine("  BitField:    0x{0:X4}", zde._BitField);
//             Console.WriteLine("  Compression: 0x{0:X4}", zde._CompressionMethod);
//             Console.WriteLine("  Lastmod:     {0}", zde._LastModified.ToString("u"));
//             Console.WriteLine("  CRC:         0x{0:X8}", zde._Crc32);
//             Console.WriteLine("  Comp:        0x{0:X8} ({0})", zde._CompressedSize);
//             Console.WriteLine("  Uncomp:      0x{0:X8} ({0})", zde._UncompressedSize);

            zde._FileNameInArchive = zde._LocalFileName;

            if (zde.AttributesIndicateDirectory)
            {
                zde.MarkAsDirectory();                                   // may append a slash to filename if nec.
            }
            // workitem 6898
            if (zde._LocalFileName.EndsWith("/"))
            {
                zde.MarkAsDirectory();
            }


            zde._CompressedFileDataSize = zde._CompressedSize;
            if ((zde._BitField & 0x01) == 0x01)
            {
                zde._Encryption        = EncryptionAlgorithm.PkzipWeak; // this may change after processing the Extra field
                zde._sourceIsEncrypted = true;
            }

            if (zde._extraFieldLength > 0)
            {
                //Console.WriteLine("ZDE Extra Field length: {0}", zde._extraFieldLength);
                zde._InputUsesZip64 = ((uint)zde._CompressedSize == 0xFFFFFFFF ||
                                       (uint)zde._UncompressedSize == 0xFFFFFFFF ||
                                       (uint)zde._RelativeOffsetOfLocalHeader == 0xFFFFFFFF);

                bytesRead += zde.ProcessExtraField(zde._extraFieldLength);
                zde._CompressedFileDataSize = zde._CompressedSize;
                //Console.WriteLine("  Compressed:  0x{0:X8} ({0})", zde._CompressedSize);
            }

            // we've processed the extra field, so we know the encryption method is set now.
            if (zde._Encryption == EncryptionAlgorithm.PkzipWeak)
            {
                // the "encryption header" of 12 bytes precedes the file data
                zde._CompressedFileDataSize -= 12;
            }
#if !NETCF20
            else if (zde.Encryption == EncryptionAlgorithm.WinZipAes128 ||
                     zde.Encryption == EncryptionAlgorithm.WinZipAes256)
            {
                zde._CompressedFileDataSize = zde.CompressedSize -
                                              ((zde._KeyStrengthInBits / 8 / 2) + 10 + 2);// zde._aesCrypto.SizeOfEncryptionMetadata;
                zde._LengthOfTrailer = 10;
                //Console.WriteLine("  CFDS:        0x{0:X8} ({0})", zde._CompressedFileDataSize);
                //Console.WriteLine("  Actual Compression: 0x{0:X4}", zde._CompressionMethod);
            }
#endif
            if (zde._commentLength > 0)
            {
                block      = new byte[zde._commentLength];
                n          = s.Read(block, 0, block.Length);
                bytesRead += n;
                if ((zde._BitField & 0x0800) == 0x0800)
                {
                    // UTF-8 is in use
                    zde._Comment = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block, block.Length);
                }
                else
                {
                    zde._Comment = Ionic.Zip.SharedUtilities.StringFromBuffer(block, block.Length, expectedEncoding);
                }
            }
            zde._LengthOfDirEntry = bytesRead;
            return(zde);
        }
Esempio n. 12
0
        private static bool ReadHeader(ZipEntry ze, System.Text.Encoding defaultEncoding)
        {
            int bytesRead = 0;

            // change for workitem 8098
            // ze._RelativeOffsetOfLocalHeader = ze.ArchiveStream.Position;
            ze._RelativeOffsetOfLocalHeader = ze._zipfile.RelativeOffset;

            int signature = Ionic.Zip.SharedUtilities.ReadSignature(ze.ArchiveStream);

            bytesRead += 4;

            // Return false if this is not a local file header signature.
            if (ZipEntry.IsNotValidSig(signature))
            {
                // Getting "not a ZipEntry signature" is not always wrong or an error.
                // This will happen after the last entry in a zipfile.  In that case, we
                // expect to read :
                //    a ZipDirEntry signature (if a non-empty zip file) or
                //    a ZipConstants.EndOfCentralDirectorySignature.
                //
                // Anything else is a surprise.

                ze.ArchiveStream.Seek(-4, SeekOrigin.Current); // unread the signature
                if (ZipEntry.IsNotValidZipDirEntrySig(signature) && (signature != ZipConstants.EndOfCentralDirectorySignature))
                {
                    throw new BadReadException(String.Format("  ZipEntry::ReadHeader(): Bad signature (0x{0:X8}) at position  0x{1:X8}", signature, ze.ArchiveStream.Position));
                }
                return(false);
            }

            byte[] block = new byte[26];
            int    n     = ze.ArchiveStream.Read(block, 0, block.Length);

            if (n != block.Length)
            {
                return(false);
            }
            bytesRead += n;

            int i = 0;

            ze._VersionNeeded     = (short)(block[i++] + block[i++] * 256);
            ze._BitField          = (short)(block[i++] + block[i++] * 256);
            ze._CompressionMethod = (short)(block[i++] + block[i++] * 256);
            ze._TimeBlob          = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256;
            // transform the time data into something usable (a DateTime)
            ze._LastModified = Ionic.Zip.SharedUtilities.PackedToDateTime(ze._TimeBlob);
            ze._timestamp   |= ZipEntryTimestamp.DOS;

            // NB: if ((ze._BitField & 0x0008) != 0x0008), then the Compressed, uncompressed and
            // CRC values are not true values; the true values will follow the entry data.
            // But, regardless of the status of bit 3 in the bitfield, the slots for
            // the three amigos may contain marker values for ZIP64.  So we must read them.
            {
                ze._Crc32            = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                ze._CompressedSize   = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                ze._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);

                if ((uint)ze._CompressedSize == 0xFFFFFFFF ||
                    (uint)ze._UncompressedSize == 0xFFFFFFFF)
                {
                    ze._InputUsesZip64 = true;
                }
            }

            Int16 filenameLength   = (short)(block[i++] + block[i++] * 256);
            Int16 extraFieldLength = (short)(block[i++] + block[i++] * 256);

            block      = new byte[filenameLength];
            n          = ze.ArchiveStream.Read(block, 0, block.Length);
            bytesRead += n;

            // if the UTF8 bit is set for this entry, override the encoding the application requested.
            ze._actualEncoding = ((ze._BitField & 0x0800) == 0x0800)
                ? System.Text.Encoding.UTF8
                : defaultEncoding;

            // need to use this form of GetString() for .NET CF
            ze._FileNameInArchive = ze._actualEncoding.GetString(block, 0, block.Length);

            // when creating an entry by reading, the LocalFileName is the same as the FileNameInArchive
            ze._LocalFileName = ze._FileNameInArchive;

            // workitem 6898
            if (ze._LocalFileName.EndsWith("/"))
            {
                ze.MarkAsDirectory();
            }

            bytesRead += ze.ProcessExtraField(extraFieldLength);

            ze._LengthOfTrailer = 0;

            // workitem 6607 - don't read for directories
            // actually get the compressed size and CRC if necessary
            if (!ze._LocalFileName.EndsWith("/") && (ze._BitField & 0x0008) == 0x0008)
            {
                // This descriptor exists only if bit 3 of the general
                // purpose bit flag is set (see below).  It is byte aligned
                // and immediately follows the last byte of compressed data,
                // as well as any encryption trailer, as with AES.
                // This descriptor is used only when it was not possible to
                // seek in the output .ZIP file, e.g., when the output .ZIP file
                // was standard output or a non-seekable device.  For ZIP64(tm) format
                // archives, the compressed and uncompressed sizes are 8 bytes each.

                // workitem 8098: ok (restore)
                long posn = ze.ArchiveStream.Position;

                // Here, we're going to loop until we find a ZipEntryDataDescriptorSignature and
                // a consistent data record after that.   To be consistent, the data record must
                // indicate the length of the entry data.
                bool wantMore       = true;
                long SizeOfDataRead = 0;
                int  tries          = 0;
                while (wantMore)
                {
                    tries++;
                    // We call the FindSignature shared routine to find the specified signature
                    // in the already-opened zip archive, starting from the current cursor
                    // position in that filestream.  If we cannot find the signature, then the
                    // routine returns -1, and the ReadHeader() method returns false,
                    // indicating we cannot read a legal entry header.  If we have found it,
                    // then the FindSignature() method returns the number of bytes in the
                    // stream we had to seek forward, to find the sig.  We need this to
                    // determine if the zip entry is valid, later.

                    ze._zipfile.OnReadBytes(ze);

                    long d = Ionic.Zip.SharedUtilities.FindSignature(ze.ArchiveStream, ZipConstants.ZipEntryDataDescriptorSignature);
                    if (d == -1)
                    {
                        return(false);
                    }

                    // total size of data read (through all loops of this).
                    SizeOfDataRead += d;

                    if (ze._InputUsesZip64)
                    {
                        // read 1x 4-byte (CRC) and 2x 8-bytes (Compressed Size, Uncompressed Size)
                        block = new byte[20];
                        n     = ze.ArchiveStream.Read(block, 0, block.Length);
                        if (n != 20)
                        {
                            return(false);
                        }

                        // do not increment bytesRead - it is for entry header only.
                        // the data we have just read is a footer (falls after the file data)
                        //bytesRead += n;

                        i                    = 0;
                        ze._Crc32            = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                        ze._CompressedSize   = BitConverter.ToInt64(block, i);
                        i                   += 8;
                        ze._UncompressedSize = BitConverter.ToInt64(block, i);
                        i                   += 8;

                        ze._LengthOfTrailer += 24;  // bytes including sig, CRC, Comp and Uncomp sizes
                    }
                    else
                    {
                        // read 3x 4-byte fields (CRC, Compressed Size, Uncompressed Size)
                        block = new byte[12];
                        n     = ze.ArchiveStream.Read(block, 0, block.Length);
                        if (n != 12)
                        {
                            return(false);
                        }

                        // do not increment bytesRead - it is for entry header only.
                        // the data we have just read is a footer (falls after the file data)
                        //bytesRead += n;

                        i                    = 0;
                        ze._Crc32            = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                        ze._CompressedSize   = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);
                        ze._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256);

                        ze._LengthOfTrailer += 16;  // bytes including sig, CRC, Comp and Uncomp sizes
                    }

                    wantMore = (SizeOfDataRead != ze._CompressedSize);

                    if (wantMore)
                    {
                        // Seek back to un-read the last 12 bytes  - maybe THEY contain
                        // the ZipEntryDataDescriptorSignature.
                        // (12 bytes for the CRC, Comp and Uncomp size.)
                        ze.ArchiveStream.Seek(-12, SeekOrigin.Current);

                        // Adjust the size to account for the false signature read in
                        // FindSignature().
                        SizeOfDataRead += 4;
                    }
                }

                // seek back to previous position, to prepare to read file data
                // workitem 8098: ok (restore)
                ze.ArchiveStream.Seek(posn, SeekOrigin.Begin);
            }

            ze._CompressedFileDataSize = ze._CompressedSize;


            // bit 0 set indicates that some kind of encryption is in use
            if ((ze._BitField & 0x01) == 0x01)
            {
#if AESCRYPTO
                if (ze.Encryption == EncryptionAlgorithm.WinZipAes128 ||
                    ze.Encryption == EncryptionAlgorithm.WinZipAes256)
                {
                    // read in the WinZip AES metadata: salt + PV. 18 bytes for AES256. 10 bytes for AES128.
                    ze._aesCrypto = WinZipAesCrypto.ReadFromStream(null, ze._KeyStrengthInBits, ze.ArchiveStream);
                    bytesRead    += ze._aesCrypto.SizeOfEncryptionMetadata - 10; // MAC (follows crypto bytes)
                    // according to WinZip, the CompressedSize includes the AES Crypto framing data.
                    ze._CompressedFileDataSize -= ze._aesCrypto.SizeOfEncryptionMetadata;
                    ze._LengthOfTrailer        += 10; // MAC
                }
                else
#endif
                {
                    // read in the header data for "weak" encryption
                    ze._WeakEncryptionHeader = new byte[12];
                    bytesRead += ZipEntry.ReadWeakEncryptionHeader(ze._archiveStream, ze._WeakEncryptionHeader);
                    // decrease the filedata size by 12 bytes
                    ze._CompressedFileDataSize -= 12;
                }
            }

            // Remember the size of the blob for this entry.
            // We also have the starting position in the stream for this entry.
            ze._LengthOfHeader = bytesRead;
            ze._TotalEntrySize = ze._LengthOfHeader + ze._CompressedFileDataSize + ze._LengthOfTrailer;


            // We've read in the regular entry header, the extra field, and any encryption
            // header.  The pointer in the file is now at the start of the filedata, which is
            // potentially compressed and encrypted.  Just ahead in the file, there are
            // _CompressedFileDataSize bytes of data, followed by potentially a non-zero length
            // trailer, consisting of optionally, some encryption stuff (10 byte MAC for AES),
            // and the bit-3 trailer (16 or 24 bytes).

            return(true);
        }