Пример #1
0
        internal static int ReadEntrySignature(Stream s)
        {
            int num = 0;

            try
            {
                num = SharedUtilities._ReadFourBytes(s, "n/a");
                if (num == 134695760)
                {
                    s.Seek(12L, SeekOrigin.Current);
                    num = SharedUtilities._ReadFourBytes(s, "n/a");
                    if (num != 67324752)
                    {
                        s.Seek(8L, SeekOrigin.Current);
                        num = SharedUtilities._ReadFourBytes(s, "n/a");
                        if (num != 67324752)
                        {
                            s.Seek(-24L, SeekOrigin.Current);
                            num = SharedUtilities._ReadFourBytes(s, "n/a");
                        }
                    }
                }
            }
            catch (BadReadException)
            {
            }
            return(num);
        }
Пример #2
0
 public void InitCipher(string passphrase)
 {
     byte[] array = SharedUtilities.StringToByteArray(passphrase);
     for (int i = 0; i < passphrase.Length; i++)
     {
         this.UpdateKeys(array[i]);
     }
 }
Пример #3
0
        internal static int ReadSignature(Stream s)
        {
            int result = 0;

            try
            {
                result = SharedUtilities._ReadFourBytes(s, "n/a");
            }
            catch (BadReadException)
            {
            }
            return(result);
        }
 public long TruncateBackward(uint diskNumber, long offset)
 {
     if (diskNumber >= 99u)
     {
         throw new ArgumentOutOfRangeException("diskNumber");
     }
     if (this.rwMode != ZipSegmentedStream.RwMode.Write)
     {
         this._exceptionPending = true;
         throw new ZipException("bad state.");
     }
     if (diskNumber == this.CurrentSegment)
     {
         return(this._innerStream.Seek(offset, SeekOrigin.Begin));
     }
     if (this._innerStream != null)
     {
         this._innerStream.Dispose();
         if (File.Exists(this._currentTempName))
         {
             File.Delete(this._currentTempName);
         }
     }
     for (uint num = this.CurrentSegment - 1u; num > diskNumber; num -= 1u)
     {
         string path = this._NameForSegment(num);
         if (File.Exists(path))
         {
             File.Delete(path);
         }
     }
     this.CurrentSegment = diskNumber;
     for (int i = 0; i < 3; i++)
     {
         try
         {
             this._currentTempName = SharedUtilities.InternalGetTempFileName();
             File.Move(this.CurrentName, this._currentTempName);
             break;
         }
         catch (IOException)
         {
             if (i == 2)
             {
                 throw;
             }
         }
     }
     this._innerStream = new FileStream(this._currentTempName, FileMode.Open);
     return(this._innerStream.Seek(offset, SeekOrigin.Begin));
 }
Пример #5
0
 public static string NormalizePathForUseInZipFile(string pathName)
 {
     if (string.IsNullOrEmpty(pathName))
     {
         return(pathName);
     }
     if (pathName.Length >= 2 && pathName[1] == ':' && pathName[2] == '\\')
     {
         pathName = pathName.Substring(3);
     }
     pathName = pathName.Replace('\\', '/');
     while (pathName.StartsWith("/"))
     {
         pathName = pathName.Substring(1);
     }
     return(SharedUtilities.SimplifyFwdSlashPath(pathName));
 }
Пример #6
0
        internal static long FindSignature(Stream stream, int SignatureToFind)
        {
            long position = stream.Position;
            int  num      = 65536;

            byte[] array = new byte[]
            {
                (byte)(SignatureToFind >> 24),
                (byte)((SignatureToFind & 16711680) >> 16),
                (byte)((SignatureToFind & 65280) >> 8),
                (byte)(SignatureToFind & 255)
            };
            byte[] array2 = new byte[num];
            bool   flag   = false;

            do
            {
                int num2 = stream.Read(array2, 0, array2.Length);
                if (num2 == 0)
                {
                    break;
                }
                for (int i = 0; i < num2; i++)
                {
                    if (array2[i] == array[3])
                    {
                        long position2 = stream.Position;
                        stream.Seek((long)(i - num2), SeekOrigin.Current);
                        int num3 = SharedUtilities.ReadSignature(stream);
                        flag = (num3 == SignatureToFind);
                        if (flag)
                        {
                            break;
                        }
                        stream.Seek(position2, SeekOrigin.Begin);
                    }
                }
            }while (!flag);
            if (!flag)
            {
                stream.Seek(position, SeekOrigin.Begin);
                return(-1L);
            }
            return(stream.Position - position - 4L);
        }
