private static System.Text.Encoding GetEncoding(ZipContainer container, string t)
        {
            switch (container.AlternateEncodingUsage)
            {
            case ZipOption.Always:
                return(container.AlternateEncoding);

            case ZipOption.Never:
                return(container.DefaultEncoding);
            }

            // AsNecessary is in force
            var e = container.DefaultEncoding;

            if (t == null)
            {
                return(e);
            }

            var bytes = e.GetBytes(t);
            var t2    = e.GetString(bytes, 0, bytes.Length);

            if (t2.Equals(t))
            {
                return(e);
            }
            return(container.AlternateEncoding);
        }
Beispiel #2
0
        // Token: 0x0600051C RID: 1308 RVA: 0x000251D0 File Offset: 0x000233D0
        private static Encoding GetEncoding(ZipContainer container, string t)
        {
            switch (container.AlternateEncodingUsage)
            {
            case ZipOption.Default:
                return(container.DefaultEncoding);

            case ZipOption.Always:
                return(container.AlternateEncoding);
            }
            Encoding defaultEncoding = container.DefaultEncoding;

            if (t == null)
            {
                return(defaultEncoding);
            }
            byte[] bytes   = defaultEncoding.GetBytes(t);
            string @string = defaultEncoding.GetString(bytes, 0, bytes.Length);

            if (@string.Equals(t))
            {
                return(defaultEncoding);
            }
            return(container.AlternateEncoding);
        }
Beispiel #3
0
        /// <summary>
        /// Extract to a stream
        /// In other words, you can extract to a stream or to a directory (filesystem), but not both!
        /// The Password param is required for encrypted entries.
        /// </summary>
        void InternalExtractToStream(Stream outStream, string password, ZipContainer zipContainer, ZipEntrySource zipEntrySource, string fileName)
        {
            // workitem 10355
            if (zipContainer.ZipFile == null)
            {
                throw new InvalidOperationException("Use Extract() only with ZipFile.");
            }

            zipContainer.ZipFile.Reset(false);

            if (zipEntrySource != ZipEntrySource.ZipFile)
            {
                throw new BadStateException("You must call ZipFile.Save before calling any Extract method");
            }

            OnBeforeExtract(this, null, zipContainer.ZipFile);

            _ioOperationCanceled = false;

            try
            {
                ValidateCompression(_CompressionMethod_FromZipFile, fileName, GetUnsupportedCompressionMethod(_CompressionMethod));
                ValidateEncryption(Encryption, fileName, _UnsupportedAlgorithmId);

                if (IsDoneWithOutputToStream())
                {
                    WriteStatus("extract dir {0}...", null);
                    // if true, then the entry was a directory and has been created.
                    // We need to fire the Extract Event.
                    OnAfterExtract(null);
                    return;
                }

                // If no password explicitly specified, use the password on the entry itself,
                // or on the zipfile itself.
                if (_Encryption_FromZipFile != EncryptionAlgorithm.None)
                {
                    EnsurePassword(password);
                }

                WriteStatus("extract entry {0} to stream...", fileName);

                var archiveStream = ArchiveStream;

                if (ExtractToStream(archiveStream, outStream, Encryption, _Crc32))
                {
                    goto ExitTry;
                }

                OnAfterExtract(null);

                ExitTry :;
            }
            catch (Exception)
            {
                _ioOperationCanceled = true;
                throw;
            }
        }
Beispiel #4
0
        /// <summary>
        /// Reads one <c>ZipEntry</c> from the given stream.  If the entry is encrypted, we don't
        /// decrypt at this point.  We also do not decompress.  Mostly we read metadata.
        /// </summary>
        /// <param name="zc">the ZipContainer this entry belongs to.</param>
        /// <param name="first">true of this is the first entry being read from the stream.</param>
        /// <returns>the <c>ZipEntry</c> read from the stream.</returns>
        internal static ZipEntry ReadEntry(ZipContainer zc, bool first)
        {
            ZipFile zf = zc.ZipFile;

            Stream s = zc.ReadStream;

            System.Text.Encoding defaultEncoding = zc.ProvisionalAlternateEncoding;
            ZipEntry             entry           = new ZipEntry();

            entry._Source        = ZipEntrySource.ZipFile;
            entry._container     = zc;
            entry._archiveStream = s;
            if (zf != null)
            {
                zf.OnReadEntry(true, null);
            }

            if (first)
            {
                HandlePK00Prefix(s);
            }

            // Read entry header, including any encryption header
            if (!ReadHeader(entry, defaultEncoding))
            {
                return(null);
            }

            // Store the position in the stream for this entry
            // change for workitem 8098
            entry.__FileDataPosition = entry.ArchiveStream.Position;

            // seek past the data without reading it. We will read on Extract()
            s.Seek(entry._CompressedFileDataSize + entry._LengthOfTrailer, SeekOrigin.Current);
            // workitem 10178
            Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s);

            // ReadHeader moves the file pointer to the end of the entry header,
            // as well as any encryption header.

            // CompressedFileDataSize includes:
            //   the maybe compressed, maybe encrypted file data
            //   the encryption trailer, if any
            //   the bit 3 descriptor, if any

            // workitem 5306
            // http://www.codeplex.com/DotNetZip/WorkItem/View.aspx?WorkItemId=5306
            HandleUnexpectedDataDescriptor(entry);

            if (zf != null)
            {
                zf.OnReadBytes(entry);
                zf.OnReadEntry(false, entry);
            }

            return(entry);
        }
Beispiel #5
0
 private void _Init(Stream stream, bool leaveOpen)
 {
     _inputStream = stream;
     if (!_inputStream.CanRead)
     {
         throw new ZipException("The stream must be readable.");
     }
     _container = new ZipContainer(this);
     _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437");
     _leaveUnderlyingStreamOpen    = leaveOpen;
     _findRequired = true;
 }
 private void _Init(Stream stream, bool leaveOpen, string name)
 {
     _inputStream = stream;
     if (!_inputStream.CanRead)
     {
         throw new ZipException("The stream must be readable.");
     }
     _container = new ZipContainer(this);
     _provisionalAlternateEncoding = SharedUtilities.ibm437;
     _leaveUnderlyingStreamOpen    = leaveOpen;
     _findRequired = true;
     _name         = name ?? "(stream)";
 }
