Example #1
0
 // Token: 0x0600065D RID: 1629 RVA: 0x0003A4E8 File Offset: 0x000386E8
 protected override void Dispose(bool disposing)
 {
     if (this._disposed)
     {
         return;
     }
     if (disposing && !this._exceptionPending)
     {
         this._FinishCurrentEntry();
         this._directoryNeededZip64 = ZipOutput.WriteCentralDirectoryStructure(this._outputStream, this._entriesWritten.Values, 1U, this._zip64, this.Comment, new ZipContainer(this));
         CountingStream countingStream = this._outputStream as CountingStream;
         Stream         stream;
         if (countingStream != null)
         {
             stream = countingStream.WrappedStream;
             countingStream.Dispose();
         }
         else
         {
             stream = this._outputStream;
         }
         if (!this._leaveUnderlyingStreamOpen)
         {
             stream.Dispose();
         }
         this._outputStream = null;
     }
     this._disposed = true;
 }
        protected override void Dispose(bool disposing)
        {
            if (_disposed)
            {
                return;
            }

            if (disposing) // not called from finalizer
            {
                // handle pending exceptions
                if (!_exceptionPending)
                {
                    _FinishCurrentEntry();
                    _directoryNeededZip64 = ZipOutput.WriteCentralDirectoryStructure(_outputStream,
                                                                                     _entriesWritten.Values,
                                                                                     1, // _numberOfSegmentsForMostRecentSave,
                                                                                     _zip64,
                                                                                     Comment,
                                                                                     new ZipContainer(this));
                    Stream         wrappedStream = null;
                    CountingStream cs            = _outputStream as CountingStream;
                    if (cs != null)
                    {
                        wrappedStream = cs.WrappedStream;
                        cs.Dispose();
                    }
                    else
                    {
                        wrappedStream = _outputStream;
                    }

                    if (!_leaveUnderlyingStreamOpen)
                    {
                        wrappedStream.Dispose();
                    }
                    _outputStream = null;
                }
            }
            _disposed = true;
        }
        /// <summary>
        ///   Saves the Zip archive to a file, specified by the Name property of the
        ///   <c>ZipFile</c>.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   The <c>ZipFile</c> instance is written to storage, typically a zip file
        ///   in a filesystem, only when the caller calls <c>Save</c>.  In the typical
        ///   case, the Save operation writes the zip content to a temporary file, and
        ///   then renames the temporary file to the desired name. If necessary, this
        ///   method will delete a pre-existing file before the rename.
        /// </para>
        ///
        /// <para>
        ///   The <see cref="ZipFile.Name"/> property is specified either explicitly,
        ///   or implicitly using one of the parameterized ZipFile constructors.  For
        ///   COM Automation clients, the <c>Name</c> property must be set explicitly,
        ///   because COM Automation clients cannot call parameterized constructors.
        /// </para>
        ///
        /// <para>
        ///   When using a filesystem file for the Zip output, it is possible to call
        ///   <c>Save</c> multiple times on the <c>ZipFile</c> instance. With each
        ///   call the zip content is re-written to the same output file.
        /// </para>
        ///
        /// <para>
        ///   Data for entries that have been added to the <c>ZipFile</c> instance is
        ///   written to the output when the <c>Save</c> method is called. This means
        ///   that the input streams for those entries must be available at the time
        ///   the application calls <c>Save</c>.  If, for example, the application
        ///   adds entries with <c>AddEntry</c> using a dynamically-allocated
        ///   <c>MemoryStream</c>, the memory stream must not have been disposed
        ///   before the call to <c>Save</c>. See the <see
        ///   cref="ZipEntry.InputStream"/> property for more discussion of the
        ///   availability requirements of the input stream for an entry, and an
        ///   approach for providing just-in-time stream lifecycle management.
        /// </para>
        ///
        /// </remarks>
        ///
        /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(String, System.IO.Stream)"/>
        ///
        /// <exception cref="Ionic.Zip.BadStateException">
        ///   Thrown if you haven't specified a location or stream for saving the zip,
        ///   either in the constructor or by setting the Name property, or if you try
        ///   to save a regular zip archive to a filename with a .exe extension.
        /// </exception>
        ///
        /// <exception cref="System.OverflowException">
        ///   Thrown if <see cref="MaxOutputSegmentSize"/> is non-zero, and the number
        ///   of segments that would be generated for the spanned zip file during the
        ///   save operation exceeds 99.  If this happens, you need to increase the
        ///   segment size.
        /// </exception>
        ///
        public void Save()
        {
            try
            {
                bool thisSaveUsedZip64 = false;
                _saveOperationCanceled             = false;
                _numberOfSegmentsForMostRecentSave = 0;
                OnSaveStarted();

                if (WriteStream == null)
                {
                    throw new BadStateException("You haven't specified where to save the zip.");
                }

                if (_name != null && _name.EndsWith(".exe") && !_SavingSfx)
                {
                    throw new BadStateException("You specified an EXE for a plain zip file.");
                }

                // check if modified, before saving.
                if (!_contentsChanged)
                {
                    OnSaveCompleted();
                    if (Verbose)
                    {
                        StatusMessageTextWriter.WriteLine("No save is necessary....");
                    }
                    return;
                }

                Reset(true);

                if (Verbose)
                {
                    StatusMessageTextWriter.WriteLine("saving....");
                }

                // validate the number of entries
                if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never)
                {
                    throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance.");
                }


                // write an entry in the zip for each file
                int n = 0;
                // workitem 9831
                ICollection <ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries;
                foreach (ZipEntry e in c) // _entries.Values
                {
                    OnSaveEntry(n, e, true);
                    e.Write(WriteStream);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    n++;
                    OnSaveEntry(n, e, false);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    // Some entries can be skipped during the save.
                    if (e.IncludedInMostRecentSave)
                    {
                        thisSaveUsedZip64 |= e.OutputUsedZip64.Value;
                    }
                }



                if (_saveOperationCanceled)
                {
                    return;
                }

                var zss = WriteStream as ZipSegmentedStream;

                _numberOfSegmentsForMostRecentSave = (zss != null)
                    ? zss.CurrentSegment
                    : 1;

                bool directoryNeededZip64 =
                    ZipOutput.WriteCentralDirectoryStructure
                        (WriteStream,
                        c,
                        _numberOfSegmentsForMostRecentSave,
                        _zip64,
                        Comment,
                        new ZipContainer(this));

                OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive);

                _hasBeenSaved    = true;
                _contentsChanged = false;

                thisSaveUsedZip64 |= directoryNeededZip64;
                _OutputUsesZip64   = new Nullable <bool>(thisSaveUsedZip64);

                if (_fileAlreadyExists && this._readstream != null)
                {
                    // This means we opened and read a zip file.
                    // If we are now saving, we need to close the orig file, first.
                    this._readstream.Close();
                    this._readstream = null;
                }
                // the archiveStream for each entry needs to be null
                foreach (var e in c)
                {
                    var zss1 = e._archiveStream as ZipSegmentedStream;
                    if (zss1 != null)
#if NETCF
                    { zss1.Close(); }
#else
                    { zss1.Dispose(); }
#endif
                    e._archiveStream = null;
                }

                // do the rename as necessary
                if (_name != null &&
                    (_temporaryFileName != null || zss != null))
                {
                    // _temporaryFileName may remain null if we are writing to a stream.
                    // only close the stream if there is a file behind it.
#if NETCF
                    WriteStream.Close();
#else
                    WriteStream.Dispose();
#endif

                    if (_saveOperationCanceled)
                    {
                        return;
                    }

                    string tmpName = null;
                    if (File.Exists(_name))
                    {
                        // the steps:
                        //
                        // 1. Delete tmpName
                        // 2. move existing zip to tmpName
                        // 3. rename (File.Move) working file to name of existing zip
                        // 4. delete tmpName
                        //
                        // This series of steps avoids the exception,
                        // System.IO.IOException:
                        //   "Cannot create a file when that file already exists."
                        //
                        // Cannot just call File.Replace() here because
                        // there is a possibility that the TEMP volume is different
                        // that the volume for the final file (c:\ vs d:\).
                        // So we need to do a Delete+Move pair.
                        //
                        // But, when doing the delete, Windows allows a process to
                        // delete the file, even though it is held open by, say, a
                        // virus scanner. It gets internally marked as "delete
                        // pending". The file does not actually get removed from the
                        // file system, it is still there after the File.Delete
                        // call.
                        //
                        // Therefore, we need to move the existing zip, which may be
                        // held open, to some other name. Then rename our working
                        // file to the desired name, then delete (possibly delete
                        // pending) the "other name".
                        //
                        // Ideally this would be transactional. It's possible that the
                        // delete succeeds and the move fails. Lacking transactions, if
                        // this kind of failure happens, we're hosed, and this logic will
                        // throw on the next File.Move().
                        //
                        //File.Delete(_name);
                        // workitem 10447
#if NETCF || SILVERLIGHT
                        tmpName = _name + "." + SharedUtilities.GenerateRandomStringImpl(8, 0) + ".tmp";
#else
                        tmpName = _name + "." + Path.GetRandomFileName();
#endif
                        if (File.Exists(tmpName))
                        {
                            DeleteFileWithRetry(tmpName);
                        }
                        File.Move(_name, tmpName);
                    }

                    OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive);
                    File.Move((zss != null) ? zss.CurrentTempName : _temporaryFileName,
                              _name);

                    OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive);

                    if (tmpName != null)
                    {
                        try
                        {
                            // not critical
                            if (File.Exists(tmpName))
                            {
                                File.Delete(tmpName);
                            }
                        }
                        catch
                        {
                            // don't care about exceptions here.
                        }
                    }
                    _fileAlreadyExists = true;
                }
                _readName = _name;

                NotifyEntriesSaveComplete(c);
                OnSaveCompleted();
                _JustSaved = true;
            }

            // workitem 5043
            finally
            {
                CleanupAfterSaveOperation();
            }

            return;
        }