Пример #7
0
 public static void CreateAndOpenUniqueTempFile(string dir, out Stream fs, out string filename)
 {
     for (int i = 0; i < 3; i++)
     {
         try
         {
             filename = Path.Combine(dir, SharedUtilities.InternalGetTempFileName());
             fs       = new FileStream(filename, FileMode.CreateNew);
             return;
         }
         catch (IOException)
         {
             if (i == 2)
             {
                 throw;
             }
         }
     }
     throw new IOException();
 }
 private void _SetWriteStream(uint increment)
 {
     if (this._innerStream != null)
     {
         this._innerStream.Dispose();
         if (File.Exists(this.CurrentName))
         {
             File.Delete(this.CurrentName);
         }
         File.Move(this._currentTempName, this.CurrentName);
     }
     if (increment > 0u)
     {
         this.CurrentSegment += increment;
     }
     SharedUtilities.CreateAndOpenUniqueTempFile(this._baseDir, out this._innerStream, out this._currentTempName);
     if (this.CurrentSegment == 0u)
     {
         this._innerStream.Write(BitConverter.GetBytes(134695760), 0, 4);
     }
 }
Пример #9
0
 public ZipEntry GetNextEntry()
 {
     if (this._findRequired)
     {
         long num = SharedUtilities.FindSignature(this._inputStream, 67324752);
         if (num == -1L)
         {
             return(null);
         }
         this._inputStream.Seek(-4L, SeekOrigin.Current);
     }
     else if (this._firstEntry)
     {
         this._inputStream.Seek(this._endOfEntry, SeekOrigin.Begin);
     }
     this._currentEntry = ZipEntry.ReadEntry(this._container, !this._firstEntry);
     this._endOfEntry   = this._inputStream.Position;
     this._firstEntry   = true;
     this._needSetup    = true;
     this._findRequired = false;
     return(this._currentEntry);
 }
Пример #10
0
 public bool ContainsEntry(string name)
 {
     return(this._entriesWritten.ContainsKey(SharedUtilities.NormalizePathForUseInZipFile(name)));
 }
Пример #11
0
        public long TruncateBackward(uint diskNumber, long offset)
        {
            // Console.WriteLine("***ZSS.Trunc to disk {0}", diskNumber);
            // Console.WriteLine("***ZSS.Trunc:  current disk {0}", CurrentSegment);
            if (diskNumber >= 99)
            {
                throw new ArgumentOutOfRangeException("diskNumber");
            }

            if (rwMode != RwMode.Write)
            {
                _exceptionPending = true;
                throw new ZipException("bad state.");
            }

            // Seek back in the segmented stream to a (maybe) prior segment.

            // Check if it is the same segment.  If it is, very simple.
            if (diskNumber == CurrentSegment)
            {
                var x = _innerStream.Seek(offset, SeekOrigin.Begin);
                // workitem 10178
                Pathfinding.Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_innerStream);
                return(x);
            }

            // Seeking back to a prior segment.
            // The current segment and any intervening segments must be removed.
            // First, close the current segment, and then remove it.
            if (_innerStream != null)
            {
#if NETCF
                _innerStream.Close();
#else
                _innerStream.Dispose();
#endif
                if (File.Exists(_currentTempName))
                {
                    File.Delete(_currentTempName);
                }
            }

            // Now, remove intervening segments.
            for (uint j = CurrentSegment - 1; j > diskNumber; j--)
            {
                string s = _NameForSegment(j);
                // Console.WriteLine("***ZSS.Trunc:  removing file {0}", s);
                if (File.Exists(s))
                {
                    File.Delete(s);
                }
            }

            // now, open the desired segment.  It must exist.
            CurrentSegment = diskNumber;

            // get a new temp file, try 3 times:
            for (int i = 0; i < 3; i++)
            {
                try
                {
                    _currentTempName = SharedUtilities.InternalGetTempFileName();
                    // move the .z0x file back to a temp name
                    File.Move(CurrentName, _currentTempName);
                    break; // workitem 12403
                }
                catch (IOException)
                {
                    if (i == 2)
                    {
                        throw;
                    }
                }
            }

            // open it
            _innerStream = new FileStream(_currentTempName, FileMode.Open);

            var r = _innerStream.Seek(offset, SeekOrigin.Begin);

            // workitem 10178
            Pathfinding.Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_innerStream);

            return(r);
        }
Пример #12
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 = 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;
                        }
                    }

                    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;
                }

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

            // workitem 5043
            finally
            {
                CleanupAfterSaveOperation();
            }

            return;
        }