Beispiel #7
0
        /// <summary>
        /// Reads one <c>ZipEntry</c> from the given stream.  If the entry is encrypted, we don't
        /// decrypt at this point.  We also do not decompress.  Mostly we read metadata.
        /// </summary>
        /// <param name="zc">the ZipContainer this entry belongs to.</param>
        /// <param name="first">true of this is the first entry being read from the stream.</param>
        /// <returns>the <c>ZipEntry</c> read from the stream.</returns>
        internal static ZipEntry ReadEntry(ZipContainer zc, bool first)
        {
            ZipFile zf = zc.ZipFile;

            Stream s = zc.ReadStream;

            System.Text.Encoding defaultEncoding = zc.ProvisionalAlternateEncoding;
            ZipEntry entry = new ZipEntry();
            entry._Source = ZipEntrySource.ZipFile;
            entry._container = zc;
            entry._archiveStream = s;
            if (zf != null)
                zf.OnReadEntry(true, null);

            if (first) HandlePK00Prefix(s);

            // Read entry header, including any encryption header
            if (!ReadHeader(entry, defaultEncoding)) return null;

            // Store the position in the stream for this entry
            // change for workitem 8098
            entry.__FileDataPosition = entry.ArchiveStream.Position;

            // seek past the data without reading it. We will read on Extract()
            s.Seek(entry._CompressedFileDataSize + entry._LengthOfTrailer, SeekOrigin.Current);
            // workitem 10178
            Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s);

            // ReadHeader moves the file pointer to the end of the entry header,
            // as well as any encryption header.

            // CompressedFileDataSize includes:
            //   the maybe compressed, maybe encrypted file data
            //   the encryption trailer, if any
            //   the bit 3 descriptor, if any

            // workitem 5306
            // http://www.codeplex.com/DotNetZip/WorkItem/View.aspx?WorkItemId=5306
            HandleUnexpectedDataDescriptor(entry);

            if (zf != null)
            {
                zf.OnReadBytes(entry);
                zf.OnReadEntry(false, entry);
            }

            return entry;
        }
        private void _Init(Stream stream, bool leaveOpen, string name)
        {
            _inputStream = stream;
            if (!_inputStream.CanRead)
            {
                throw new ZipException("The stream must be readable.");
            }
            _container = new ZipContainer(this);
#if (Core)
            _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("utf-8");
#else
            _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437");
#endif
            _leaveUnderlyingStreamOpen = leaveOpen;
            _findRequired = true;
            _name         = name ?? "(stream)";
        }
        internal static ZipEntry ReadEntry(ZipContainer zc, bool first)
        {
            ZipFile zf = zc.ZipFile;
            Stream  s  = zc.ReadStream;

            System.Text.Encoding defaultEncoding = zc.AlternateEncoding;
            ZipEntry             entry           = new ZipEntry();

            entry._Source        = ZipEntrySource.ZipFile;
            entry._container     = zc;
            entry._archiveStream = s;
            if (zf != null)
            {
                zf.OnReadEntry(true, null);
            }

            if (first)
            {
                HandlePK00Prefix(s);
            }

            // Read entry header, including any encryption header
            if (!ReadHeader(entry, defaultEncoding))
            {
                return(null);
            }

            // Store the position in the stream for this entry
            // change for workitem 8098
            entry.__FileDataPosition = entry.ArchiveStream.Position;

            // seek past the data without reading it. We will read on Extract()
            s.Seek(entry._CompressedFileDataSize + entry._LengthOfTrailer, SeekOrigin.Current);

            HandleUnexpectedDataDescriptor(entry);

            if (zf != null)
            {
                zf.OnReadBytes(entry);
                zf.OnReadEntry(false, entry);
            }

            return(entry);
        }
        private void _Init(Stream stream, bool leaveOpen, string name)
        {
            _inputStream = stream;
            if (!_inputStream.CanRead)
            {
                throw new ZipException("The stream must be readable.");
            }
            _container = new ZipContainer(this);

#if NETSTANDARD2_0 || NETSTANDARD2_1
            if (_provisionalAlternateEncoding == null)
            {
                _provisionalAlternateEncoding = System.Text.Encoding.ASCII;
            }
#elif NETCOREAPP2_0 || NET5_0 || NET6_0 || NETCOREAPP3_0 || NETCOREAPP3_1
            if (_provisionalAlternateEncoding == null)
            {
                try
                {
                    _provisionalAlternateEncoding = System.Text.CodePagesEncodingProvider.Instance.GetEncoding(1252);
                }
                catch (Exception /*e*/)
                {
                }
            }
#else
            if (_provisionalAlternateEncoding == null)
            {
                try
                {
                    _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding(1252);
                }
                catch (Exception /*e*/)
                {
                }
            }
#endif

            _leaveUnderlyingStreamOpen = leaveOpen;
            _findRequired = true;
            _name         = name ?? "(stream)";
        }
Beispiel #11
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;
                // in lieu of hashset, use a dictionary
                var previouslySeen = new Dictionary<String,Object>();
                while ((de = ZipEntry.ReadDirEntry(zf, previouslySeen)) != 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();
                    }
                    previouslySeen.Add(de.FileName,null); // to prevent dupes
                }

                // 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 (ZipException) { }
            catch (IOException) { }

            zf.OnReadCompleted();
        }