Example #4
0
        /// <summary>
        /// Saves the Zip archive to a file, specified by the Name property of the <c>ZipFile</c>.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        /// The <c>ZipFile</c> instance is written to storage, typically a zip file in a
        /// filesystem, only when the caller calls <c>Save</c>.  The Save operation writes
        /// the zip content to a temporary file, and then renames the temporary file
        /// to the desired name. If necessary, this method will delete a pre-existing file
        /// before the rename.
        /// </para>
        ///
        /// <para> The <see cref="ZipFile.Name"/> property is specified either
        /// explicitly, or implicitly using one of the parameterized ZipFile
        /// constructors.  For COM Automation clients, the <c>Name</c> property must be
        /// set explicitly, because COM Automation clients cannot call parameterized
        /// constructors.  </para>
        ///
        /// <para>
        /// When using a filesystem file for the Zip output, it is possible to call
        /// <c>Save</c> multiple times on the <c>ZipFile</c> instance. With each call the zip
        /// content is re-written to the same output file.
        /// </para>
        ///
        /// <para>
        /// Data for entries that have been added to the <c>ZipFile</c> instance is written
        /// to the output when the <c>Save</c> method is called. This means that the input
        /// streams for those entries must be available at the time the application calls
        /// <c>Save</c>.  If, for example, the application adds entries with <c>AddEntry</c>
        /// using a dynamically-allocated <c>MemoryStream</c>, the memory stream must not
        /// have been disposed before the call to <c>Save</c>. See the <see
        /// cref="ZipEntry.InputStream"/> property for more discussion of the availability
        /// requirements of the input stream for an entry, and an approach for providing
        /// just-in-time stream lifecycle management.
        /// </para>
        ///
        /// </remarks>
        ///
        /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(String, System.IO.Stream)"/>
        ///
        /// <exception cref="Ionic.Zip.BadStateException">
        /// Thrown if you haven't specified a location or stream for saving the zip,
        /// either in the constructor or by setting the Name property, or if you try to
        /// save a regular zip archive to a filename with a .exe extension.
        /// </exception>
        ///
        public void Save()
        {
            try
            {
                bool thisSaveUsedZip64 = false;
                _saveOperationCanceled             = false;
                _numberOfSegmentsForMostRecentSave = 0;
                OnSaveStarted();

                if (WriteStream == null)
                {
                    throw new BadStateException("You haven't specified where to save the zip.");
                }

                if (_name != null && _name.EndsWith(".exe") && !_SavingSfx)
                {
                    throw new BadStateException("You specified an EXE for a plain zip file.");
                }

                // check if modified, before saving.
                if (!_contentsChanged)
                {
                    OnSaveCompleted();
                    if (Verbose)
                    {
                        StatusMessageTextWriter.WriteLine("No save is necessary....");
                    }
                    return;
                }

                Reset();

                if (Verbose)
                {
                    StatusMessageTextWriter.WriteLine("saving....");
                }

                // validate the number of entries
                if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never)
                {
                    throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance.");
                }


                // write an entry in the zip for each file
                int n = 0;
                // workitem 9831
                ICollection <ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries;
                foreach (ZipEntry e in c)     // _entries.Values
                {
                    OnSaveEntry(n, e, true);
                    e.Write(WriteStream);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    n++;
                    OnSaveEntry(n, e, false);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    // Some entries can be skipped during the save.
                    if (e.IncludedInMostRecentSave)
                    {
                        thisSaveUsedZip64 |= e.OutputUsedZip64.Value;
                    }
                }



                if (_saveOperationCanceled)
                {
                    return;
                }

                var zss = WriteStream as ZipSegmentedStream;

                _numberOfSegmentsForMostRecentSave = (zss != null)
                    ? zss.CurrentSegment
                    : 1;

                bool directoryNeededZip64 = ZipOutput.WriteCentralDirectoryStructure(WriteStream,
                                                                                     c,
                                                                                     _numberOfSegmentsForMostRecentSave,
                                                                                     _zip64,
                                                                                     Comment,
                                                                                     ProvisionalAlternateEncoding);

                OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive);

                _hasBeenSaved    = true;
                _contentsChanged = false;

                thisSaveUsedZip64 |= directoryNeededZip64;
                _OutputUsesZip64   = new Nullable <bool>(thisSaveUsedZip64);


                // do the rename as necessary
                if (_name != null &&
                    (_temporaryFileName != null || zss != null))
                {
                    // _temporaryFileName may remain null if we are writing to a stream.
                    // only close the stream if there is a file behind it.
                    WriteStream.Close();
#if !NETCF
                    WriteStream.Dispose();
#endif
                    if (_saveOperationCanceled)
                    {
                        return;
                    }

                    if ((_fileAlreadyExists) && (this._readstream != null))
                    {
                        // This means we opened and read a zip file.
                        // If we are now saving to the same file, we need to close the
                        // orig file, first.
                        this._readstream.Close();
                        this._readstream = null;
                        // the archiveStream for each entry needs to be null
                        foreach (var e in c)
                        {
                            e._archiveStream = null;
                        }
                    }

                    if (_fileAlreadyExists)
                    {
                        // We do not just call File.Replace() here because
                        // there is a possibility that the TEMP volume is different
                        // that the volume for the final file (c:\ vs d:\).
                        // So we need to do a Delete+Move pair.
                        //
                        // Ideally this would be transactional.
                        //
                        // It's possible that the delete succeeds and the move fails.
                        // in that case, we're hosed, and we'll throw.
                        //
                        // Could make this more complicated by moving (renaming) the first file, then
                        // moving the second, then deleting the first file. But the
                        // error handling and unwrap logic just gets more complicated.
                        //
                        // Better to just keep it simple.
                        File.Delete(_name);
                    }

                    OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive);
                    File.Move((zss != null) ? zss.CurrentName : _temporaryFileName, _name);
                    OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive);

                    _fileAlreadyExists = true;
                }

                NotifyEntriesSaveComplete(c);
                OnSaveCompleted();
                _JustSaved = true;
            }

            // workitem 5043
            finally
            {
                CleanupAfterSaveOperation();
            }

            return;
        }