Пример #13
0
        private static void ReadIntoInstance(ZipFile zf)
        {
            Stream s = zf.ReadStream;

            try
            {
                zf._readName = zf._name; // workitem 13915
                if (!s.CanSeek)
                {
                    ReadIntoInstance_Orig(zf);
                    return;
                }

                zf.OnReadStarted();

                // change for workitem 8098
                //zf._originPosition = s.Position;

                // Try reading the central directory, rather than scanning the file.

                uint datum = ReadFirstFourBytes(s);

                if (datum == ZipConstants.EndOfCentralDirectorySignature)
                {
                    return;
                }


                // start at the end of the file...
                // seek backwards a bit, then look for the EoCD signature.
                int  nTries  = 0;
                bool success = false;

                // The size of the end-of-central-directory-footer plus 2 bytes is 18.
                // This implies an archive comment length of 0.  We'll add a margin of
                // safety and start "in front" of that, when looking for the
                // EndOfCentralDirectorySignature
                long posn        = s.Length - 64;
                long maxSeekback = Math.Max(s.Length - 0x4000, 10);
                do
                {
                    if (posn < 0)
                    {
                        posn = 0;            // BOF
                    }
                    s.Seek(posn, SeekOrigin.Begin);
                    long bytesRead = SharedUtilities.FindSignature(s, (int)ZipConstants.EndOfCentralDirectorySignature);
                    if (bytesRead != -1)
                    {
                        success = true;
                    }
                    else
                    {
                        if (posn == 0)
                        {
                            break;          // started at the BOF and found nothing
                        }
                        nTries++;
                        // Weird: with NETCF, negative offsets from SeekOrigin.End DO
                        // NOT WORK. So rather than seek a negative offset, we seek
                        // from SeekOrigin.Begin using a smaller number.
                        posn -= (32 * (nTries + 1) * nTries);
                    }
                }while (!success && posn > maxSeekback);

                if (success)
                {
                    // workitem 8299
                    zf._locEndOfCDS = s.Position - 4;

                    byte[] block = new byte[16];
                    s.Read(block, 0, block.Length);

                    zf._diskNumberWithCd = BitConverter.ToUInt16(block, 2);

                    if (zf._diskNumberWithCd == 0xFFFF)
                    {
                        throw new ZipException("Spanned archives with more than 65534 segments are not supported at this time.");
                    }

                    zf._diskNumberWithCd++; // I think the number in the file differs from reality by 1

                    int i = 12;

                    uint offset32 = (uint)BitConverter.ToUInt32(block, i);
                    if (offset32 == 0xFFFFFFFF)
                    {
                        Zip64SeekToCentralDirectory(zf);
                    }
                    else
                    {
                        zf._OffsetOfCentralDirectory = offset32;
                        // change for workitem 8098
                        s.Seek(offset32, SeekOrigin.Begin);
                    }

                    ReadCentralDirectory(zf);
                }
                else
                {
                    // Could not find the central directory.
                    // Fallback to the old method.
                    // workitem 8098: ok
                    //s.Seek(zf._originPosition, SeekOrigin.Begin);
                    s.Seek(0L, SeekOrigin.Begin);
                    ReadIntoInstance_Orig(zf);
                }
            }
            catch (Exception ex1)
            {
                if (zf._ReadStreamIsOurs && zf._readstream != null)
                {
                    try
                    {
#if NETCF
                        zf._readstream.Close();
#else
                        zf._readstream.Dispose();
#endif
                        zf._readstream = null;
                    }
                    finally { }
                }

                throw new ZipException("Cannot read that as a ZipFile", ex1);
            }

            // the instance has been read in
            zf._contentsChanged = false;
        }
Пример #14
0
 internal static int ReadInt(Stream s)
 {
     return(SharedUtilities._ReadFourBytes(s, "Could not read block - no data!  (position 0x{0:X8})"));
 }
Пример #15
0
 internal static string Utf8StringFromBuffer(byte[] buf)
 {
     return(SharedUtilities.StringFromBuffer(buf, SharedUtilities.utf8));
 }
Пример #16
0
 internal static byte[] StringToByteArray(string value)
 {
     return(SharedUtilities.StringToByteArray(value, SharedUtilities.ibm437));
 }
Пример #17
0
 public static string InternalGetTempFileName()
 {
     return("DotNetZip-" + SharedUtilities.GenerateRandomStringImpl(8, 0) + ".tmp");
 }