Beispiel #12
0
        // Token: 0x060005F6 RID: 1526 RVA: 0x00039A20 File Offset: 0x00037C20
        private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory, long EndOfCentralDirectory, Zip64Option zip64, int entryCount, string comment, ZipContainer container)
        {
            Encoding encoding = ZipOutput.GetEncoding(container, comment);
            int      num      = 22;

            byte[] array = null;
            short  num2  = 0;

            if (comment != null && comment.Length != 0)
            {
                array = encoding.GetBytes(comment);
                num2  = (short)array.Length;
            }
            num += (int)num2;
            byte[] array2 = new byte[num];
            byte[] bytes  = BitConverter.GetBytes(101010256U);
            Array.Copy(bytes, 0, array2, 0, 4);
            array2[4] = 0;
            array2[5] = 0;
            array2[6] = 0;
            byte[] array3 = array2;
            int    num3   = 7;
            int    num4   = 8;

            array3[num3] = 0;
            if (entryCount < 65535)
            {
                if (zip64 != Zip64Option.Always)
                {
                    array2[num4++] = (byte)(entryCount & 255);
                    array2[num4++] = (byte)((entryCount & 65280) >> 8);
                    array2[num4++] = (byte)(entryCount & 255);
                    array2[num4++] = (byte)((entryCount & 65280) >> 8);
                    goto IL_F2;
                }
            }
            for (int i = 0; i < 4; i++)
            {
                array2[num4++] = byte.MaxValue;
            }
IL_F2:
            long num5 = EndOfCentralDirectory - StartOfCentralDirectory;

            if (num5 < 4294967295L && StartOfCentralDirectory < 4294967295L)
            {
                array2[num4++] = (byte)(num5 & 255L);
                array2[num4++] = (byte)((num5 & 65280L) >> 8);
                array2[num4++] = (byte)((num5 & 16711680L) >> 16);
                array2[num4++] = (byte)((num5 & 4278190080L) >> 24);
                array2[num4++] = (byte)(StartOfCentralDirectory & 255L);
                array2[num4++] = (byte)((StartOfCentralDirectory & 65280L) >> 8);
                array2[num4++] = (byte)((StartOfCentralDirectory & 16711680L) >> 16);
                array2[num4++] = (byte)((StartOfCentralDirectory & 4278190080L) >> 24);
            }
            else
            {
                for (int i = 0; i < 8; i++)
                {
                    array2[num4++] = byte.MaxValue;
                }
            }
            if (comment != null && comment.Length != 0)
            {
                if ((int)num2 + num4 + 2 > array2.Length)
                {
                    num2 = (short)(array2.Length - num4 - 2);
                }
                array2[num4++] = (byte)(num2 & 255);
                array2[num4++] = (byte)(((int)num2 & 65280) >> 8);
                if (num2 != 0)
                {
                    int i = 0;
                    while (i < (int)num2 && num4 + i < array2.Length)
                    {
                        array2[num4 + i] = array[i];
                        i++;
                    }
                    num4 += i;
                }
            }
            else
            {
                array2[num4++] = 0;
                array2[num4++] = 0;
            }
            return(array2);
        }
Beispiel #13
0
        // Token: 0x0600051D RID: 1309 RVA: 0x00025244 File Offset: 0x00023444
        private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory, long EndOfCentralDirectory, Zip64Option zip64, int entryCount, string comment, ZipContainer container)
        {
            Encoding encoding = ZipOutput.GetEncoding(container, comment);
            int      num      = 22;

            byte[] array = null;
            short  num2  = 0;

            if (comment != null && comment.Length != 0)
            {
                array = encoding.GetBytes(comment);
                num2  = (short)array.Length;
            }
            num += (int)num2;
            byte[] array2 = new byte[num];
            int    num3   = 0;

            byte[] bytes = BitConverter.GetBytes(101010256u);
            Array.Copy(bytes, 0, array2, num3, 4);
            num3          += 4;
            array2[num3++] = 0;
            array2[num3++] = 0;
            array2[num3++] = 0;
            array2[num3++] = 0;
            if (entryCount >= 65535 || zip64 == Zip64Option.Always)
            {
                for (int i = 0; i < 4; i++)
                {
                    array2[num3++] = byte.MaxValue;
                }
            }
            else
            {
                array2[num3++] = (byte)(entryCount & 255);
                array2[num3++] = (byte)((entryCount & 65280) >> 8);
                array2[num3++] = (byte)(entryCount & 255);
                array2[num3++] = (byte)((entryCount & 65280) >> 8);
            }
            long num4 = EndOfCentralDirectory - StartOfCentralDirectory;

            if (num4 >= (long)((ulong)-1) || StartOfCentralDirectory >= (long)((ulong)-1))
            {
                for (int i = 0; i < 8; i++)
                {
                    array2[num3++] = byte.MaxValue;
                }
            }
            else
            {
                array2[num3++] = (byte)(num4 & 255L);
                array2[num3++] = (byte)((num4 & 65280L) >> 8);
                array2[num3++] = (byte)((num4 & 16711680L) >> 16);
                array2[num3++] = (byte)((num4 & (long)((ulong)-16777216)) >> 24);
                array2[num3++] = (byte)(StartOfCentralDirectory & 255L);
                array2[num3++] = (byte)((StartOfCentralDirectory & 65280L) >> 8);
                array2[num3++] = (byte)((StartOfCentralDirectory & 16711680L) >> 16);
                array2[num3++] = (byte)((StartOfCentralDirectory & (long)((ulong)-16777216)) >> 24);
            }
            if (comment == null || comment.Length == 0)
            {
                array2[num3++] = 0;
                array2[num3++] = 0;
            }
            else
            {
                if ((int)num2 + num3 + 2 > array2.Length)
                {
                    num2 = (short)(array2.Length - num3 - 2);
                }
                array2[num3++] = (byte)(num2 & 255);
                array2[num3++] = (byte)(((int)num2 & 65280) >> 8);
                if (num2 != 0)
                {
                    int i = 0;
                    while (i < (int)num2 && num3 + i < array2.Length)
                    {
                        array2[num3 + i] = array[i];
                        i++;
                    }
                    num3 += i;
                }
            }
            return(array2);
        }