Example #5
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);
        }
Example #6
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);
        }
        public void Save()
        {
            try
            {
                bool thisSaveUsedZip64 = false;
                _saveOperationCanceled             = false;
                _numberOfSegmentsForMostRecentSave = 0;
                OnSaveStarted();

                if (WriteStream == null)
                {
                    throw new BadStateException("You haven't specified where to save the zip.");
                }

                if (_name != null && _name.EndsWith(".exe") && !_SavingSfx)
                {
                    throw new BadStateException("You specified an EXE for a plain zip file.");
                }

                // check if modified, before saving.
                if (!_contentsChanged)
                {
                    OnSaveCompleted();
                    if (Verbose)
                    {
                        StatusMessageTextWriter.WriteLine("No save is necessary....");
                    }
                    return;
                }

                Reset(true);

                if (Verbose)
                {
                    StatusMessageTextWriter.WriteLine("saving....");
                }

                // validate the number of entries
                if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never)
                {
                    throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance.");
                }


                // write an entry in the zip for each file
                int n = 0;
                // workitem 9831
                ICollection <ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries;
                foreach (ZipEntry e in c) // _entries.Values
                {
                    OnSaveEntry(n, e, true);
                    e.Write(WriteStream);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    n++;
                    OnSaveEntry(n, e, false);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    // Some entries can be skipped during the save.
                    if (e.IncludedInMostRecentSave)
                    {
                        thisSaveUsedZip64 |= e.OutputUsedZip64.Value;
                    }
                }



                if (_saveOperationCanceled)
                {
                    return;
                }

                var zss = WriteStream as ZipSegmentedStream;

                _numberOfSegmentsForMostRecentSave = (zss != null)
                    ? zss.CurrentSegment
                    : 1;

                bool directoryNeededZip64 =
                    ZipOutput.WriteCentralDirectoryStructure
                        (WriteStream,
                        c,
                        _numberOfSegmentsForMostRecentSave,
                        _zip64,
                        Comment,
                        new ZipContainer(this));

                OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive);

                _hasBeenSaved    = true;
                _contentsChanged = false;

                thisSaveUsedZip64 |= directoryNeededZip64;
                _OutputUsesZip64   = new Nullable <bool>(thisSaveUsedZip64);

                if (_fileAlreadyExists && this._readstream != null)
                {
                    // This means we opened and read a zip file.
                    // If we are now saving, we need to close the orig file, first.
                    this._readstream.Close();
                    this._readstream = null;
                }
                // the archiveStream for each entry needs to be null
                foreach (var e in c)
                {
                    var zss1 = e._archiveStream as ZipSegmentedStream;
                    if (zss1 != null)
                    {
                        zss1.Dispose();
                    }
                    e._archiveStream = null;
                }

                // do the rename as necessary
                if (_name != null &&
                    (_temporaryFileName != null || zss != null))
                {
                    // _temporaryFileName may remain null if we are writing to a stream.
                    // only close the stream if there is a file behind it.
                    WriteStream.Dispose();

                    if (_saveOperationCanceled)
                    {
                        return;
                    }

                    string tmpName = null;
                    if (File.Exists(_name))
                    {
                        tmpName = _name + "." + Path.GetRandomFileName();
                        if (File.Exists(tmpName))
                        {
                            DeleteFileWithRetry(tmpName);
                        }
                        File.Move(_name, tmpName);
                    }

                    OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive);
                    File.Move((zss != null) ? zss.CurrentTempName : _temporaryFileName,
                              _name);

                    OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive);

                    if (tmpName != null)
                    {
                        try
                        {
                            // not critical
                            if (File.Exists(tmpName))
                            {
                                File.Delete(tmpName);
                            }
                        }
                        catch
                        {
                            // don't care about exceptions here.
                        }
                    }
                    _fileAlreadyExists = true;
                }
                _readName = _name;

                NotifyEntriesSaveComplete(c);
                OnSaveCompleted();
                _JustSaved = true;
            }

            // workitem 5043
            finally
            {
                CleanupAfterSaveOperation();
            }

            return;
        }
