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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        /// <summary>
        ///   Reads one <c>ZipEntry</c> from the given stream.  The content for
        ///   the entry does not get decompressed or decrypted.  This method
        ///   basically reads metadata, and seeks.
        /// </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.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);
            // workitem 10178
            Pathfinding.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)
 {
     this._inputStream = stream;
     if (!this._inputStream.CanRead)
     {
         throw new ZipException("The stream must be readable.");
     }
     this._container = new ZipContainer(this);
     this._provisionalAlternateEncoding = Encoding.UTF8;
     this._leaveUnderlyingStreamOpen    = leaveOpen;
     this._findRequired = true;
     this._name         = (name ?? "(stream)");
 }
        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 SILVERLIGHT
            _provisionalAlternateEncoding = System.Text.Encoding.UTF8;
#else
            _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437");
#endif
            _leaveUnderlyingStreamOpen = leaveOpen;
            _findRequired = true;
            _name         = name ?? "(stream)";
        }
Exemple #6
0
        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++] = 255;
                }
            }
            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++] = 255;
                }
            }
            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);
        }
Exemple #7
0
        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 current in entries)
                {
                    if (current.IncludedInMostRecentSave)
                    {
                        current.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) ? s.Position : countingStream.ComputedPosition;
            long           num3           = num2 - num;
            uint           num4           = (zipSegmentedStream == null) ? 0u : zipSegmentedStream.CurrentSegment;
            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);
        }
        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);
        }
        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);
        }
Exemple #10
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();
        }