Beispiel #14
0
        // Token: 0x0600051B RID: 1307 RVA: 0x00024F38 File Offset: 0x00023138
        public static bool WriteCentralDirectoryStructure(Stream s, ICollection <ZipEntry> entries, uint numSegments, Zip64Option zip64, string comment, ZipContainer container)
        {
            ZipSegmentedStream zipSegmentedStream = s as ZipSegmentedStream;

            if (zipSegmentedStream != null)
            {
                zipSegmentedStream.ContiguousWrite = true;
            }
            long num = 0L;

            using (MemoryStream memoryStream = new MemoryStream())
            {
                foreach (ZipEntry zipEntry in entries)
                {
                    if (zipEntry.IncludedInMostRecentSave)
                    {
                        zipEntry.WriteCentralDirectoryEntry(memoryStream);
                    }
                }
                byte[] array = memoryStream.ToArray();
                s.Write(array, 0, array.Length);
                num = (long)array.Length;
            }
            CountingStream countingStream = s as CountingStream;
            long           num2           = (countingStream != null) ? countingStream.ComputedPosition : s.Position;
            long           num3           = num2 - num;
            uint           num4           = (zipSegmentedStream != null) ? zipSegmentedStream.CurrentSegment : 0u;
            long           num5           = num2 - num3;
            int            num6           = ZipOutput.CountEntries(entries);
            bool           flag           = zip64 == Zip64Option.Always || num6 >= 65535 || num5 > (long)((ulong)-1) || num3 > (long)((ulong)-1);

            byte[] array3;
            if (flag)
            {
                if (zip64 == Zip64Option.Default)
                {
                    StackFrame stackFrame = new StackFrame(1);
                    if (stackFrame.GetMethod().DeclaringType == typeof(ZipFile))
                    {
                        throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipFile.UseZip64WhenSaving property.");
                    }
                    throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipOutputStream.EnableZip64 property.");
                }
                else
                {
                    byte[] array2 = ZipOutput.GenZip64EndOfCentralDirectory(num3, num2, num6, numSegments);
                    array3 = ZipOutput.GenCentralDirectoryFooter(num3, num2, zip64, num6, comment, container);
                    if (num4 != 0u)
                    {
                        uint value = zipSegmentedStream.ComputeSegment(array2.Length + array3.Length);
                        int  num7  = 16;
                        Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4);
                        num7 += 4;
                        Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4);
                        num7 = 60;
                        Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4);
                        num7 += 4;
                        num7 += 8;
                        Array.Copy(BitConverter.GetBytes(value), 0, array2, num7, 4);
                    }
                    s.Write(array2, 0, array2.Length);
                }
            }
            else
            {
                array3 = ZipOutput.GenCentralDirectoryFooter(num3, num2, zip64, num6, comment, container);
            }
            if (num4 != 0u)
            {
                ushort value2 = (ushort)zipSegmentedStream.ComputeSegment(array3.Length);
                int    num8   = 4;
                Array.Copy(BitConverter.GetBytes(value2), 0, array3, num8, 2);
                num8 += 2;
                Array.Copy(BitConverter.GetBytes(value2), 0, array3, num8, 2);
                num8 += 2;
            }
            s.Write(array3, 0, array3.Length);
            if (zipSegmentedStream != null)
            {
                zipSegmentedStream.ContiguousWrite = false;
            }
            return(flag);
        }
Beispiel #15
0
        private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory, long EndOfCentralDirectory, Zip64Option zip64, int entryCount, string comment, ZipContainer container)
        {
            Encoding encoding = GetEncoding(container, comment);
            int      num      = 0;
            int      num2     = 22;

            byte[] array = null;
            short  num3  = 0;

            if (comment != null && comment.Length != 0)
            {
                array = encoding.GetBytes(comment);
                num3  = (short)array.Length;
            }
            num2 += num3;
            byte[] array2 = new byte[num2];
            int    num4   = 0;

            byte[] bytes = BitConverter.GetBytes(101010256u);
            Array.Copy(bytes, 0, array2, num4, 4);
            num4          += 4;
            array2[num4++] = 0;
            array2[num4++] = 0;
            array2[num4++] = 0;
            array2[num4++] = 0;
            if (entryCount >= 65535 || zip64 == Zip64Option.Always)
            {
                for (num = 0; num < 4; num++)
                {
                    array2[num4++] = byte.MaxValue;
                }
            }
            else
            {
                array2[num4++] = (byte)(entryCount & 0xFF);
                array2[num4++] = (byte)((entryCount & 0xFF00) >> 8);
                array2[num4++] = (byte)(entryCount & 0xFF);
                array2[num4++] = (byte)((entryCount & 0xFF00) >> 8);
            }
            long num5 = EndOfCentralDirectory - StartOfCentralDirectory;

            if (num5 >= uint.MaxValue || StartOfCentralDirectory >= uint.MaxValue)
            {
                for (num = 0; num < 8; num++)
                {
                    array2[num4++] = byte.MaxValue;
                }
            }
            else
            {
                array2[num4++] = (byte)(num5 & 0xFF);
                array2[num4++] = (byte)((num5 & 0xFF00) >> 8);
                array2[num4++] = (byte)((num5 & 0xFF0000) >> 16);
                array2[num4++] = (byte)((num5 & 4278190080u) >> 24);
                array2[num4++] = (byte)(StartOfCentralDirectory & 0xFF);
                array2[num4++] = (byte)((StartOfCentralDirectory & 0xFF00) >> 8);
                array2[num4++] = (byte)((StartOfCentralDirectory & 0xFF0000) >> 16);
                array2[num4++] = (byte)((StartOfCentralDirectory & 4278190080u) >> 24);
            }
            if (comment == null || comment.Length == 0)
            {
                array2[num4++] = 0;
                array2[num4++] = 0;
            }
            else
            {
                if (num3 + num4 + 2 > array2.Length)
                {
                    num3 = (short)(array2.Length - num4 - 2);
                }
                array2[num4++] = (byte)(num3 & 0xFF);
                array2[num4++] = (byte)((num3 & 0xFF00) >> 8);
                if (num3 != 0)
                {
                    for (num = 0; num < num3 && num4 + num < array2.Length; num++)
                    {
                        array2[num4 + num] = array[num];
                    }
                    num4 += num;
                }
            }
            return(array2);
        }
        /// <summary>
        /// Pass in either basedir or s, but not both.
        /// In other words, you can extract to a stream or to a directory (filesystem), but not both!
        /// The Password param is required for encrypted entries.
        /// </summary>
        void InternalExtractToBaseDir(string baseDir, string password, ZipContainer zipContainer, ZipEntrySource zipEntrySource, string fileName)
        {
            if (baseDir == null)
                throw new ArgumentNullException("baseDir");

            // workitem 7958
            if (zipContainer == null)
                throw new BadStateException("This entry is an orphan");

            // workitem 10355
            if (zipContainer.ZipFile == null)
                throw new InvalidOperationException("Use Extract() only with ZipFile.");

            zipContainer.ZipFile.Reset(false);

            if (zipEntrySource != ZipEntrySource.ZipFile)
                throw new BadStateException("You must call ZipFile.Save before calling any Extract method");

            OnBeforeExtract(this, baseDir, zipContainer.ZipFile);

            _ioOperationCanceled = false;

            var fileExistsBeforeExtraction = false;
            var checkLaterForResetDirTimes = false;
            string targetFileName = null;
            try
            {
                ValidateCompression(_CompressionMethod_FromZipFile, fileName, GetUnsupportedCompressionMethod(_CompressionMethod));
                ValidateEncryption(Encryption, fileName, _UnsupportedAlgorithmId);

                if (IsDoneWithOutputToBaseDir(baseDir, out targetFileName))
                {
                    WriteStatus("extract dir {0}...", targetFileName);
                    // if true, then the entry was a directory and has been created.
                    // We need to fire the Extract Event.
                    OnAfterExtract(baseDir);
                    return;
                }

                // workitem 10639
                // do we want to extract to a regular filesystem file?
                
                // Check for extracting to a previously existing file. The user
                // can specify bejavior for that case: overwrite, don't
                // overwrite, and throw.  Also, if the file exists prior to
                // extraction, it affects exception handling: whether to delete
                // the target of extraction or not. This check needs to be done
                // before the password check is done, because password check may
                // throw a BadPasswordException, which triggers the catch,
                // wherein the existing file may be deleted if not flagged as
                // pre-existing.
                if (File.Exists(targetFileName))
                {
                    fileExistsBeforeExtraction = true;
                    int rc = CheckExtractExistingFile(baseDir, targetFileName);
                    if (rc == 2) goto ExitTry; // cancel
                    if (rc == 1) return; // do not overwrite
                }

                // If no password explicitly specified, use the password on the entry itself,
                // or on the zipfile itself.
                if (_Encryption_FromZipFile != EncryptionAlgorithm.None)
                    EnsurePassword(password);

                // set up the output stream
                var tmpName = Path.GetRandomFileName();
                var tmpPath = Path.Combine(Path.GetDirectoryName(targetFileName), tmpName);
                WriteStatus("extract file {0}...", targetFileName);

                using (var output = OpenFileStream(tmpPath, ref checkLaterForResetDirTimes))
                {
                    if (ExtractToStream(ArchiveStream, output, Encryption, _Crc32))
                        goto ExitTry;

                    output.Close();
                }

                MoveFileInPlace(fileExistsBeforeExtraction, targetFileName, tmpPath, checkLaterForResetDirTimes);

                OnAfterExtract(baseDir);

                ExitTry: ;
            }
            catch (Exception)
            {
                _ioOperationCanceled = true;
                throw;
            }
            finally
            {
                if (_ioOperationCanceled && targetFileName != null)
                {
                    // An exception has occurred. If the file exists, check
                    // to see if it existed before we tried extracting.  If
                    // it did not, attempt to remove the target file. There
                    // is a small possibility that the existing file has
                    // been extracted successfully, overwriting a previously
                    // existing file, and an exception was thrown after that
                    // but before final completion (setting times, etc). In
                    // that case the file will remain, even though some
                    // error occurred.  Nothing to be done about it.
                    if (File.Exists(targetFileName) && !fileExistsBeforeExtraction)
                        File.Delete(targetFileName);
                }
            }
        }