Example #8
0
        /// <summary>
        ///   Saves the Zip archive to a file, specified by the Name property of the
        ///   <c>ZipFile</c>.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   The <c>ZipFile</c> instance is written to storage, typically a zip file
        ///   in a filesystem, only when the caller calls <c>Save</c>.  In the typical
        ///   case, the Save operation writes the zip content to a temporary file, and
        ///   then renames the temporary file to the desired name. If necessary, this
        ///   method will delete a pre-existing file before the rename.
        /// </para>
        ///
        /// <para>
        ///   The <see cref="ZipFile.Name"/> property is specified either explicitly,
        ///   or implicitly using one of the parameterized ZipFile constructors.  For
        ///   COM Automation clients, the <c>Name</c> property must be set explicitly,
        ///   because COM Automation clients cannot call parameterized constructors.
        /// </para>
        ///
        /// <para>
        ///   When using a filesystem file for the Zip output, it is possible to call
        ///   <c>Save</c> multiple times on the <c>ZipFile</c> instance. With each
        ///   call the zip content is re-written to the same output file.
        /// </para>
        ///
        /// <para>
        ///   Data for entries that have been added to the <c>ZipFile</c> instance is
        ///   written to the output when the <c>Save</c> method is called. This means
        ///   that the input streams for those entries must be available at the time
        ///   the application calls <c>Save</c>.  If, for example, the application
        ///   adds entries with <c>AddEntry</c> using a dynamically-allocated
        ///   <c>MemoryStream</c>, the memory stream must not have been disposed
        ///   before the call to <c>Save</c>. See the <see
        ///   cref="ZipEntry.InputStream"/> property for more discussion of the
        ///   availability requirements of the input stream for an entry, and an
        ///   approach for providing just-in-time stream lifecycle management.
        /// </para>
        ///
        /// </remarks>
        ///
        /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(String, System.IO.Stream)"/>
        ///
        /// <exception cref="Ionic.Zip.BadStateException">
        ///   Thrown if you haven't specified a location or stream for saving the zip,
        ///   either in the constructor or by setting the Name property, or if you try
        ///   to save a regular zip archive to a filename with a .exe extension.
        /// </exception>
        ///
        /// <exception cref="System.OverflowException">
        ///   Thrown if <see cref="MaxOutputSegmentSize"/> is non-zero, and the number
        ///   of segments that would be generated for the spanned zip file during the
        ///   save operation exceeds 99.  If this happens, you need to increase the
        ///   segment size.
        /// </exception>
        ///
        public void Save()
        {
            try
            {
                bool thisSaveUsedZip64 = false;
                _saveOperationCanceled             = false;
                _numberOfSegmentsForMostRecentSave = 0;
                OnSaveStarted();

                if (WriteStream == null)
                {
                    throw new BadStateException("You haven't specified where to save the zip.");
                }

                if (_name != null && _name.EndsWith(".exe") && !_SavingSfx)
                {
                    throw new BadStateException("You specified an EXE for a plain zip file.");
                }

                // check if modified, before saving.
                if (!_contentsChanged)
                {
                    OnSaveCompleted();
                    if (Verbose)
                    {
                        StatusMessageTextWriter.WriteLine("No save is necessary....");
                    }
                    return;
                }

                Reset(true);

                if (Verbose)
                {
                    StatusMessageTextWriter.WriteLine("saving....");
                }

                // validate the number of entries
                if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never)
                {
                    throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance.");
                }


                // write an entry in the zip for each file
                int n = 0;
                // workitem 9831
                ICollection <ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries;
                foreach (ZipEntry e in c) // _entries.Values
                {
                    OnSaveEntry(n, e, true);
                    e.Write(WriteStream);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    n++;
                    OnSaveEntry(n, e, false);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    // Some entries can be skipped during the save.
                    if (e.IncludedInMostRecentSave)
                    {
                        thisSaveUsedZip64 |= e.OutputUsedZip64.Value;
                    }
                }



                if (_saveOperationCanceled)
                {
                    return;
                }

                var zss = WriteStream as ZipSegmentedStream;

                _numberOfSegmentsForMostRecentSave = (zss != null)
                    ? zss.CurrentSegment
                    : 1;

                bool directoryNeededZip64 =
                    ZipOutput.WriteCentralDirectoryStructure
                        (WriteStream,
                        c,
                        _numberOfSegmentsForMostRecentSave,
                        _zip64,
                        Comment,
                        new ZipContainer(this));

                OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive);

                _hasBeenSaved    = true;
                _contentsChanged = false;

                thisSaveUsedZip64 |= directoryNeededZip64;
                _OutputUsesZip64   = new Nullable <bool>(thisSaveUsedZip64);


                // do the rename as necessary
                if (_name != null &&
                    (_temporaryFileName != null || zss != null))
                {
                    // _temporaryFileName may remain null if we are writing to a stream.
                    // only close the stream if there is a file behind it.
#if NETCF
                    WriteStream.Close();
#else
                    WriteStream.Dispose();
#endif
                    if (_saveOperationCanceled)
                    {
                        return;
                    }

                    if (_fileAlreadyExists && this._readstream != null)
                    {
                        // This means we opened and read a zip file.
                        // If we are now saving to the same file, we need to close the
                        // orig file, first.
                        this._readstream.Close();
                        this._readstream.Dispose();
                        this._readstream = null;
                        // the archiveStream for each entry needs to be null
                        foreach (var e in c)
                        {
                            var zss1 = e._archiveStream as ZipSegmentedStream;
                            if (zss1 != null)
#if NETCF
                            { zss1.Close(); }
#else
                            { zss1.Dispose(); }
#endif
                            e._archiveStream = null;
                        }
                    }

                    if (_fileAlreadyExists && this._writestream != null)
                    {
                        this.WriteStream.Close();
                    }

                    string tmpName = null;
                    if (File.Exists(_name))
                    {
                        // the steps:
                        //
                        // 1. Delete tmpName
                        // 2. move existing zip to tmpName
                        // 3. rename (File.Move) working file to name of existing zip
                        // 4. delete tmpName
                        //
                        // This series of steps avoids the exception,
                        // System.IO.IOException:
                        //   "Cannot create a file when that file already exists."
                        //
                        // Cannot just call File.Replace() here because
                        // there is a possibility that the TEMP volume is different
                        // that the volume for the final file (c:\ vs d:\).
                        // So we need to do a Delete+Move pair.
                        //
                        // But, when doing the delete, Windows allows a process to
                        // delete the file, even though it is held open by, say, a
                        // virus scanner. It gets internally marked as "delete
                        // pending". The file does not actually get removed from the
                        // file system, it is still there after the File.Delete
                        // call.
                        //
                        // Therefore, we need to move the existing zip, which may be
                        // held open, to some other name. Then rename our working
                        // file to the desired name, then delete (possibly delete
                        // pending) the "other name".
                        //
                        // Ideally this would be transactional. It's possible that the
                        // delete succeeds and the move fails. Lacking transactions, if
                        // this kind of failure happens, we're hosed, and this logic will
                        // throw on the next File.Move().
                        //
                        //File.Delete(_name);
                        // workitem 10447
#if NETCF || SILVERLIGHT
                        tmpName = _name + "." + SharedUtilities.GenerateRandomStringImpl(8, 0) + ".tmp";
#else
                        tmpName = _name + "." + Path.GetRandomFileName();
#endif
                        if (File.Exists(tmpName))
                        {
                            DeleteFileWithRetry(tmpName);
                        }

                        try {
                            File.Move(_name, tmpName);
                        }
                        catch {
                            if (System.Diagnostics.Debugger.IsAttached)
                            {
                                System.Diagnostics.Debugger.Break(); //Look at the comment below. Added this to force a break here instead of your catch so you don't miss the cause and waste your time like I did
                            }
                            throw;
                        }

                        //Oh boy. You've just hit an exception on that File.Move line right above this stating that the template file can't be renamed because it's open
                        //in another process, right?

                        //Congratulation! You've probably run into the same gibberish I ran into!

                        //Check to make sure your file streams are closed, and ITpipes/Template Editor/Winrar/7-Zip don't have the template file open. I'm betting you won't find anything.

                        //If you try closing Visual Studio and running the binary directly I'm betting you won't have this crash occur. Go ahead--try it.

                        //What the hell, right?

                        //The XAML designer process (XDesProc.exe) is configured, by default, to populate its ViewModel in the designer UI. This creates a copy of the model--which creates a second
                        //Ionic.Zip.ZipFile object using the same template file. So when *this* ZipFile object attempts to move the existing template to replace it with an updated file
                        //the exception is thrown.

                        //To fix this, disable the following option in the Visual Studio toolbar above:
                        // Tools -> Options -> XAML Designer -> "Run project code in XAML Designer (if supported)"

                        //Once that's disabled, restart Visual Studio. Problem solved.

                        //Hopefully these comments will prevent someone else from wasting their time obsessing over their streams and AntiVirus. - Vincent Nary
                    }

                    OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive);
                    File.Move((zss != null) ? zss.CurrentTempName : _temporaryFileName,
                              _name);

                    OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive);

                    if (tmpName != null)
                    {
                        try
                        {
                            // not critical
                            if (File.Exists(tmpName))
                            {
                                File.Delete(tmpName);
                            }
                        }
                        catch
                        {
                            // don't care about exceptions here.
                        }
                    }
                    _fileAlreadyExists = true;
                }

                NotifyEntriesSaveComplete(c);
                OnSaveCompleted();
                _JustSaved = true;
            }

            // workitem 5043
            finally
            {
                CleanupAfterSaveOperation();
            }

            return;
        }