Beispiel #17
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();
        }
        public static bool WriteCentralDirectoryStructure(Stream s,
                                                          ICollection <ZipEntry> entries,
                                                          uint numSegments,
                                                          Zip64Option zip64,
                                                          String comment,
                                                          ZipContainer container)
        {
            var zss = s as ZipSegmentedStream;

            if (zss != null)
            {
                zss.ContiguousWrite = true;
            }

            // write to a memory stream in order to keep the
            // CDR contiguous
            Int64 aLength = 0;

            using (var ms = new MemoryStream())
            {
                foreach (ZipEntry e in entries)
                {
                    if (e.IncludedInMostRecentSave)
                    {
                        // this writes a ZipDirEntry corresponding to the ZipEntry
                        e.WriteCentralDirectoryEntry(ms);
                    }
                }
                var a = ms.ToArray();
                s.Write(a, 0, a.Length);
                aLength = a.Length;
            }


            // We need to keep track of the start and
            // Finish of the Central Directory Structure.

            // Cannot always use WriteStream.Length or Position; some streams do
            // not support these. (eg, ASP.NET Response.OutputStream) In those
            // cases we have a CountingStream.

            // Also, we cannot just set Start as s.Position bfore the write, and Finish
            // as s.Position after the write.  In a split zip, the write may actually
            // flip to the next segment.  In that case, Start will be zero.  But we
            // don't know that til after we know the size of the thing to write.  So the
            // answer is to compute the directory, then ask the ZipSegmentedStream which
            // segment that directory would fall in, it it were written.  Then, include
            // that data into the directory, and finally, write the directory to the
            // output stream.

            var  output = s as CountingStream;
            long Finish = (output != null) ? output.ComputedPosition : s.Position;  // BytesWritten
            long Start  = Finish - aLength;

            // need to know which segment the EOCD record starts in
            UInt32 startSegment = (zss != null)
                ? zss.CurrentSegment
                : 0;

            Int64 SizeOfCentralDirectory = Finish - Start;

            int countOfEntries = CountEntries(entries);

            bool needZip64CentralDirectory =
                zip64 == Zip64Option.Always ||
                countOfEntries >= 0xFFFF ||
                SizeOfCentralDirectory > 0xFFFFFFFF ||
                Start > 0xFFFFFFFF;

            byte[] a2 = null;

            // emit ZIP64 extensions as required
            if (needZip64CentralDirectory)
            {
                if (zip64 == Zip64Option.Never)
                {
#if NETCF
                    throw new ZipException("The archive requires a ZIP64 Central Directory. Consider enabling ZIP64 extensions.");
#else
                    System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame(1);
                    if (sf.GetMethod().DeclaringType == typeof(ZipFile))
                    {
                        throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipFile.UseZip64WhenSaving property.");
                    }
                    else
                    {
                        throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipOutputStream.EnableZip64 property.");
                    }
#endif
                }

                var a = GenZip64EndOfCentralDirectory(Start, Finish, countOfEntries, numSegments);
                a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container);
                if (startSegment != 0)
                {
                    UInt32 thisSegment = zss.ComputeSegment(a.Length + a2.Length);
                    int    i           = 16;
                    // number of this disk
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);
                    i += 4;
                    // number of the disk with the start of the central directory
                    //Array.Copy(BitConverter.GetBytes(startSegment), 0, a, i, 4);
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);

                    i = 60;
                    // offset 60
                    // number of the disk with the start of the zip64 eocd
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);
                    i += 4;
                    i += 8;

                    // offset 72
                    // total number of disks
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);
                }
                s.Write(a, 0, a.Length);
            }
            else
            {
                a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container);
            }


            // now, the regular footer
            if (startSegment != 0)
            {
                // The assumption is the central directory is never split across
                // segment boundaries.

                UInt16 thisSegment = (UInt16)zss.ComputeSegment(a2.Length);
                int    i           = 4;
                // number of this disk
                Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2);
                i += 2;
                // number of the disk with the start of the central directory
                //Array.Copy(BitConverter.GetBytes((UInt16)startSegment), 0, a2, i, 2);
                Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2);
                i += 2;
            }

            s.Write(a2, 0, a2.Length);

            // reset the contiguous write property if necessary
            if (zss != null)
            {
                zss.ContiguousWrite = false;
            }

            return(needZip64CentralDirectory);
        }
        public static bool WriteCentralDirectoryStructure(Stream s,
                                                          ICollection<ZipEntry> entries,
                                                          uint numSegments,
                                                          Zip64Option zip64,
                                                          String comment,
                                                          ZipContainer container)
        {
            var zss = s as ZipSegmentedStream;
            if (zss != null)
                zss.ContiguousWrite = true;

            // write to a memory stream in order to keep the
            // CDR contiguous
            Int64 aLength = 0;
            using (var ms = new MemoryStream())
            {
                foreach (ZipEntry e in entries)
                {
                    if (e.IncludedInMostRecentSave)
                    {
                        // this writes a ZipDirEntry corresponding to the ZipEntry
                        e.WriteCentralDirectoryEntry(ms);
                    }
                }
                var a = ms.ToArray();
                s.Write(a, 0, a.Length);
                aLength = a.Length;
            }


            // We need to keep track of the start and
            // Finish of the Central Directory Structure.

            // Cannot always use WriteStream.Length or Position; some streams do
            // not support these. (eg, ASP.NET Response.OutputStream) In those
            // cases we have a CountingStream.

            // Also, we cannot just set Start as s.Position bfore the write, and Finish
            // as s.Position after the write.  In a split zip, the write may actually
            // flip to the next segment.  In that case, Start will be zero.  But we
            // don't know that til after we know the size of the thing to write.  So the
            // answer is to compute the directory, then ask the ZipSegmentedStream which
            // segment that directory would fall in, it it were written.  Then, include
            // that data into the directory, and finally, write the directory to the
            // output stream.

            var output = s as CountingStream;
            long Finish = (output != null) ? output.ComputedPosition : s.Position;  // BytesWritten
            long Start = Finish - aLength;

            // need to know which segment the EOCD record starts in
            UInt32 startSegment = (zss != null)
                ? zss.CurrentSegment
                : 0;

            Int64 SizeOfCentralDirectory = Finish - Start;

            int countOfEntries = CountEntries(entries);

            bool needZip64CentralDirectory =
                zip64 == Zip64Option.Always ||
                countOfEntries >= 0xFFFF ||
                SizeOfCentralDirectory > 0xFFFFFFFF ||
                Start > 0xFFFFFFFF;

            byte[] a2 = null;

            // emit ZIP64 extensions as required
            if (needZip64CentralDirectory)
            {
                if (zip64 == Zip64Option.Never)
                {
#if NETCF
                    throw new ZipException("The archive requires a ZIP64 Central Directory. Consider enabling ZIP64 extensions.");
#else
                    System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame(1);
                    if (sf.GetMethod().DeclaringType == typeof(ZipFile))
                        throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipFile.UseZip64WhenSaving property.");
                    else
                        throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipOutputStream.EnableZip64 property.");
#endif

                }

                var a = GenZip64EndOfCentralDirectory(Start, Finish, countOfEntries, numSegments);
                a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container);
                if (startSegment != 0)
                {
                    UInt32 thisSegment = zss.ComputeSegment(a.Length + a2.Length);
                    int i = 16;
                    // number of this disk
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);
                    i += 4;
                    // number of the disk with the start of the central directory
                    //Array.Copy(BitConverter.GetBytes(startSegment), 0, a, i, 4);
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);

                    i = 60;
                    // offset 60
                    // number of the disk with the start of the zip64 eocd
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);
                    i += 4;
                    i += 8;

                    // offset 72
                    // total number of disks
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);
                }
                s.Write(a, 0, a.Length);
            }
            else
                a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container);


            // now, the regular footer
            if (startSegment != 0)
            {
                // The assumption is the central directory is never split across
                // segment boundaries.

                UInt16 thisSegment = (UInt16) zss.ComputeSegment(a2.Length);
                int i = 4;
                // number of this disk
                Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2);
                i += 2;
                // number of the disk with the start of the central directory
                //Array.Copy(BitConverter.GetBytes((UInt16)startSegment), 0, a2, i, 2);
                Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2);
                i += 2;
            }

            s.Write(a2, 0, a2.Length);

            // reset the contiguous write property if necessary
            if (zss != null)
                zss.ContiguousWrite = false;

            return needZip64CentralDirectory;
        }
        private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory,
                                                        long EndOfCentralDirectory,
                                                        Zip64Option zip64,
                                                        int entryCount,
                                                        string comment,
                                                        ZipContainer container)
        {
            System.Text.Encoding encoding = GetEncoding(container, comment);
            int j            = 0;
            int bufferLength = 22;

            byte[] block         = null;
            Int16  commentLength = 0;

            if ((comment != null) && (comment.Length != 0))
            {
                block         = encoding.GetBytes(comment);
                commentLength = (Int16)block.Length;
            }
            bufferLength += commentLength;
            byte[] bytes = new byte[bufferLength];

            int i = 0;

            // signature
            byte[] sig = BitConverter.GetBytes(ZipConstants.EndOfCentralDirectorySignature);
            Array.Copy(sig, 0, bytes, i, 4);
            i += 4;

            // number of this disk
            // (this number may change later)
            bytes[i++] = 0;
            bytes[i++] = 0;

            // number of the disk with the start of the central directory
            // (this number may change later)
            bytes[i++] = 0;
            bytes[i++] = 0;

            // handle ZIP64 extensions for the end-of-central-directory
            if (entryCount >= 0xFFFF || zip64 == Zip64Option.Always)
            {
                // the ZIP64 version.
                for (j = 0; j < 4; j++)
                {
                    bytes[i++] = 0xFF;
                }
            }
            else
            {
                // the standard version.
                // total number of entries in the central dir on this disk
                bytes[i++] = (byte)(entryCount & 0x00FF);
                bytes[i++] = (byte)((entryCount & 0xFF00) >> 8);

                // total number of entries in the central directory
                bytes[i++] = (byte)(entryCount & 0x00FF);
                bytes[i++] = (byte)((entryCount & 0xFF00) >> 8);
            }

            // size of the central directory
            Int64 SizeOfCentralDirectory = EndOfCentralDirectory - StartOfCentralDirectory;

            if (SizeOfCentralDirectory >= 0xFFFFFFFF || StartOfCentralDirectory >= 0xFFFFFFFF)
            {
                // The actual data is in the ZIP64 central directory structure
                for (j = 0; j < 8; j++)
                {
                    bytes[i++] = 0xFF;
                }
            }
            else
            {
                // size of the central directory (we just get the low 4 bytes)
                bytes[i++] = (byte)(SizeOfCentralDirectory & 0x000000FF);
                bytes[i++] = (byte)((SizeOfCentralDirectory & 0x0000FF00) >> 8);
                bytes[i++] = (byte)((SizeOfCentralDirectory & 0x00FF0000) >> 16);
                bytes[i++] = (byte)((SizeOfCentralDirectory & 0xFF000000) >> 24);

                // offset of the start of the central directory (we just get the low 4 bytes)
                bytes[i++] = (byte)(StartOfCentralDirectory & 0x000000FF);
                bytes[i++] = (byte)((StartOfCentralDirectory & 0x0000FF00) >> 8);
                bytes[i++] = (byte)((StartOfCentralDirectory & 0x00FF0000) >> 16);
                bytes[i++] = (byte)((StartOfCentralDirectory & 0xFF000000) >> 24);
            }


            // zip archive comment
            if ((comment == null) || (comment.Length == 0))
            {
                // no comment!
                bytes[i++] = (byte)0;
                bytes[i++] = (byte)0;
            }
            else
            {
                // the size of our buffer defines the max length of the comment we can write
                if (commentLength + i + 2 > bytes.Length)
                {
                    commentLength = (Int16)(bytes.Length - i - 2);
                }
                bytes[i++] = (byte)(commentLength & 0x00FF);
                bytes[i++] = (byte)((commentLength & 0xFF00) >> 8);

                if (commentLength != 0)
                {
                    // now actually write the comment itself into the byte buffer
                    for (j = 0; (j < commentLength) && (i + j < bytes.Length); j++)
                    {
                        bytes[i + j] = block[j];
                    }
                    i += j;
                }
            }

            //   s.Write(bytes, 0, i);
            return(bytes);
        }
        private static System.Text.Encoding GetEncoding(ZipContainer container, string t)
        {
            switch (container.AlternateEncodingUsage)
            {
                case ZipOption.Always:
                    return container.AlternateEncoding;
                case ZipOption.Never:
                    return container.DefaultEncoding;
            }

            // AsNecessary is in force
            var e = container.DefaultEncoding;
            if (t == null) return e;

            var bytes = e.GetBytes(t);
            var t2 = e.GetString(bytes,0,bytes.Length);
            if (t2.Equals(t)) return e;
            return container.AlternateEncoding;
        }
 private void _Init(Stream stream, bool leaveOpen, string name)
 {
     _inputStream = stream;
     if (!_inputStream.CanRead)
         throw new ZipException("The stream must be readable.");
     _container= new ZipContainer(this);
     _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437");
     _leaveUnderlyingStreamOpen = leaveOpen;
     _findRequired= true;
     _name = name ?? "(stream)";
 }
        private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory,
                                                        long EndOfCentralDirectory,
                                                        Zip64Option zip64,
                                                        int entryCount,
                                                        string comment,
                                                        ZipContainer container)
        {
            System.Text.Encoding encoding = GetEncoding(container, comment);
            int j = 0;
            int bufferLength = 22;
            byte[] block = null;
            Int16 commentLength = 0;
            if ((comment != null) && (comment.Length != 0))
            {
                block = encoding.GetBytes(comment);
                commentLength = (Int16)block.Length;
            }
            bufferLength += commentLength;
            byte[] bytes = new byte[bufferLength];

            int i = 0;
            // signature
            byte[] sig = BitConverter.GetBytes(ZipConstants.EndOfCentralDirectorySignature);
            Array.Copy(sig, 0, bytes, i, 4);
            i+=4;

            // number of this disk
            // (this number may change later)
            bytes[i++] = 0;
            bytes[i++] = 0;

            // number of the disk with the start of the central directory
            // (this number may change later)
            bytes[i++] = 0;
            bytes[i++] = 0;

            // handle ZIP64 extensions for the end-of-central-directory
            if (entryCount >= 0xFFFF || zip64 == Zip64Option.Always)
            {
                // the ZIP64 version.
                for (j = 0; j < 4; j++)
                    bytes[i++] = 0xFF;
            }
            else
            {
                // the standard version.
                // total number of entries in the central dir on this disk
                bytes[i++] = (byte)(entryCount & 0x00FF);
                bytes[i++] = (byte)((entryCount & 0xFF00) >> 8);

                // total number of entries in the central directory
                bytes[i++] = (byte)(entryCount & 0x00FF);
                bytes[i++] = (byte)((entryCount & 0xFF00) >> 8);
            }

            // size of the central directory
            Int64 SizeOfCentralDirectory = EndOfCentralDirectory - StartOfCentralDirectory;

            if (SizeOfCentralDirectory >= 0xFFFFFFFF || StartOfCentralDirectory >= 0xFFFFFFFF)
            {
                // The actual data is in the ZIP64 central directory structure
                for (j = 0; j < 8; j++)
                    bytes[i++] = 0xFF;
            }
            else
            {
                // size of the central directory (we just get the low 4 bytes)
                bytes[i++] = (byte)(SizeOfCentralDirectory & 0x000000FF);
                bytes[i++] = (byte)((SizeOfCentralDirectory & 0x0000FF00) >> 8);
                bytes[i++] = (byte)((SizeOfCentralDirectory & 0x00FF0000) >> 16);
                bytes[i++] = (byte)((SizeOfCentralDirectory & 0xFF000000) >> 24);

                // offset of the start of the central directory (we just get the low 4 bytes)
                bytes[i++] = (byte)(StartOfCentralDirectory & 0x000000FF);
                bytes[i++] = (byte)((StartOfCentralDirectory & 0x0000FF00) >> 8);
                bytes[i++] = (byte)((StartOfCentralDirectory & 0x00FF0000) >> 16);
                bytes[i++] = (byte)((StartOfCentralDirectory & 0xFF000000) >> 24);
            }


            // zip archive comment
            if ((comment == null) || (comment.Length == 0))
            {
                // no comment!
                bytes[i++] = (byte)0;
                bytes[i++] = (byte)0;
            }
            else
            {
                // the size of our buffer defines the max length of the comment we can write
                if (commentLength + i + 2 > bytes.Length) commentLength = (Int16)(bytes.Length - i - 2);
                bytes[i++] = (byte)(commentLength & 0x00FF);
                bytes[i++] = (byte)((commentLength & 0xFF00) >> 8);

                if (commentLength != 0)
                {
                    // now actually write the comment itself into the byte buffer
                    for (j = 0; (j < commentLength) && (i + j < bytes.Length); j++)
                    {
                        bytes[i + j] = block[j];
                    }
                    i += j;
                }
            }

            //   s.Write(bytes, 0, i);
            return bytes;
        }
        /// <summary>
        /// Extract to a stream
        /// In other words, you can extract to a stream or to a directory (filesystem), but not both!
        /// The Password param is required for encrypted entries.
        /// </summary>
        void InternalExtractToStream(Stream outStream, string password, ZipContainer zipContainer, ZipEntrySource zipEntrySource, string fileName)
        {
            // workitem 7958
            if (zipContainer == null)
                throw new BadStateException("This entry is an orphan");

            // workitem 10355
            if (zipContainer.ZipFile == null)
                throw new InvalidOperationException("Use Extract() only with ZipFile.");

            zipContainer.ZipFile.Reset(false);

            if (zipEntrySource != ZipEntrySource.ZipFile)
                throw new BadStateException("You must call ZipFile.Save before calling any Extract method");

            OnBeforeExtract(this, null, zipContainer.ZipFile);

            _ioOperationCanceled = false;

            try
            {
                ValidateCompression(_CompressionMethod_FromZipFile, fileName, GetUnsupportedCompressionMethod(_CompressionMethod));
                ValidateEncryption(Encryption, fileName, _UnsupportedAlgorithmId);

                if (IsDoneWithOutputToStream())
                {
                    WriteStatus("extract dir {0}...", null);
                    // if true, then the entry was a directory and has been created.
                    // We need to fire the Extract Event.
                    OnAfterExtract(null);
                    return;
                }

                // If no password explicitly specified, use the password on the entry itself,
                // or on the zipfile itself.
                if (_Encryption_FromZipFile != EncryptionAlgorithm.None)
                    EnsurePassword(password);

                WriteStatus("extract entry {0} to stream...", fileName);

                var archiveStream = ArchiveStream;

                if (ExtractToStream(archiveStream, outStream, Encryption, _Crc32))
                    goto ExitTry;

                OnAfterExtract(null);

                ExitTry: ;
            }
            catch (Exception)
            {
                _ioOperationCanceled = true;
                throw;
            }
        }
        public static bool WriteCentralDirectoryStructure(Stream s,
                                                          ICollection <ZipEntry> entries,
                                                          uint numSegments,
                                                          Zip64Option zip64,
                                                          String comment,
                                                          ZipContainer container)
        {
            var zss = s as ZipSegmentedStream;

            if (zss != null)
            {
                zss.ContiguousWrite = true;
            }

            // write to a memory stream in order to keep the
            // CDR contiguous
            Int64 aLength = 0;

            using (var ms = new MemoryStream())
            {
                foreach (ZipEntry e in entries)
                {
                    if (e.IncludedInMostRecentSave)
                    {
                        // this writes a ZipDirEntry corresponding to the ZipEntry
                        e.WriteCentralDirectoryEntry(ms);
                    }
                }
                var a = ms.ToArray();
                s.Write(a, 0, a.Length);
                aLength = a.Length;
            }


            var  output = s as CountingStream;
            long Finish = (output != null) ? output.ComputedPosition : s.Position;  // BytesWritten
            long Start  = Finish - aLength;

            // need to know which segment the EOCD record starts in
            UInt32 startSegment = (zss != null)
                ? zss.CurrentSegment
                : 0;

            Int64 SizeOfCentralDirectory = Finish - Start;

            int countOfEntries = CountEntries(entries);

            bool needZip64CentralDirectory =
                zip64 == Zip64Option.Always ||
                countOfEntries >= 0xFFFF ||
                SizeOfCentralDirectory > 0xFFFFFFFF ||
                Start > 0xFFFFFFFF;

            byte[] a2 = null;

            // emit ZIP64 extensions as required
            if (needZip64CentralDirectory)
            {
                if (zip64 == Zip64Option.Never)
                {
                    System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame(1);
                    if (sf.GetMethod().DeclaringType == typeof(ZipFile))
                    {
                        throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipFile.UseZip64WhenSaving property.");
                    }
                    else
                    {
                        throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipOutputStream.EnableZip64 property.");
                    }
                }

                var a = GenZip64EndOfCentralDirectory(Start, Finish, countOfEntries, numSegments);
                a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container);
                if (startSegment != 0)
                {
                    UInt32 thisSegment = zss.ComputeSegment(a.Length + a2.Length);
                    int    i           = 16;
                    // number of this disk
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);
                    i += 4;
                    // number of the disk with the start of the central directory
                    //Array.Copy(BitConverter.GetBytes(startSegment), 0, a, i, 4);
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);

                    i = 60;
                    // offset 60
                    // number of the disk with the start of the zip64 eocd
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);
                    i += 4;
                    i += 8;

                    // offset 72
                    // total number of disks
                    Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4);
                }
                s.Write(a, 0, a.Length);
            }
            else
            {
                a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container);
            }


            // now, the regular footer
            if (startSegment != 0)
            {
                // The assumption is the central directory is never split across
                // segment boundaries.

                UInt16 thisSegment = (UInt16)zss.ComputeSegment(a2.Length);
                int    i           = 4;
                // number of this disk
                Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2);
                i += 2;
                // number of the disk with the start of the central directory
                //Array.Copy(BitConverter.GetBytes((UInt16)startSegment), 0, a2, i, 2);
                Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2);
                i += 2;
            }

            s.Write(a2, 0, a2.Length);

            // reset the contiguous write property if necessary
            if (zss != null)
            {
                zss.ContiguousWrite = false;
            }

            return(needZip64CentralDirectory);
        }