Example #9
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);
        }
Example #10
0
        /// <summary>
        ///   Saves the Zip archive to a file, specified by the Name property of the
        ///   <c>ZipFile</c>.
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        ///   The <c>ZipFile</c> instance is written to storage, typically a zip file
        ///   in a filesystem, only when the caller calls <c>Save</c>.  In the typical
        ///   case, the Save operation writes the zip content to a temporary file, and
        ///   then renames the temporary file to the desired name. If necessary, this
        ///   method will delete a pre-existing file before the rename.
        /// </para>
        ///
        /// <para>
        ///   The <see cref="ZipFile.Name"/> property is specified either explicitly,
        ///   or implicitly using one of the parameterized ZipFile constructors.  For
        ///   COM Automation clients, the <c>Name</c> property must be set explicitly,
        ///   because COM Automation clients cannot call parameterized constructors.
        /// </para>
        ///
        /// <para>
        ///   When using a filesystem file for the Zip output, it is possible to call
        ///   <c>Save</c> multiple times on the <c>ZipFile</c> instance. With each
        ///   call the zip content is re-written to the same output file.
        /// </para>
        ///
        /// <para>
        ///   Data for entries that have been added to the <c>ZipFile</c> instance is
        ///   written to the output when the <c>Save</c> method is called. This means
        ///   that the input streams for those entries must be available at the time
        ///   the application calls <c>Save</c>.  If, for example, the application
        ///   adds entries with <c>AddEntry</c> using a dynamically-allocated
        ///   <c>MemoryStream</c>, the memory stream must not have been disposed
        ///   before the call to <c>Save</c>. See the <see
        ///   cref="ZipEntry.InputStream"/> property for more discussion of the
        ///   availability requirements of the input stream for an entry, and an
        ///   approach for providing just-in-time stream lifecycle management.
        /// </para>
        ///
        /// </remarks>
        ///
        /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(String, System.IO.Stream)"/>
        ///
        /// <exception cref="Ionic.Zip.BadStateException">
        ///   Thrown if you haven't specified a location or stream for saving the zip,
        ///   either in the constructor or by setting the Name property, or if you try
        ///   to save a regular zip archive to a filename with a .exe extension.
        /// </exception>
        ///
        /// <exception cref="System.OverflowException">
        ///   Thrown if <see cref="MaxOutputSegmentSize"/> is non-zero, and the number
        ///   of segments that would be generated for the spanned zip file during the
        ///   save operation exceeds 99.  If this happens, you need to increase the
        ///   segment size.
        /// </exception>
        ///
        internal void Save()
        {
            try
            {
                bool thisSaveUsedZip64 = false;
                _saveOperationCanceled             = false;
                _numberOfSegmentsForMostRecentSave = 0;
                OnSaveStarted();

                if (WriteStream == null)
                {
                    throw new BadStateException("You haven't specified where to save the zip.");
                }


                // check if modified, before saving.
                if (!_contentsChanged)
                {
                    OnSaveCompleted();
                    if (Verbose)
                    {
                        StatusMessageTextWriter.WriteLine("No save is necessary....");
                    }
                    return;
                }

                Reset(true);

                if (Verbose)
                {
                    StatusMessageTextWriter.WriteLine("saving....");
                }

                // validate the number of entries
                if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never)
                {
                    throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance.");
                }


                // write an entry in the zip for each file
                int n = 0;
                // workitem 9831
                ICollection <ZipEntry> c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries;
                foreach (ZipEntry e in c) // _entries.Values
                {
                    OnSaveEntry(n, e, true);
                    e.Write(WriteStream);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    n++;
                    OnSaveEntry(n, e, false);
                    if (_saveOperationCanceled)
                    {
                        break;
                    }

                    // Some entries can be skipped during the save.
                    if (e.IncludedInMostRecentSave)
                    {
                        thisSaveUsedZip64 |= e.OutputUsedZip64.Value;
                    }
                }



                if (_saveOperationCanceled)
                {
                    return;
                }

                var zss = WriteStream as ZipSegmentedStream;

                _numberOfSegmentsForMostRecentSave = (zss != null)
                    ? zss.CurrentSegment
                    : 0;

                bool directoryNeededZip64 =
                    ZipOutput.WriteCentralDirectoryStructure
                        (WriteStream,
                        c,
                        (zss != null) ? zss.CurrentSegment : 1,
                        _zip64,
                        Comment,
                        new ZipContainer(this));

                OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive);

                _hasBeenSaved    = true;
                _contentsChanged = false;

                thisSaveUsedZip64 |= directoryNeededZip64;
                _OutputUsesZip64   = new Nullable <bool>(thisSaveUsedZip64);



                NotifyEntriesSaveComplete(c);
                OnSaveCompleted();
                _JustSaved = true;
            }

            // workitem 5043
            finally
            {
                CleanupAfterSaveOperation();
            }

            return;
        }