Esempio n. 1
0
 private static void AddExtraDataAes(ZipEntry entry, ZipExtraData extraData)
 {
     extraData.StartNewEntry();
     extraData.AddLeShort(2);
     extraData.AddLeShort(0x4541);
     extraData.AddData(entry.AesEncryptionStrength);
     extraData.AddLeShort((int)entry.CompressionMethod);
     extraData.AddNewEntry(0x9901);
 }
Esempio n. 2
0
        internal void ProcessExtraData(bool localHeader)
        {
            ZipExtraData zipExtraData = new ZipExtraData(this.extra);

            if (zipExtraData.Find(1))
            {
                if ((this.versionToExtract & 255) < 45)
                {
                    throw new ZipException("Zip64 Extended information found but version is not valid");
                }
                this.forceZip64_ = true;
                if (zipExtraData.ValueLength < 4)
                {
                    throw new ZipException("Extra data extended Zip64 information length is invalid");
                }
                if (localHeader || this.size == unchecked ((ulong)-1))
                {
                    this.size = (ulong)zipExtraData.ReadLong();
                }
                if (localHeader || this.compressedSize == unchecked ((ulong)-1))
                {
                    this.compressedSize = (ulong)zipExtraData.ReadLong();
                }
            }
            else if ((this.versionToExtract & 255) >= 45 && (this.size == unchecked ((ulong)-1) || this.compressedSize == unchecked ((ulong)-1)))
            {
                throw new ZipException("Zip64 Extended information required but is missing.");
            }
            if (zipExtraData.Find(21589))
            {
                int valueLength = zipExtraData.ValueLength;
                int num         = zipExtraData.ReadByte();
                if ((num & 1) != 0 && valueLength >= 5)
                {
                    int seconds = zipExtraData.ReadInt();
                    this.DateTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + new TimeSpan(0, 0, 0, seconds, 0)).ToLocalTime();
                }
            }
        }
Esempio n. 3
0
        private void ProcessAesExtraData(ZipExtraData extraData)
        {
            if (!extraData.Find(0x9901))
            {
                throw new ZipException("AES Extra Data missing");
            }
            _versionToExtract = 0x33;
            Flags            |= 0x40;
            int valueLength = extraData.ValueLength;

            if (valueLength < 7)
            {
                throw new ZipException("AES Extra Data Length " + valueLength + " invalid.");
            }
            extraData.ReadShort();
            extraData.ReadShort();
            int num3 = extraData.ReadByte();
            int num4 = extraData.ReadShort();

            _aesEncryptionStrength = num3;
            _method = (CompressionMethod)num4;
        }
Esempio n. 4
0
 public override void Finish()
 {
     if (_entries != null)
     {
         if (_curEntry != null)
         {
             CloseEntry();
         }
         long count = _entries.Count;
         long sizeEntries = 0L;
         foreach (ZipEntry entry in _entries)
         {
             WriteLeInt(ZipConstants.CentralHeaderSignature);
             WriteLeShort(0x33);
             WriteLeShort(entry.Version);
             WriteLeShort(entry.Flags);
             WriteLeShort((short)entry.CompressionMethodForHeader);
             WriteLeInt((int)entry.DosTime);
             WriteLeInt((int)entry.Crc);
             if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL))
             {
                 WriteLeInt(-1);
             }
             else
             {
                 WriteLeInt((int)entry.CompressedSize);
             }
             if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL))
             {
                 WriteLeInt(-1);
             }
             else
             {
                 WriteLeInt((int)entry.Size);
             }
             byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
             if (buffer.Length > 0xffff)
             {
                 throw new ZipException("Name too long.");
             }
             ZipExtraData extraData = new ZipExtraData(entry.ExtraData);
             if (entry.CentralHeaderRequiresZip64)
             {
                 extraData.StartNewEntry();
                 if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL))
                 {
                     extraData.AddLeLong(entry.Size);
                 }
                 if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL))
                 {
                     extraData.AddLeLong(entry.CompressedSize);
                 }
                 if (entry.Offset >= 0xffffffffL)
                 {
                     extraData.AddLeLong(entry.Offset);
                 }
                 extraData.AddNewEntry(1);
             }
             else
             {
                 extraData.Delete(1);
             }
             if (entry.AesKeySize > 0)
             {
                 AddExtraDataAes(entry, extraData);
             }
             byte[] entryData = extraData.GetEntryData();
             byte[] buffer3 = (entry.Comment != null) ? ZipConstants.ConvertToArray(entry.Flags, entry.Comment) : new byte[0];
             if (buffer3.Length > 0xffff)
             {
                 throw new ZipException("Comment too long.");
             }
             WriteLeShort(buffer.Length);
             WriteLeShort(entryData.Length);
             WriteLeShort(buffer3.Length);
             WriteLeShort(0);
             WriteLeShort(0);
             if (entry.ExternalFileAttributes != -1)
             {
                 WriteLeInt(entry.ExternalFileAttributes);
             }
             else if (entry.IsDirectory)
             {
                 WriteLeInt(0x10);
             }
             else
             {
                 WriteLeInt(0);
             }
             if (entry.Offset >= 0xffffffffL)
             {
                 WriteLeInt(-1);
             }
             else
             {
                 WriteLeInt((int)entry.Offset);
             }
             if (buffer.Length > 0)
             {
                 BaseOutputStream.Write(buffer, 0, buffer.Length);
             }
             if (entryData.Length > 0)
             {
                 BaseOutputStream.Write(entryData, 0, entryData.Length);
             }
             if (buffer3.Length > 0)
             {
                 BaseOutputStream.Write(buffer3, 0, buffer3.Length);
             }
             sizeEntries += ((ZipConstants.CentralHeaderBaseSize + buffer.Length) + entryData.Length) + buffer3.Length;
         }
         using (ZipHelperStream stream = new ZipHelperStream(BaseOutputStream))
         {
             stream.WriteEndOfCentralDirectory(count, sizeEntries, _offset, _zipComment);
         }
         _entries = null;
     }
 }
Esempio n. 5
0
 private int WriteCentralDirectoryHeader(ZipEntry entry)
 {
     if (entry.CompressedSize < 0L)
     {
         throw new ZipException("Attempt to write central directory entry with unknown csize");
     }
     if (entry.Size < 0L)
     {
         throw new ZipException("Attempt to write central directory entry with unknown size");
     }
     if (entry.Crc < 0L)
     {
         throw new ZipException("Attempt to write central directory entry with unknown crc");
     }
     WriteLeInt(ZipConstants.CentralHeaderSignature);
     WriteLeShort(0x33);
     WriteLeShort(entry.Version);
     WriteLeShort(entry.Flags);
     WriteLeShort((byte)entry.CompressionMethod);
     WriteLeInt((int)entry.DosTime);
     WriteLeInt((int)entry.Crc);
     if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL))
     {
         WriteLeInt(-1);
     }
     else
     {
         WriteLeInt((int)(((ulong)entry.CompressedSize) & 0xffffffffL));
     }
     if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL))
     {
         WriteLeInt(-1);
     }
     else
     {
         WriteLeInt((int)entry.Size);
     }
     var buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
     if (buffer.Length > 0xffff)
     {
         throw new ZipException("Entry name is too long.");
     }
     WriteLeShort(buffer.Length);
     var data = new ZipExtraData(entry.ExtraData);
     if (entry.CentralHeaderRequiresZip64)
     {
         data.StartNewEntry();
         if ((entry.Size >= 0xffffffffL) || (_useZip64 == UseZip64.On))
         {
             data.AddLeLong(entry.Size);
         }
         if ((entry.CompressedSize >= 0xffffffffL) || (_useZip64 == UseZip64.On))
         {
             data.AddLeLong(entry.CompressedSize);
         }
         if (entry.Offset >= 0xffffffffL)
         {
             data.AddLeLong(entry.Offset);
         }
         data.AddNewEntry(1);
     }
     else
     {
         data.Delete(1);
     }
     var entryData = data.GetEntryData();
     WriteLeShort(entryData.Length);
     WriteLeShort(entry.Comment?.Length ?? 0);
     WriteLeShort(0);
     WriteLeShort(0);
     if (entry.ExternalFileAttributes != -1)
     {
         WriteLeInt(entry.ExternalFileAttributes);
     }
     else if (entry.IsDirectory)
     {
         WriteLeUint(0x10);
     }
     else
     {
         WriteLeUint(0);
     }
     if (entry.Offset >= 0xffffffffL)
     {
         WriteLeUint(uint.MaxValue);
     }
     else
     {
         WriteLeUint((uint)((int)entry.Offset));
     }
     if (buffer.Length > 0)
     {
         _baseStream.Write(buffer, 0, buffer.Length);
     }
     if (entryData.Length > 0)
     {
         _baseStream.Write(entryData, 0, entryData.Length);
     }
     var buffer3 = (entry.Comment != null) ? Encoding.ASCII.GetBytes(entry.Comment) : new byte[0];
     if (buffer3.Length > 0)
     {
         _baseStream.Write(buffer3, 0, buffer3.Length);
     }
     return (((0x2e + buffer.Length) + entryData.Length) + buffer3.Length);
 }
Esempio n. 6
0
        public override void Finish()
        {
            if (this.entries == null)
            {
                return;
            }
            if (this.curEntry != null)
            {
                this.CloseEntry();
            }
            long noOfEntries = (long)this.entries.Count;
            long num         = 0L;

            foreach (object obj in this.entries)
            {
                ZipEntry zipEntry = (ZipEntry)obj;
                this.WriteLeInt(33639248);
                this.WriteLeShort(45);
                this.WriteLeShort(zipEntry.Version);
                this.WriteLeShort(zipEntry.Flags);
                this.WriteLeShort((int)((short)zipEntry.CompressionMethod));
                this.WriteLeInt((int)zipEntry.DosTime);
                this.WriteLeInt((int)zipEntry.Crc);
                if (zipEntry.IsZip64Forced() || zipEntry.CompressedSize >= unchecked ((long)((ulong)-1)))
                {
                    this.WriteLeInt(-1);
                }
                else
                {
                    this.WriteLeInt((int)zipEntry.CompressedSize);
                }
                if (zipEntry.IsZip64Forced() || zipEntry.Size >= unchecked ((long)((ulong)-1)))
                {
                    this.WriteLeInt(-1);
                }
                else
                {
                    this.WriteLeInt((int)zipEntry.Size);
                }
                byte[] array = ZipConstants.ConvertToArray(zipEntry.Flags, zipEntry.Name);
                if (array.Length > 65535)
                {
                    throw new ZipException("Name too long.");
                }
                ZipExtraData zipExtraData = new ZipExtraData(zipEntry.ExtraData);
                if (zipEntry.CentralHeaderRequiresZip64)
                {
                    zipExtraData.StartNewEntry();
                    if (zipEntry.IsZip64Forced() || zipEntry.Size >= unchecked ((long)((ulong)-1)))
                    {
                        zipExtraData.AddLeLong(zipEntry.Size);
                    }
                    if (zipEntry.IsZip64Forced() || zipEntry.CompressedSize >= unchecked ((long)((ulong)-1)))
                    {
                        zipExtraData.AddLeLong(zipEntry.CompressedSize);
                    }
                    if (zipEntry.Offset >= unchecked ((long)((ulong)-1)))
                    {
                        zipExtraData.AddLeLong(zipEntry.Offset);
                    }
                    zipExtraData.AddNewEntry(1);
                }
                else
                {
                    zipExtraData.Delete(1);
                }
                byte[] entryData = zipExtraData.GetEntryData();
                byte[] array2    = (zipEntry.Comment != null) ? ZipConstants.ConvertToArray(zipEntry.Flags, zipEntry.Comment) : new byte[0];
                if (array2.Length > 65535)
                {
                    throw new ZipException("Comment too long.");
                }
                this.WriteLeShort(array.Length);
                this.WriteLeShort(entryData.Length);
                this.WriteLeShort(array2.Length);
                this.WriteLeShort(0);
                this.WriteLeShort(0);
                if (zipEntry.ExternalFileAttributes != -1)
                {
                    this.WriteLeInt(zipEntry.ExternalFileAttributes);
                }
                else if (zipEntry.IsDirectory)
                {
                    this.WriteLeInt(16);
                }
                else
                {
                    this.WriteLeInt(0);
                }
                if (zipEntry.Offset >= unchecked ((long)((ulong)-1)))
                {
                    this.WriteLeInt(-1);
                }
                else
                {
                    this.WriteLeInt((int)zipEntry.Offset);
                }
                if (array.Length > 0)
                {
                    this.baseOutputStream.Write(array, 0, array.Length);
                }
                if (entryData.Length > 0)
                {
                    this.baseOutputStream.Write(entryData, 0, entryData.Length);
                }
                if (array2.Length > 0)
                {
                    this.baseOutputStream.Write(array2, 0, array2.Length);
                }
                num += (long)(46 + array.Length + entryData.Length + array2.Length);
            }
            using (ZipHelperStream zipHelperStream = new ZipHelperStream(this.baseOutputStream))
            {
                zipHelperStream.WriteEndOfCentralDirectory(noOfEntries, num, this.offset, this.zipComment);
            }
            this.entries = null;
        }
Esempio n. 7
0
        int WriteCentralDirectoryHeader(ZipEntry entry)
        {
            // Write the central file header
            WriteLEInt(ZipConstants.CentralHeaderSignature);

            // Version made by
            WriteLEShort(ZipConstants.VersionMadeBy);

            // Version required to extract
            WriteLEShort(entry.Version);

            WriteLEShort(entry.Flags);
            WriteLEShort((byte)entry.CompressionMethod);
            WriteLEInt((int)entry.DosTime);
            WriteLEInt((int)entry.Crc);

            if ( entry.CompressedSize >= 0xffffffff ) {
                WriteLEInt(-1);
            }
            else {
                WriteLEInt((int)(entry.CompressedSize & 0xffffffff));
            }

            if ( entry.Size >= 0xffffffff ) {
                WriteLEInt(-1);
            }
            else {
                WriteLEInt((int)entry.Size);
            }

            byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);

            if ( name.Length > 0xFFFF ) {
                throw new ZipException("Entry name is too long.");
            }

            WriteLEShort(name.Length);

            // Central header extra data is different to local header version so regenerate.
            ZipExtraData ed = new ZipExtraData(entry.ExtraData);

            if ( entry.CentralHeaderRequiresZip64 ) {
                ed.StartNewEntry();

                if ( (entry.Size >= 0xffffffff) || (useZip64_ == UseZip64.On) )
                {
                    ed.AddLeLong(entry.Size);
                }

                if ( (entry.CompressedSize >= 0xffffffff) || (useZip64_ == UseZip64.On) )
                {
                    ed.AddLeLong(entry.CompressedSize);
                }

                if ( entry.Offset >= 0xffffffff ) {
                    ed.AddLeLong(entry.Offset);
                }

                // Number of disk on which this file starts isnt supported and is never written here.
                ed.AddNewEntry(1);
            }
            else {
                // Should have already be done when local header was added.
                ed.Delete(1);
            }

            byte[] centralExtraData = ed.GetEntryData();

            WriteLEShort(centralExtraData.Length);
            WriteLEShort(entry.Comment != null ? entry.Comment.Length : 0);

            WriteLEShort(0);	// disk number
            WriteLEShort(0);	// internal file attributes

            // External file attributes...
            if ( entry.ExternalFileAttributes != -1 ) {
                WriteLEInt(entry.ExternalFileAttributes);
            }
            else {
                if ( entry.IsDirectory ) {
                    WriteLEUint(16);
                }
                else {
                    WriteLEUint(0);
                }
            }

            if ( entry.Offset >= 0xffffffff ) {
                WriteLEUint(0xffffffff);
            }
            else {
                WriteLEUint((uint)(int)entry.Offset);
            }

            if ( name.Length > 0 ) {
                baseStream_.Write(name, 0, name.Length);
            }

            if ( centralExtraData.Length > 0 ) {
                baseStream_.Write(centralExtraData, 0, centralExtraData.Length);
            }

            byte[] rawComment = (entry.Comment != null) ? Encoding.ASCII.GetBytes(entry.Comment) : new byte[0];

            if ( rawComment.Length > 0 ) {
                baseStream_.Write(rawComment, 0, rawComment.Length);
            }

            return ZipConstants.CentralHeaderBaseSize + name.Length + centralExtraData.Length + rawComment.Length;
        }
Esempio n. 8
0
        /// <summary>
        /// Process extra data fields updating the entry based on the contents.
        /// </summary>
        /// <param name="localHeader">True if the extra data fields should be handled
        /// for a local header, rather than for a central header.
        /// </param>
        internal void ProcessExtraData(bool localHeader)
        {
            ZipExtraData extraData = new ZipExtraData(this.extra);

            if (extraData.Find(0x0001))
            {
                if ((versionToExtract & 0xff) < ZipConstants.VersionZip64)
                {
                    throw new ZipException("Zip64 Extended information found but version is not valid");
                }

                // The recorded size will change but remember that this is zip64.
                forceZip64_ = true;

                if (extraData.ValueLength < 4)
                {
                    throw new ZipException("Extra data extended Zip64 information length is invalid");
                }

                if (localHeader || (size == uint.MaxValue))
                {
                    size = (ulong)extraData.ReadLong();
                }

                if (localHeader || (compressedSize == uint.MaxValue))
                {
                    compressedSize = (ulong)extraData.ReadLong();
                }
            }
            else
            {
                if (
                    ((versionToExtract & 0xff) >= ZipConstants.VersionZip64) &&
                    ((size == uint.MaxValue) ||
                     (compressedSize == uint.MaxValue)))
                {
                    throw new ZipException("Zip64 Extended information required but is missing.");
                }
            }

/* TODO: Testing for handling of windows extra data
 *                      if ( extraData.Find(10) ) {
 *                              // No room for any tags.
 *                              if ( extraData.ValueLength < 8 ) {
 *                                      throw new ZipException("NTFS Extra data invalid");
 *                              }
 *
 *                              extraData.ReadInt(); // Reserved
 *
 *                              while ( extraData.UnreadCount >= 4 ) {
 *                                      int ntfsTag = extraData.ReadShort();
 *                                      int ntfsLength = extraData.ReadShort();
 *                                      if ( ntfsTag == 1 ) {
 *                                              if ( ntfsLength >= 24 ) {
 *                                                      long lastModification = extraData.ReadLong();
 *                                                      long lastAccess = extraData.ReadLong();
 *                                                      long createTime = extraData.ReadLong();
 *
 *                                                      DateTime = System.DateTime.FromFileTime(lastModification);
 *                                              }
 *                                              break;
 *                                      }
 *                                      else {
 *                                              // An unknown NTFS tag so simply skip it.
 *                                              extraData.Skip(ntfsLength);
 *                                      }
 *                              }
 *                      }
 *                      else
 */
            if (extraData.Find(0x5455))
            {
                int length = extraData.ValueLength;
                int flags  = extraData.ReadByte();

                // Can include other times but these are ignored.  Length of data should
                // actually be 1 + 4 * no of bits in flags.
                if (((flags & 1) != 0) && (length >= 5))
                {
                    int iTime = extraData.ReadInt();

                    DateTime = (new System.DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() +
                                new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime();
                }
            }
        }
Esempio n. 9
0
		/// <summary>
		/// Starts a new Zip entry. It automatically closes the previous
		/// entry if present.
		/// All entry elements bar name are optional, but must be correct if present.
		/// If the compression method is stored and the output is not patchable
		/// the compression for that entry is automatically changed to deflate level 0
		/// </summary>
		/// <param name="entry">
		/// the entry.
		/// </param>
		/// <exception cref="System.ArgumentNullException">
		/// if entry passed is null.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// if an I/O error occured.
		/// </exception>
		/// <exception cref="System.InvalidOperationException">
		/// if stream was finished
		/// </exception>
		/// <exception cref="ZipException">
		/// Too many entries in the Zip file<br/>
		/// Entry name is too long<br/>
		/// Finish has already been called<br/>
		/// </exception>
		public void PutNextEntry(ZipEntry entry)
		{
			if ( entry == null ) {
				throw new ArgumentNullException("entry");
			}

			if (entries == null) {
				throw new InvalidOperationException("ZipOutputStream was finished");
			}
			
			if (curEntry != null) {
				CloseEntry();
			}

			if (entries.Count == int.MaxValue) {
				throw new ZipException("Too many entries for Zip file");
			}
			
			CompressionMethod method = entry.CompressionMethod;
			int compressionLevel = defaultCompressionLevel;
			
			// Clear flags that the library manages internally
			entry.Flags &= (int)GeneralBitFlags.UnicodeText;
			patchEntryHeader = false;
			bool headerInfoAvailable = true;
			
			if (method == CompressionMethod.Stored) {
				// Cant store values in a data descriptor as you cant extract stored files
				// if the length isnt known.
				entry.Flags &= ~8;
				if (entry.CompressedSize >= 0) {
					if (entry.Size < 0) {
						entry.Size = entry.CompressedSize;
					} else if (entry.Size != entry.CompressedSize) {
						throw new ZipException("Method STORED, but compressed size != size");
					}
				} else {
					if (entry.Size >= 0) {
						entry.CompressedSize = entry.Size;
					}
				}
					
				if (entry.Size < 0 || entry.Crc < 0) {
					if (CanPatchEntries == true) {
						headerInfoAvailable = false;
					}
					else {
						// Can't patch entries so storing is not possible.
						method = CompressionMethod.Deflated;
						compressionLevel = 0;
					}
				}
			}
				
			if (method == CompressionMethod.Deflated) {
				if (entry.Size == 0) {
					// No need to compress - no data.
					entry.CompressedSize = entry.Size;
					entry.Crc = 0;
					method = CompressionMethod.Stored;
				} else if ( (entry.CompressedSize < 0) || (entry.Size < 0) || (entry.Crc < 0) ) {
					headerInfoAvailable = false;
				}
			}
			
			if (headerInfoAvailable == false) {
				if (CanPatchEntries == false) {
					// Only way to record size and compressed size is to append a data descriptor
					// after compressed data.
					entry.Flags |= 8;
				} else {
					patchEntryHeader = true;
				}
			}
			
			if (Password != null) {
				entry.IsCrypted = true;
				if (entry.Crc < 0) {
					// Need to append a data descriptor as the crc isnt available for use
					// with encryption, the date is used instead.  Setting the flag
					// indicates this to the decompressor.
					entry.Flags |= 8;
				}
			}

			entry.Offset = offset;
			entry.CompressionMethod = (CompressionMethod)method;
			
			curMethod = method;
			sizePatchPos = -1;
			
			if ( (useZip64_ == UseZip64.On) || ((entry.Size < 0) && (useZip64_ == UseZip64.Dynamic)) ) {
				entry.ForceZip64();
			}

			// Write the local file header
			WriteLeInt(ZipConstants.LocalHeaderSignature);
			
			WriteLeShort(entry.Version);
			WriteLeShort(entry.Flags);
			WriteLeShort((byte)method);
			WriteLeInt((int)entry.DosTime);

			// TODO: Refactor header writing.  Its done in several places.
			if (headerInfoAvailable == true) {
				WriteLeInt((int)entry.Crc);
				if ( entry.LocalHeaderRequiresZip64 ) {
					WriteLeInt(-1);
					WriteLeInt(-1);
				}
				else {
					WriteLeInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize);
					WriteLeInt((int)entry.Size);
				}
			} else {
				if (patchEntryHeader == true) {
					crcPatchPos = baseOutputStream_.Position;
				}
				WriteLeInt(0);	// Crc
				
				if ( patchEntryHeader ) {
					sizePatchPos = baseOutputStream_.Position;
				}

				// For local header both sizes appear in Zip64 Extended Information
				if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) {
					WriteLeInt(-1);
					WriteLeInt(-1);
				}
				else {
					WriteLeInt(0);	// Compressed size
					WriteLeInt(0);	// Uncompressed size
				}
			}

			byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
			
			if (name.Length > 0xFFFF) {
				throw new ZipException("Entry name too long.");
			}

			ZipExtraData ed = new ZipExtraData(entry.ExtraData);

			if (entry.LocalHeaderRequiresZip64 && (headerInfoAvailable || patchEntryHeader)) {
				ed.StartNewEntry();
				if (headerInfoAvailable) {
					ed.AddLeLong(entry.Size);
					ed.AddLeLong(entry.CompressedSize);
				}
				else {
					ed.AddLeLong(-1);
					ed.AddLeLong(-1);
				}
				ed.AddNewEntry(1);

				if ( !ed.Find(1) ) {
					throw new ZipException("Internal error cant find extra data");
				}
				
				if ( patchEntryHeader ) {
					sizePatchPos = ed.CurrentReadIndex;
				}
			}
			else {
				ed.Delete(1);
			}
			
			byte[] extra = ed.GetEntryData();

			WriteLeShort(name.Length);
			WriteLeShort(extra.Length);

			if ( name.Length > 0 ) {
				baseOutputStream_.Write(name, 0, name.Length);
			}
			
			if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) {
				sizePatchPos += baseOutputStream_.Position;
			}

			if ( extra.Length > 0 ) {
				baseOutputStream_.Write(extra, 0, extra.Length);
			}
			
			offset += ZipConstants.LocalHeaderBaseSize + name.Length + extra.Length;
			
			// Activate the entry.
			curEntry = entry;
			crc.Reset();
			if (method == CompressionMethod.Deflated) {
				deflater_.Reset();
				deflater_.SetLevel(compressionLevel);
			}
			size = 0;
			
			if (entry.IsCrypted == true) {
				if (entry.Crc < 0) {			// so testing Zip will says its ok
					WriteEncryptionHeader(entry.DosTime << 16);
				} else {
					WriteEncryptionHeader(entry.Crc);
				}
			}
		}
Esempio n. 10
0
 public override void Finish()
 {
     if (_entries != null)
     {
         if (_curEntry != null)
         {
             CloseEntry();
         }
         long count       = _entries.Count;
         long sizeEntries = 0L;
         foreach (ZipEntry entry in _entries)
         {
             WriteLeInt(ZipConstants.CentralHeaderSignature);
             WriteLeShort(0x33);
             WriteLeShort(entry.Version);
             WriteLeShort(entry.Flags);
             WriteLeShort((short)entry.CompressionMethodForHeader);
             WriteLeInt((int)entry.DosTime);
             WriteLeInt((int)entry.Crc);
             if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL))
             {
                 WriteLeInt(-1);
             }
             else
             {
                 WriteLeInt((int)entry.CompressedSize);
             }
             if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL))
             {
                 WriteLeInt(-1);
             }
             else
             {
                 WriteLeInt((int)entry.Size);
             }
             byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
             if (buffer.Length > 0xffff)
             {
                 throw new ZipException("Name too long.");
             }
             ZipExtraData extraData = new ZipExtraData(entry.ExtraData);
             if (entry.CentralHeaderRequiresZip64)
             {
                 extraData.StartNewEntry();
                 if (entry.IsZip64Forced() || (entry.Size >= 0xffffffffL))
                 {
                     extraData.AddLeLong(entry.Size);
                 }
                 if (entry.IsZip64Forced() || (entry.CompressedSize >= 0xffffffffL))
                 {
                     extraData.AddLeLong(entry.CompressedSize);
                 }
                 if (entry.Offset >= 0xffffffffL)
                 {
                     extraData.AddLeLong(entry.Offset);
                 }
                 extraData.AddNewEntry(1);
             }
             else
             {
                 extraData.Delete(1);
             }
             if (entry.AesKeySize > 0)
             {
                 AddExtraDataAes(entry, extraData);
             }
             byte[] entryData = extraData.GetEntryData();
             byte[] buffer3   = (entry.Comment != null) ? ZipConstants.ConvertToArray(entry.Flags, entry.Comment) : new byte[0];
             if (buffer3.Length > 0xffff)
             {
                 throw new ZipException("Comment too long.");
             }
             WriteLeShort(buffer.Length);
             WriteLeShort(entryData.Length);
             WriteLeShort(buffer3.Length);
             WriteLeShort(0);
             WriteLeShort(0);
             if (entry.ExternalFileAttributes != -1)
             {
                 WriteLeInt(entry.ExternalFileAttributes);
             }
             else if (entry.IsDirectory)
             {
                 WriteLeInt(0x10);
             }
             else
             {
                 WriteLeInt(0);
             }
             if (entry.Offset >= 0xffffffffL)
             {
                 WriteLeInt(-1);
             }
             else
             {
                 WriteLeInt((int)entry.Offset);
             }
             if (buffer.Length > 0)
             {
                 BaseOutputStream.Write(buffer, 0, buffer.Length);
             }
             if (entryData.Length > 0)
             {
                 BaseOutputStream.Write(entryData, 0, entryData.Length);
             }
             if (buffer3.Length > 0)
             {
                 BaseOutputStream.Write(buffer3, 0, buffer3.Length);
             }
             sizeEntries += ((ZipConstants.CentralHeaderBaseSize + buffer.Length) + entryData.Length) + buffer3.Length;
         }
         using (ZipHelperStream stream = new ZipHelperStream(BaseOutputStream))
         {
             stream.WriteEndOfCentralDirectory(count, sizeEntries, _offset, _zipComment);
         }
         _entries = null;
     }
 }
Esempio n. 11
0
        internal void ProcessExtraData(bool localHeader)
        {
            ZipExtraData extraData = new ZipExtraData(_extra);

            if (extraData.Find(1))
            {
                _forceZip64 = true;
                if (extraData.ValueLength < 4)
                {
                    throw new ZipException("Extra data extended Zip64 information length is invalid");
                }
                if (localHeader || (_size == 0xffffffffL))
                {
                    _size = (ulong)extraData.ReadLong();
                }
                if (localHeader || (_compressedSize == 0xffffffffL))
                {
                    _compressedSize = (ulong)extraData.ReadLong();
                }
                if (!localHeader && (Offset == 0xffffffffL))
                {
                    Offset = extraData.ReadLong();
                }
            }
            else if (((_versionToExtract & 0xff) >= 0x2d) && ((_size == 0xffffffffL) || (_compressedSize == 0xffffffffL)))
            {
                throw new ZipException("Zip64 Extended information required but is missing.");
            }
            if (extraData.Find(10))
            {
                if (extraData.ValueLength < 4)
                {
                    throw new ZipException("NTFS Extra data invalid");
                }
                extraData.ReadInt();
                while (extraData.UnreadCount >= 4)
                {
                    int num    = extraData.ReadShort();
                    int amount = extraData.ReadShort();
                    if (num == 1)
                    {
                        if (amount >= 0x18)
                        {
                            long fileTime = extraData.ReadLong();
                            extraData.ReadLong();
                            extraData.ReadLong();
                            DateTime = DateTime.FromFileTime(fileTime);
                        }
                        break;
                    }
                    extraData.Skip(amount);
                }
            }
            else if (extraData.Find(0x5455))
            {
                int valueLength = extraData.ValueLength;
                if (((extraData.ReadByte() & 1) != 0) && (valueLength >= 5))
                {
                    int      seconds = extraData.ReadInt();
                    DateTime time    = new DateTime(0x7b2, 1, 1, 0, 0, 0);
                    DateTime = (time.ToUniversalTime() + new TimeSpan(0, 0, 0, seconds, 0)).ToLocalTime();
                }
            }
            if (_method == CompressionMethod.WinZipAes)
            {
                ProcessAesExtraData(extraData);
            }
        }
Esempio n. 12
0
 internal void ProcessExtraData(bool localHeader)
 {
     ZipExtraData extraData = new ZipExtraData(_extra);
     if (extraData.Find(1))
     {
         _forceZip64 = true;
         if (extraData.ValueLength < 4)
         {
             throw new ZipException("Extra data extended Zip64 information length is invalid");
         }
         if (localHeader || (_size == 0xffffffffL))
         {
             _size = (ulong)extraData.ReadLong();
         }
         if (localHeader || (_compressedSize == 0xffffffffL))
         {
             _compressedSize = (ulong)extraData.ReadLong();
         }
         if (!localHeader && (Offset == 0xffffffffL))
         {
             Offset = extraData.ReadLong();
         }
     }
     else if (((_versionToExtract & 0xff) >= 0x2d) && ((_size == 0xffffffffL) || (_compressedSize == 0xffffffffL)))
     {
         throw new ZipException("Zip64 Extended information required but is missing.");
     }
     if (extraData.Find(10))
     {
         if (extraData.ValueLength < 4)
         {
             throw new ZipException("NTFS Extra data invalid");
         }
         extraData.ReadInt();
         while (extraData.UnreadCount >= 4)
         {
             int num = extraData.ReadShort();
             int amount = extraData.ReadShort();
             if (num == 1)
             {
                 if (amount >= 0x18)
                 {
                     long fileTime = extraData.ReadLong();
                     extraData.ReadLong();
                     extraData.ReadLong();
                     DateTime = DateTime.FromFileTime(fileTime);
                 }
                 break;
             }
             extraData.Skip(amount);
         }
     }
     else if (extraData.Find(0x5455))
     {
         int valueLength = extraData.ValueLength;
         if (((extraData.ReadByte() & 1) != 0) && (valueLength >= 5))
         {
             int seconds = extraData.ReadInt();
             DateTime time = new DateTime(0x7b2, 1, 1, 0, 0, 0);
             DateTime = (time.ToUniversalTime() + new TimeSpan(0, 0, 0, seconds, 0)).ToLocalTime();
         }
     }
     if (_method == CompressionMethod.WinZipAes)
     {
         ProcessAesExtraData(extraData);
     }
 }
Esempio n. 13
0
 private void ProcessAesExtraData(ZipExtraData extraData)
 {
     if (!extraData.Find(0x9901))
     {
         throw new ZipException("AES Extra Data missing");
     }
     _versionToExtract = 0x33;
     Flags |= 0x40;
     int valueLength = extraData.ValueLength;
     if (valueLength < 7)
     {
         throw new ZipException("AES Extra Data Length " + valueLength + " invalid.");
     }
     extraData.ReadShort();
     extraData.ReadShort();
     int num3 = extraData.ReadByte();
     int num4 = extraData.ReadShort();
     _aesEncryptionStrength = num3;
     _method = (CompressionMethod)num4;
 }
Esempio n. 14
0
        private void WriteLocalEntryHeader(ZipUpdate update)
        {
            var outEntry = update.OutEntry;
            outEntry.Offset = _baseStream.Position;
            if (update.Command != UpdateCommand.Copy)
            {
                if (outEntry.CompressionMethod == CompressionMethod.Deflated)
                {
                    if (outEntry.Size == 0L)
                    {
                        outEntry.CompressedSize = outEntry.Size;
                        outEntry.Crc = 0L;
                        outEntry.CompressionMethod = CompressionMethod.Stored;
                    }
                }
                else if (outEntry.CompressionMethod == CompressionMethod.Stored)
                {
                    outEntry.Flags &= -9;
                }
                if (HaveKeys)
                {
                    outEntry.IsCrypted = true;
                    if (outEntry.Crc < 0L)
                    {
                        outEntry.Flags |= 8;
                    }
                }
                else
                {
                    outEntry.IsCrypted = false;
                }
                switch (_useZip64)
                {
                    case UseZip64.On:
                        outEntry.ForceZip64();
                        break;

                    case UseZip64.Dynamic:
                        if (outEntry.Size < 0L)
                        {
                            outEntry.ForceZip64();
                        }
                        break;
                }
            }
            WriteLeInt(ZipConstants.LocalHeaderSignature);
            WriteLeShort(outEntry.Version);
            WriteLeShort(outEntry.Flags);
            WriteLeShort((byte)outEntry.CompressionMethod);
            WriteLeInt((int)outEntry.DosTime);
            if (!outEntry.HasCrc)
            {
                update.CrcPatchOffset = _baseStream.Position;
                WriteLeInt(0);
            }
            else
            {
                WriteLeInt((int)outEntry.Crc);
            }
            if (outEntry.LocalHeaderRequiresZip64)
            {
                WriteLeInt(-1);
                WriteLeInt(-1);
            }
            else
            {
                if ((outEntry.CompressedSize < 0L) || (outEntry.Size < 0L))
                {
                    update.SizePatchOffset = _baseStream.Position;
                }
                WriteLeInt((int)outEntry.CompressedSize);
                WriteLeInt((int)outEntry.Size);
            }
            var buffer = ZipConstants.ConvertToArray(outEntry.Flags, outEntry.Name);
            if (buffer.Length > 0xffff)
            {
                throw new ZipException("Entry name too long.");
            }
            var data = new ZipExtraData(outEntry.ExtraData);
            if (outEntry.LocalHeaderRequiresZip64)
            {
                data.StartNewEntry();
                data.AddLeLong(outEntry.Size);
                data.AddLeLong(outEntry.CompressedSize);
                data.AddNewEntry(1);
            }
            else
            {
                data.Delete(1);
            }
            outEntry.ExtraData = data.GetEntryData();
            WriteLeShort(buffer.Length);
            WriteLeShort(outEntry.ExtraData.Length);
            if (buffer.Length > 0)
            {
                _baseStream.Write(buffer, 0, buffer.Length);
            }
            if (outEntry.LocalHeaderRequiresZip64)
            {
                if (!data.Find(1))
                {
                    throw new ZipException("Internal error cannot find extra data");
                }
                update.SizePatchOffset = _baseStream.Position + data.CurrentReadIndex;
            }
            if (outEntry.ExtraData.Length > 0)
            {
                _baseStream.Write(outEntry.ExtraData, 0, outEntry.ExtraData.Length);
            }
        }
Esempio n. 15
0
 public void PutNextEntry(ZipEntry entry)
 {
     bool hasCrc;
     if (entry == null)
     {
         throw new ArgumentNullException(nameof(entry));
     }
     if (_entries == null)
     {
         throw new InvalidOperationException("ZipOutputStream was finished");
     }
     if (_curEntry != null)
     {
         CloseEntry();
     }
     if (_entries.Count == 0x7fffffff)
     {
         throw new ZipException("Too many entries for Zip file");
     }
     CompressionMethod compressionMethod = entry.CompressionMethod;
     int compressionLevel = _defaultCompressionLevel;
     entry.Flags &= 0x800;
     _patchEntryHeader = false;
     if (entry.Size == 0L)
     {
         entry.CompressedSize = entry.Size;
         entry.Crc = 0L;
         compressionMethod = CompressionMethod.Stored;
         hasCrc = true;
     }
     else
     {
         hasCrc = (entry.Size >= 0L) && entry.HasCrc;
         if (compressionMethod == CompressionMethod.Stored)
         {
             if (!hasCrc)
             {
                 if (!CanPatchEntries)
                 {
                     compressionMethod = CompressionMethod.Deflated;
                     compressionLevel = 0;
                 }
             }
             else
             {
                 entry.CompressedSize = entry.Size;
                 hasCrc = entry.HasCrc;
             }
         }
     }
     if (!hasCrc)
     {
         if (!CanPatchEntries)
         {
             entry.Flags |= 8;
         }
         else
         {
             _patchEntryHeader = true;
         }
     }
     if (Password != null)
     {
         entry.IsCrypted = true;
         if (entry.Crc < 0L)
         {
             entry.Flags |= 8;
         }
     }
     entry.Offset = _offset;
     entry.CompressionMethod = compressionMethod;
     _curMethod = compressionMethod;
     _sizePatchPos = -1L;
     if ((_useZip64 == UseZip64.On) || ((entry.Size < 0L) && (_useZip64 == UseZip64.Dynamic)))
     {
         entry.ForceZip64();
     }
     WriteLeInt(ZipConstants.LocalHeaderSignature);
     WriteLeShort(entry.Version);
     WriteLeShort(entry.Flags);
     WriteLeShort((byte)entry.CompressionMethodForHeader);
     WriteLeInt((int)entry.DosTime);
     if (hasCrc)
     {
         WriteLeInt((int)entry.Crc);
         if (entry.LocalHeaderRequiresZip64)
         {
             WriteLeInt(-1);
             WriteLeInt(-1);
         }
         else
         {
             WriteLeInt(entry.IsCrypted ? (((int)entry.CompressedSize) + 12) : ((int)entry.CompressedSize));
             WriteLeInt((int)entry.Size);
         }
     }
     else
     {
         if (_patchEntryHeader)
         {
             _crcPatchPos = BaseOutputStream.Position;
         }
         WriteLeInt(0);
         if (_patchEntryHeader)
         {
             _sizePatchPos = BaseOutputStream.Position;
         }
         if (entry.LocalHeaderRequiresZip64 || _patchEntryHeader)
         {
             WriteLeInt(-1);
             WriteLeInt(-1);
         }
         else
         {
             WriteLeInt(0);
             WriteLeInt(0);
         }
     }
     byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
     if (buffer.Length > 0xffff)
     {
         throw new ZipException("Entry name too long.");
     }
     ZipExtraData extraData = new ZipExtraData(entry.ExtraData);
     if (entry.LocalHeaderRequiresZip64)
     {
         extraData.StartNewEntry();
         if (hasCrc)
         {
             extraData.AddLeLong(entry.Size);
             extraData.AddLeLong(entry.CompressedSize);
         }
         else
         {
             extraData.AddLeLong(-1L);
             extraData.AddLeLong(-1L);
         }
         extraData.AddNewEntry(1);
         if (!extraData.Find(1))
         {
             throw new ZipException("Internal error cant find extra data");
         }
         if (_patchEntryHeader)
         {
             _sizePatchPos = extraData.CurrentReadIndex;
         }
     }
     else
     {
         extraData.Delete(1);
     }
     if (entry.AesKeySize > 0)
     {
         AddExtraDataAes(entry, extraData);
     }
     byte[] entryData = extraData.GetEntryData();
     WriteLeShort(buffer.Length);
     WriteLeShort(entryData.Length);
     if (buffer.Length > 0)
     {
         BaseOutputStream.Write(buffer, 0, buffer.Length);
     }
     if (entry.LocalHeaderRequiresZip64 && _patchEntryHeader)
     {
         _sizePatchPos += BaseOutputStream.Position;
     }
     if (entryData.Length > 0)
     {
         BaseOutputStream.Write(entryData, 0, entryData.Length);
     }
     _offset += (30 + buffer.Length) + entryData.Length;
     if (entry.AesKeySize > 0)
     {
         _offset += entry.AesOverheadSize;
     }
     _curEntry = entry;
     _crc.Reset();
     if (compressionMethod == CompressionMethod.Deflated)
     {
         Deflater.Reset();
         Deflater.SetLevel(compressionLevel);
     }
     _size = 0L;
     if (entry.IsCrypted)
     {
         if (entry.AesKeySize > 0)
         {
             WriteAesHeader(entry);
         }
         else if (entry.Crc < 0L)
         {
             WriteEncryptionHeader(entry.DosTime << 0x10);
         }
         else
         {
             WriteEncryptionHeader(entry.Crc);
         }
     }
 }
Esempio n. 16
0
        public void PutNextEntry(ZipEntry entry)
        {
            bool hasCrc;

            if (entry == null)
            {
                throw new ArgumentNullException(nameof(entry));
            }
            if (_entries == null)
            {
                throw new InvalidOperationException("ZipOutputStream was finished");
            }
            if (_curEntry != null)
            {
                CloseEntry();
            }
            if (_entries.Count == 0x7fffffff)
            {
                throw new ZipException("Too many entries for Zip file");
            }
            CompressionMethod compressionMethod = entry.CompressionMethod;
            int compressionLevel = _defaultCompressionLevel;

            entry.Flags      &= 0x800;
            _patchEntryHeader = false;
            if (entry.Size == 0L)
            {
                entry.CompressedSize = entry.Size;
                entry.Crc            = 0L;
                compressionMethod    = CompressionMethod.Stored;
                hasCrc = true;
            }
            else
            {
                hasCrc = (entry.Size >= 0L) && entry.HasCrc;
                if (compressionMethod == CompressionMethod.Stored)
                {
                    if (!hasCrc)
                    {
                        if (!CanPatchEntries)
                        {
                            compressionMethod = CompressionMethod.Deflated;
                            compressionLevel  = 0;
                        }
                    }
                    else
                    {
                        entry.CompressedSize = entry.Size;
                        hasCrc = entry.HasCrc;
                    }
                }
            }
            if (!hasCrc)
            {
                if (!CanPatchEntries)
                {
                    entry.Flags |= 8;
                }
                else
                {
                    _patchEntryHeader = true;
                }
            }
            if (Password != null)
            {
                entry.IsCrypted = true;
                if (entry.Crc < 0L)
                {
                    entry.Flags |= 8;
                }
            }
            entry.Offset            = _offset;
            entry.CompressionMethod = compressionMethod;
            _curMethod    = compressionMethod;
            _sizePatchPos = -1L;
            if ((_useZip64 == UseZip64.On) || ((entry.Size < 0L) && (_useZip64 == UseZip64.Dynamic)))
            {
                entry.ForceZip64();
            }
            WriteLeInt(ZipConstants.LocalHeaderSignature);
            WriteLeShort(entry.Version);
            WriteLeShort(entry.Flags);
            WriteLeShort((byte)entry.CompressionMethodForHeader);
            WriteLeInt((int)entry.DosTime);
            if (hasCrc)
            {
                WriteLeInt((int)entry.Crc);
                if (entry.LocalHeaderRequiresZip64)
                {
                    WriteLeInt(-1);
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt(entry.IsCrypted ? (((int)entry.CompressedSize) + 12) : ((int)entry.CompressedSize));
                    WriteLeInt((int)entry.Size);
                }
            }
            else
            {
                if (_patchEntryHeader)
                {
                    _crcPatchPos = BaseOutputStream.Position;
                }
                WriteLeInt(0);
                if (_patchEntryHeader)
                {
                    _sizePatchPos = BaseOutputStream.Position;
                }
                if (entry.LocalHeaderRequiresZip64 || _patchEntryHeader)
                {
                    WriteLeInt(-1);
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt(0);
                    WriteLeInt(0);
                }
            }
            byte[] buffer = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
            if (buffer.Length > 0xffff)
            {
                throw new ZipException("Entry name too long.");
            }
            ZipExtraData extraData = new ZipExtraData(entry.ExtraData);

            if (entry.LocalHeaderRequiresZip64)
            {
                extraData.StartNewEntry();
                if (hasCrc)
                {
                    extraData.AddLeLong(entry.Size);
                    extraData.AddLeLong(entry.CompressedSize);
                }
                else
                {
                    extraData.AddLeLong(-1L);
                    extraData.AddLeLong(-1L);
                }
                extraData.AddNewEntry(1);
                if (!extraData.Find(1))
                {
                    throw new ZipException("Internal error cant find extra data");
                }
                if (_patchEntryHeader)
                {
                    _sizePatchPos = extraData.CurrentReadIndex;
                }
            }
            else
            {
                extraData.Delete(1);
            }
            if (entry.AesKeySize > 0)
            {
                AddExtraDataAes(entry, extraData);
            }
            byte[] entryData = extraData.GetEntryData();
            WriteLeShort(buffer.Length);
            WriteLeShort(entryData.Length);
            if (buffer.Length > 0)
            {
                BaseOutputStream.Write(buffer, 0, buffer.Length);
            }
            if (entry.LocalHeaderRequiresZip64 && _patchEntryHeader)
            {
                _sizePatchPos += BaseOutputStream.Position;
            }
            if (entryData.Length > 0)
            {
                BaseOutputStream.Write(entryData, 0, entryData.Length);
            }
            _offset += (30 + buffer.Length) + entryData.Length;
            if (entry.AesKeySize > 0)
            {
                _offset += entry.AesOverheadSize;
            }
            _curEntry = entry;
            _crc.Reset();
            if (compressionMethod == CompressionMethod.Deflated)
            {
                Deflater.Reset();
                Deflater.SetLevel(compressionLevel);
            }
            _size = 0L;
            if (entry.IsCrypted)
            {
                if (entry.AesKeySize > 0)
                {
                    WriteAesHeader(entry);
                }
                else if (entry.Crc < 0L)
                {
                    WriteEncryptionHeader(entry.DosTime << 0x10);
                }
                else
                {
                    WriteEncryptionHeader(entry.Crc);
                }
            }
        }
Esempio n. 17
0
        /// <summary>
        /// Starts a new Zip entry. It automatically closes the previous
        /// entry if present.
        /// All entry elements bar name are optional, but must be correct if present.
        /// If the compression method is stored and the output is not patchable
        /// the compression for that entry is automatically changed to deflate level 0
        /// </summary>
        /// <param name="entry">
        /// the entry.
        /// </param>
        /// <exception cref="System.ArgumentNullException">
        /// if entry passed is null.
        /// </exception>
        /// <exception cref="System.IO.IOException">
        /// if an I/O error occured.
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// if stream was finished
        /// </exception>
        /// <exception cref="ZipException">
        /// Too many entries in the Zip file<br/>
        /// Entry name is too long<br/>
        /// Finish has already been called<br/>
        /// </exception>
        public void PutNextEntry(ZipEntry entry)
        {
            if (entry == null)
            {
                throw new ArgumentNullException("entry");
            }

            if (entries == null)
            {
                throw new InvalidOperationException("ZipOutputStream was finished");
            }

            if (curEntry != null)
            {
                CloseEntry();
            }

            if (entries.Count == int.MaxValue)
            {
                throw new ZipException("Too many entries for Zip file");
            }

            CompressionMethod method = entry.CompressionMethod;
            int compressionLevel     = defaultCompressionLevel;

            // Clear flags that the library manages internally
            entry.Flags     &= (int)GeneralBitFlags.UnicodeText;
            patchEntryHeader = false;
            bool headerInfoAvailable = true;

            if (method == CompressionMethod.Stored)
            {
                // Cant store values in a data descriptor as you cant extract stored files
                // if the length isnt known.
                entry.Flags &= ~8;
                if (entry.CompressedSize >= 0)
                {
                    if (entry.Size < 0)
                    {
                        entry.Size = entry.CompressedSize;
                    }
                    else if (entry.Size != entry.CompressedSize)
                    {
                        throw new ZipException("Method STORED, but compressed size != size");
                    }
                }
                else
                {
                    if (entry.Size >= 0)
                    {
                        entry.CompressedSize = entry.Size;
                    }
                }

                if (entry.Size < 0 || entry.Crc < 0)
                {
                    if (CanPatchEntries == true)
                    {
                        headerInfoAvailable = false;
                    }
                    else
                    {
                        // Can't patch entries so storing is not possible.
                        method           = CompressionMethod.Deflated;
                        compressionLevel = 0;
                    }
                }
            }

            if (method == CompressionMethod.Deflated)
            {
                if (entry.Size == 0)
                {
                    // No need to compress - no data.
                    entry.CompressedSize = entry.Size;
                    entry.Crc            = 0;
                    method = CompressionMethod.Stored;
                }
                else if ((entry.CompressedSize < 0) || (entry.Size < 0) || (entry.Crc < 0))
                {
                    headerInfoAvailable = false;
                }
            }

            if (headerInfoAvailable == false)
            {
                if (CanPatchEntries == false)
                {
                    // Only way to record size and compressed size is to append a data descriptor
                    // after compressed data.
                    entry.Flags |= 8;
                }
                else
                {
                    patchEntryHeader = true;
                }
            }

            if (Password != null)
            {
                entry.IsCrypted = true;
                if (entry.Crc < 0)
                {
                    // Need to append a data descriptor as the crc isnt available for use
                    // with encryption, the date is used instead.  Setting the flag
                    // indicates this to the decompressor.
                    entry.Flags |= 8;
                }
            }

            entry.Offset            = offset;
            entry.CompressionMethod = (CompressionMethod)method;

            curMethod = method;

            if ((useZip64_ == UseZip64.On) || ((entry.Size < 0) && (useZip64_ == UseZip64.Dynamic)))
            {
                entry.ForceZip64();
            }

            // Write the local file header
            WriteLeInt(ZipConstants.LocalHeaderSignature);

            WriteLeShort(entry.Version);
            WriteLeShort(entry.Flags);
            WriteLeShort((byte)method);
            WriteLeInt((int)entry.DosTime);

            // TODO: Refactor header writing.  Its done in several places.
            if (headerInfoAvailable == true)
            {
                WriteLeInt((int)entry.Crc);
                if (entry.LocalHeaderRequiresZip64)
                {
                    WriteLeInt(-1);
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize);
                    WriteLeInt((int)entry.Size);
                }
            }
            else
            {
                if (patchEntryHeader == true)
                {
                    crcPatchPos = baseOutputStream.Position;
                }
                WriteLeInt(0);                  // Crc

                if (patchEntryHeader)
                {
                    sizePatchPos = baseOutputStream.Position;
                }

                // For local header both sizes appear in Zip64 Extended Information
                if (entry.LocalHeaderRequiresZip64)
                {
                    WriteLeInt(-1);
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt(0);                      // Compressed size
                    WriteLeInt(0);                      // Uncompressed size
                }
            }

            byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);

            if (name.Length > 0xFFFF)
            {
                throw new ZipException("Entry name too long.");
            }

            ZipExtraData ed = new ZipExtraData(entry.ExtraData);

            if (entry.LocalHeaderRequiresZip64)
            {
                ed.StartNewEntry();
                ed.AddLeLong(-1);
                ed.AddLeLong(-1);
                ed.AddNewEntry(1);

                if (!ed.Find(1))
                {
                    throw new ZipException("Internal error cant find extra data");
                }

                if (patchEntryHeader)
                {
                    sizePatchPos = ed.CurrentReadIndex;
                }
            }
            else
            {
                ed.Delete(1);
            }

            byte[] extra = ed.GetEntryData();

            WriteLeShort(name.Length);
            WriteLeShort(extra.Length);

            if (name.Length > 0)
            {
                baseOutputStream.Write(name, 0, name.Length);
            }

            if (entry.LocalHeaderRequiresZip64 && patchEntryHeader)
            {
                sizePatchPos += baseOutputStream.Position;
            }

            if (extra.Length > 0)
            {
                baseOutputStream.Write(extra, 0, extra.Length);
            }

            offset += ZipConstants.LocalHeaderBaseSize + name.Length + extra.Length;

            // Activate the entry.
            curEntry = entry;
            crc.Reset();
            if (method == CompressionMethod.Deflated)
            {
                def.Reset();
                def.SetLevel(compressionLevel);
            }
            size = 0;

            if (entry.IsCrypted == true)
            {
                if (entry.Crc < 0)                                      // so testing Zip will says its ok
                {
                    WriteEncryptionHeader(entry.DosTime << 16);
                }
                else
                {
                    WriteEncryptionHeader(entry.Crc);
                }
            }
        }
Esempio n. 18
0
		/// <summary>
		/// Finishes the stream.  This will write the central directory at the
		/// end of the zip file and flush the stream.
		/// </summary>
		/// <remarks>
		/// This is automatically called when the stream is closed.
		/// </remarks>
		/// <exception cref="System.IO.IOException">
		/// An I/O error occurs.
		/// </exception>
		/// <exception cref="ZipException">
		/// Comment exceeds the maximum length<br/>
		/// Entry name exceeds the maximum length
		/// </exception>
		public override void Finish()
		{
			if (entries == null)  {
				return;
			}
			
			if (curEntry != null) {
				CloseEntry();
			}
			
			long numEntries = entries.Count;
			long sizeEntries = 0;
			
			foreach (ZipEntry entry in entries) {
				WriteLeInt(ZipConstants.CentralHeaderSignature); 
				WriteLeShort(ZipConstants.VersionMadeBy);
				WriteLeShort(entry.Version);
				WriteLeShort(entry.Flags);
				WriteLeShort((short)entry.CompressionMethod);
				WriteLeInt((int)entry.DosTime);
				WriteLeInt((int)entry.Crc);

				if ( entry.IsZip64Forced() || 
					(entry.CompressedSize >= uint.MaxValue) )
				{
					WriteLeInt(-1);
				}
				else {
					WriteLeInt((int)entry.CompressedSize);
				}

				if ( entry.IsZip64Forced() ||
					(entry.Size >= uint.MaxValue) )
				{
					WriteLeInt(-1);
				}
				else {
					WriteLeInt((int)entry.Size);
				}

				byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
				
				if (name.Length > 0xffff) {
					throw new ZipException("Name too long.");
				}
				
				ZipExtraData ed = new ZipExtraData(entry.ExtraData);

				if ( entry.CentralHeaderRequiresZip64 ) {
					ed.StartNewEntry();
					if ( entry.IsZip64Forced() ||
						(entry.Size >= 0xffffffff) )
					{
						ed.AddLeLong(entry.Size);
					}

					if ( entry.IsZip64Forced() ||
						(entry.CompressedSize >= 0xffffffff) )
					{
						ed.AddLeLong(entry.CompressedSize);
					}

					if ( entry.Offset >= 0xffffffff )
					{
						ed.AddLeLong(entry.Offset);
					}

					ed.AddNewEntry(1);
				}
				else {
					ed.Delete(1);
				}

				byte[] extra = ed.GetEntryData();
				
				byte[] entryComment = 
					(entry.Comment != null) ? 
					ZipConstants.ConvertToArray(entry.Flags, entry.Comment) :
					new byte[0];

				if (entryComment.Length > 0xffff) {
					throw new ZipException("Comment too long.");
				}
				
				WriteLeShort(name.Length);
				WriteLeShort(extra.Length);
				WriteLeShort(entryComment.Length);
				WriteLeShort(0);	// disk number
				WriteLeShort(0);	// internal file attributes
									// external file attributes

				if (entry.ExternalFileAttributes != -1) {
					WriteLeInt(entry.ExternalFileAttributes);
				} else {
					if (entry.IsDirectory) {                         // mark entry as directory (from nikolam.AT.perfectinfo.com)
						WriteLeInt(16);
					} else {
						WriteLeInt(0);
					}
				}

				if ( entry.Offset >= uint.MaxValue ) {
					WriteLeInt(-1);
				}
				else {
					WriteLeInt((int)entry.Offset);
				}
				
				if ( name.Length > 0 ) {
					baseOutputStream_.Write(name,    0, name.Length);
				}

				if ( extra.Length > 0 ) {
					baseOutputStream_.Write(extra,   0, extra.Length);
				}

				if ( entryComment.Length > 0 ) {
					baseOutputStream_.Write(entryComment, 0, entryComment.Length);
				}

				sizeEntries += ZipConstants.CentralHeaderBaseSize + name.Length + extra.Length + entryComment.Length;
			}
			
			using ( ZipHelperStream zhs = new ZipHelperStream(baseOutputStream_) ) {
				zhs.WriteEndOfCentralDirectory(numEntries, sizeEntries, offset, zipComment);
			}

			entries = null;
		}
Esempio n. 19
0
        /// <summary>
        /// Finishes the stream.  This will write the central directory at the
        /// end of the zip file and flush the stream.
        /// </summary>
        /// <remarks>
        /// This is automatically called when the stream is closed.
        /// </remarks>
        /// <exception cref="System.IO.IOException">
        /// An I/O error occurs.
        /// </exception>
        /// <exception cref="ZipException">
        /// Comment exceeds the maximum length<br/>
        /// Entry name exceeds the maximum length
        /// </exception>
        public override void Finish()
        {
            if (entries == null)
            {
                return;
            }

            if (curEntry != null)
            {
                CloseEntry();
            }

            long numEntries  = entries.Count;
            long sizeEntries = 0;

            foreach (ZipEntry entry in entries)
            {
                WriteLeInt(ZipConstants.CentralHeaderSignature);
                WriteLeShort(ZipConstants.VersionMadeBy);
                WriteLeShort(entry.Version);
                WriteLeShort(entry.Flags);
                WriteLeShort((short)entry.CompressionMethod);
                WriteLeInt((int)entry.DosTime);
                WriteLeInt((int)entry.Crc);

                if (entry.IsZip64Forced() ||
                    (entry.CompressedSize >= uint.MaxValue))
                {
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt((int)entry.CompressedSize);
                }

                if (entry.IsZip64Forced() ||
                    (entry.Size >= uint.MaxValue))
                {
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt((int)entry.Size);
                }

                byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);

                if (name.Length > 0xffff)
                {
                    throw new ZipException("Name too long.");
                }

                ZipExtraData ed = new ZipExtraData(entry.ExtraData);

                if (entry.CentralHeaderRequiresZip64)
                {
                    ed.StartNewEntry();
                    if (entry.IsZip64Forced() ||
                        (entry.Size >= 0xffffffff))
                    {
                        ed.AddLeLong(entry.Size);
                    }

                    if (entry.IsZip64Forced() ||
                        (entry.CompressedSize >= 0xffffffff))
                    {
                        ed.AddLeLong(entry.CompressedSize);
                    }

                    if (entry.Offset >= 0xffffffff)
                    {
                        ed.AddLeLong(entry.Offset);
                    }

                    ed.AddNewEntry(1);
                }
                else
                {
                    ed.Delete(1);
                }

                byte[] extra = ed.GetEntryData();

                byte[] entryComment =
                    (entry.Comment != null) ?
                    ZipConstants.ConvertToArray(entry.Flags, entry.Comment) :
                    new byte[0];

                if (entryComment.Length > 0xffff)
                {
                    throw new ZipException("Comment too long.");
                }

                WriteLeShort(name.Length);
                WriteLeShort(extra.Length);
                WriteLeShort(entryComment.Length);
                WriteLeShort(0);                        // disk number
                WriteLeShort(0);                        // internal file attributes
                // external file attributes

                if (entry.ExternalFileAttributes != -1)
                {
                    WriteLeInt(entry.ExternalFileAttributes);
                }
                else
                {
                    if (entry.IsDirectory)                                               // mark entry as directory (from nikolam.AT.perfectinfo.com)
                    {
                        WriteLeInt(16);
                    }
                    else
                    {
                        WriteLeInt(0);
                    }
                }

                if (entry.Offset >= uint.MaxValue)
                {
                    WriteLeInt(-1);
                }
                else
                {
                    WriteLeInt((int)entry.Offset);
                }

                if (name.Length > 0)
                {
                    baseOutputStream.Write(name, 0, name.Length);
                }

                if (extra.Length > 0)
                {
                    baseOutputStream.Write(extra, 0, extra.Length);
                }

                if (entryComment.Length > 0)
                {
                    baseOutputStream.Write(entryComment, 0, entryComment.Length);
                }

                sizeEntries += ZipConstants.CentralHeaderBaseSize + name.Length + extra.Length + entryComment.Length;
            }

            using (ZipHelperStream zhs = new ZipHelperStream(baseOutputStream)) {
                zhs.WriteEndOfCentralDirectory(numEntries, sizeEntries, offset, zipComment);
            }

            entries = null;
        }
Esempio n. 20
0
        /// <summary>
        /// Test a local header against that provided from the central directory
        /// </summary>
        /// <param name="entry">
        /// The entry to test against
        /// </param>
        /// <param name="tests">The type of <see cref="HeaderTest">tests</see> to carry out.</param>
        /// <returns>The offset of the entries data in the file</returns>
        long TestLocalHeader(ZipEntry entry, HeaderTest tests)
        {
            lock(baseStream_)
            {
                bool testHeader = (tests & HeaderTest.Header) != 0;
                bool testData = (tests & HeaderTest.Extract) != 0;

                baseStream_.Seek(offsetOfFirstEntry + entry.Offset, SeekOrigin.Begin);
                if ((int)ReadLEUint() != ZipConstants.LocalHeaderSignature) {
                    throw new ZipException(string.Format("Wrong local header signature @{0:X}", offsetOfFirstEntry + entry.Offset));
                }

                short extractVersion = ( short )ReadLEUshort();
                short localFlags = ( short )ReadLEUshort();
                short compressionMethod = ( short )ReadLEUshort();
                short fileTime = ( short )ReadLEUshort();
                short fileDate = ( short )ReadLEUshort();
                uint crcValue = ReadLEUint();
                long size = ReadLEUint();
                long compressedSize = ReadLEUint();
                int storedNameLength = ReadLEUshort();
                int extraDataLength = ReadLEUshort();

                // eliminate system id from version (use version only)
                extractVersion &= 0x00FF;

                if ( testData ) {
                    if ( entry.IsFile ) {
                        if ( !entry.IsCompressionMethodSupported() ) {
                            throw new ZipException("Compression method not supported");
                        }

                        if ( (extractVersion > ZipConstants.VersionMadeBy)
                            || ((extractVersion > 20) && (extractVersion < ZipConstants.VersionZip64)) ) {
                            throw new ZipException(string.Format("Version required to extract this entry not supported ({0})", extractVersion));
                        }

                        if ( (localFlags & ( int )(GeneralBitFlags.Patched | GeneralBitFlags.StrongEncryption | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked)) != 0 ) {
                            throw new ZipException("The library does not support the zip version required to extract this entry");
                        }
                    }
                }

                if ( testHeader ) {
                    if ((extractVersion <= 63) &&	// Ignore later versions as we dont know about them..
                        (extractVersion != 10) &&
                        (extractVersion != 11) &&
                        (extractVersion != 20) &&
                        (extractVersion != 21) &&
                        (extractVersion != 25) &&
                        (extractVersion != 27) &&
                        (extractVersion != 45) &&
                        (extractVersion != 46) &&
                        (extractVersion != 50) &&
                        (extractVersion != 51) &&
                        (extractVersion != 52) &&
                        (extractVersion != 61) &&
                        (extractVersion != 62) &&
                        (extractVersion != 63)
                        ) {
                        throw new ZipException(string.Format("Version required to extract this entry is invalid ({0})", extractVersion));
                    }

                    // Local entry flags dont have reserved bit set on.
                    if ( (localFlags & ( int )(GeneralBitFlags.ReservedPKware4 | GeneralBitFlags.ReservedPkware14 | GeneralBitFlags.ReservedPkware15)) != 0 ) {
                        throw new ZipException("Reserved bit flags cannot be set.");
                    }

                    // Encryption requires extract version >= 20
                    if ( ((localFlags & ( int )GeneralBitFlags.Encrypted) != 0) && (extractVersion < 20) ) {
                        throw new ZipException(string.Format("Version required to extract this entry is too low for encryption ({0})", extractVersion));
                    }

                    // Strong encryption requires encryption flag to be set and extract version >= 50.
                    if ( (localFlags & (int)GeneralBitFlags.StrongEncryption) != 0 ) {
                        if ( (localFlags & (int)GeneralBitFlags.Encrypted) == 0 ) {
                            throw new ZipException("Strong encryption flag set but encryption flag is not set");
                        }

                        if ( extractVersion < 50 ) {
                            throw new ZipException(string.Format("Version required to extract this entry is too low for encryption ({0})", extractVersion));
                        }
                    }

                    // Patched entries require extract version >= 27
                    if ( ((localFlags & ( int )GeneralBitFlags.Patched) != 0) && (extractVersion < 27) ) {
                        throw new ZipException(string.Format("Patched data requires higher version than ({0})", extractVersion));
                    }

                    // Central header flags match local entry flags.
                    if ( localFlags != entry.Flags ) {
                        throw new ZipException("Central header/local header flags mismatch");
                    }

                    // Central header compression method matches local entry
                    if ( entry.CompressionMethod != ( CompressionMethod )compressionMethod ) {
                        throw new ZipException("Central header/local header compression method mismatch");
                    }

                    // Strong encryption and extract version match
                    if ( (localFlags & ( int )GeneralBitFlags.StrongEncryption) != 0 ) {
                        if ( extractVersion < 62 ) {
                            throw new ZipException("Strong encryption flag set but version not high enough");
                        }
                    }

                    if ( (localFlags & ( int )GeneralBitFlags.HeaderMasked) != 0 ) {
                        if ( (fileTime != 0) || (fileDate != 0) ) {
                            throw new ZipException("Header masked set but date/time values non-zero");
                        }
                    }

                    if ( (localFlags & ( int )GeneralBitFlags.Descriptor) == 0 ) {
                        if ( crcValue != (uint)entry.Crc ) {
                            throw new ZipException("Central header/local header crc mismatch");
                        }
                    }

                    // Crc valid for empty entry.
                    if ( (size == 0) && (compressedSize == 0) ) {
                        if ( crcValue != 0 ) {
                            throw new ZipException("Invalid CRC for empty entry");
                        }
                    }

                    // TODO: make test more correct...  can't compare lengths as was done originally as this can fail for MBCS strings
                    // Assuming a code page at this point is not valid?  Best is to store the name length in the ZipEntry probably
                    if ( entry.Name.Length > storedNameLength ) {
                        throw new ZipException("File name length mismatch");
                    }

                    byte[] nameData = new byte[storedNameLength];
                    StreamUtils.ReadFully(baseStream_, nameData);

                    string localName = ZipConstants.ConvertToStringExt(localFlags, nameData);

                    // Central directory and local entry name match
                    if ( localName != entry.Name ) {
                        throw new ZipException("Central header and local header file name mismatch");
                    }

                    // Directories have zero size.
                    if ( entry.IsDirectory ) {
                        if ( (compressedSize != 0) || (size != 0) ) {
                            throw new ZipException("Directory cannot have size");
                        }
                    }

                    if ( !ZipNameTransform.IsValidName(localName, true) ) {
                        throw new ZipException("Name is invalid");
                    }

                    byte[] data = new byte[extraDataLength];
                    StreamUtils.ReadFully(baseStream_, data);
                    ZipExtraData ed = new ZipExtraData(data);

                    // Extra data / zip64 checks
                    if ( ed.Find(1) ) {
                        // Zip64 extra data but 'extract version' is too low
                        if ( extractVersion < ZipConstants.VersionZip64 ) {
                            throw new ZipException(
                                string.Format("Extra data contains Zip64 information but version {0}.{1} is not high enough",
                                extractVersion / 10, extractVersion % 10));
                        }

                        // Zip64 extra data but size fields dont indicate its required.
                        if ( (( uint )size != uint.MaxValue) && (( uint )compressedSize != uint.MaxValue) ) {
                            throw new ZipException("Entry sizes not correct for Zip64");
                        }

                        size = ed.ReadLong();
                        compressedSize = ed.ReadLong();
                    }
                    else {
                        // No zip64 extra data but entry requires it.
                        if ( (extractVersion >= ZipConstants.VersionZip64) &&
                            ((( uint )size == uint.MaxValue) || (( uint )compressedSize == uint.MaxValue)) ) {
                            throw new ZipException("Required Zip64 extended information missing");
                        }
                    }
                }

                int extraLength = storedNameLength + extraDataLength;
                return offsetOfFirstEntry + entry.Offset + ZipConstants.LocalHeaderBaseSize + extraLength;
            }
        }
Esempio n. 21
0
		/// <summary>
		/// Process extra data fields updating the entry based on the contents.
		/// </summary>
		/// <param name="localHeader">True if the extra data fields should be handled
		/// for a local header, rather than for a central header.
		/// </param>
		internal void ProcessExtraData(bool localHeader)
		{
			ZipExtraData extraData = new ZipExtraData(this.extra);

			if ( extraData.Find(0x0001) ) {
				if ( (versionToExtract & 0xff) < ZipConstants.VersionZip64 ) {
					throw new ZipException("Zip64 Extended information found but version is not valid");
				}

				// The recorded size will change but remember that this is zip64.
				forceZip64_ = true;

				if ( extraData.ValueLength < 4 ) {
					throw new ZipException("Extra data extended Zip64 information length is invalid");
				}

				if ( localHeader || (size == uint.MaxValue) ) {
					size = (ulong)extraData.ReadLong();
				}

				if ( localHeader || (compressedSize == uint.MaxValue) ) {
					compressedSize = (ulong)extraData.ReadLong();
				}

				if ( !localHeader && (offset == uint.MaxValue) ) {
					offset = extraData.ReadLong();
				}
			}
			else {
				if ( 
					((versionToExtract & 0xff) >= ZipConstants.VersionZip64) &&
					((size == uint.MaxValue) || (compressedSize == uint.MaxValue))
				) {
					throw new ZipException("Zip64 Extended information required but is missing.");
				}
			}

			if ( extraData.Find(10) ) {
				// No room for any tags.
				if ( extraData.ValueLength < 8 ) {
					throw new ZipException("NTFS Extra data invalid");
				}

				extraData.ReadInt(); // Reserved

				while ( extraData.UnreadCount >= 4 ) {
					int ntfsTag = extraData.ReadShort();
					int ntfsLength = extraData.ReadShort();
					if ( ntfsTag == 1 ) {
						if ( ntfsLength >= 24 ) {
							long lastModification = extraData.ReadLong();
							long lastAccess = extraData.ReadLong();
							long createTime = extraData.ReadLong();

							DateTime = System.DateTime.FromFileTime(lastModification);
						}
						break;
					}
					else {
						// An unknown NTFS tag so simply skip it.
						extraData.Skip(ntfsLength);
					}
				}
			}
			else if ( extraData.Find(0x5455) ) {
				int length = extraData.ValueLength;	
				int flags = extraData.ReadByte();
					
				// Can include other times but these are ignored.  Length of data should
				// actually be 1 + 4 * no of bits in flags.
				if ( ((flags & 1) != 0) && (length >= 5) ) {
					int iTime = extraData.ReadInt();

					DateTime = (new System.DateTime ( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime() +
						new TimeSpan ( 0, 0, 0, iTime, 0 )).ToLocalTime();
				}
			}
		}
Esempio n. 22
0
        void WriteLocalEntryHeader(ZipUpdate update)
        {
            ZipEntry entry = update.OutEntry;

            // TODO: Local offset will require adjusting for multi-disk zip files.
            entry.Offset = baseStream_.Position;

            // TODO: Need to clear any entry flags that dont make sense or throw an exception here.
            if (update.Command != UpdateCommand.Copy) {
                if (entry.CompressionMethod == CompressionMethod.Deflated) {
                    if (entry.Size == 0) {
                        // No need to compress - no data.
                        entry.CompressedSize = entry.Size;
                        entry.Crc = 0;
                        entry.CompressionMethod = CompressionMethod.Stored;
                    }
                }
                else if (entry.CompressionMethod == CompressionMethod.Stored) {
                    entry.Flags &= ~(int)GeneralBitFlags.Descriptor;
                }

                if (HaveKeys) {
                    entry.IsCrypted = true;
                    if (entry.Crc < 0) {
                        entry.Flags |= (int)GeneralBitFlags.Descriptor;
                    }
                }
                else {
                    entry.IsCrypted = false;
                }

                switch (useZip64_) {
                    case UseZip64.Dynamic:
                        if (entry.Size < 0) {
                            entry.ForceZip64();
                        }
                        break;

                    case UseZip64.On:
                        entry.ForceZip64();
                        break;

                    case UseZip64.Off:
                        // Do nothing.  The entry itself may be using Zip64 independantly.
                        break;
                }
            }

            // Write the local file header
            WriteLEInt(ZipConstants.LocalHeaderSignature);

            WriteLEShort(entry.Version);
            WriteLEShort(entry.Flags);

            WriteLEShort((byte)entry.CompressionMethod);
            WriteLEInt(( int )entry.DosTime);

            if ( !entry.HasCrc ) {
                // Note patch address for updating later.
                update.CrcPatchOffset = baseStream_.Position;
                WriteLEInt(( int )0);
            }
            else
            {
                WriteLEInt(( int )entry.Crc);
            }

            if ( entry.LocalHeaderRequiresZip64 ) {
                WriteLEInt(-1);
                WriteLEInt(-1);
            }
            else {
                if ( (entry.CompressedSize < 0) || (entry.Size < 0) ) {
                    update.SizePatchOffset = baseStream_.Position;
                }

                WriteLEInt(( int )entry.CompressedSize);
                WriteLEInt(( int )entry.Size);
            }

            byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);

            if ( name.Length > 0xFFFF ) {
                throw new ZipException("Entry name too long.");
            }

            ZipExtraData ed = new ZipExtraData(entry.ExtraData);

            if ( entry.LocalHeaderRequiresZip64 ) {
                ed.StartNewEntry();

                // Local entry header always includes size and compressed size.
                // NOTE the order of these fields is reversed when compared to the headers!
                ed.AddLeLong(entry.Size);
                ed.AddLeLong(entry.CompressedSize);
                ed.AddNewEntry(1);
            }
            else {
                ed.Delete(1);
            }

            entry.ExtraData = ed.GetEntryData();

            WriteLEShort(name.Length);
            WriteLEShort(entry.ExtraData.Length);

            if ( name.Length > 0 ) {
                baseStream_.Write(name, 0, name.Length);
            }

            if ( entry.LocalHeaderRequiresZip64 ) {
                if ( !ed.Find(1) ) {
                    throw new ZipException("Internal error cannot find extra data");
                }

                update.SizePatchOffset = baseStream_.Position + ed.CurrentReadIndex;
            }

            if ( entry.ExtraData.Length > 0 ) {
                baseStream_.Write(entry.ExtraData, 0, entry.ExtraData.Length);
            }
        }
Esempio n. 23
0
		// Write the local file header
		// TODO: ZipHelperStream.WriteLocalHeader is not yet used and needs checking for ZipFile and ZipOuptutStream usage
		void WriteLocalHeader(ZipEntry entry, EntryPatchData patchData) 
		{
			CompressionMethod method = entry.CompressionMethod;
			bool headerInfoAvailable = true; // How to get this?
			bool patchEntryHeader = false;

			WriteLEInt(ZipConstants.LocalHeaderSignature);
			
			WriteLEShort(entry.Version);
			WriteLEShort(entry.Flags);
			WriteLEShort((byte)method);
			WriteLEInt((int)entry.DosTime);

			if (headerInfoAvailable == true) {
				WriteLEInt((int)entry.Crc);
				if ( entry.LocalHeaderRequiresZip64 ) {
					WriteLEInt(-1);
					WriteLEInt(-1);
				}
				else {
					WriteLEInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize);
					WriteLEInt((int)entry.Size);
				}
			} else {
				if (patchData != null) {
					patchData.CrcPatchOffset = stream_.Position;
				}
				WriteLEInt(0);	// Crc
				
				if ( patchData != null ) {
					patchData.SizePatchOffset = stream_.Position;
				}

				// For local header both sizes appear in Zip64 Extended Information
				if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) {
					WriteLEInt(-1);
					WriteLEInt(-1);
				}
				else {
					WriteLEInt(0);	// Compressed size
					WriteLEInt(0);	// Uncompressed size
				}
			}

			byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
			
			if (name.Length > 0xFFFF) {
				throw new ZipException("Entry name too long.");
			}

			ZipExtraData ed = new ZipExtraData(entry.ExtraData);

			if (entry.LocalHeaderRequiresZip64 && (headerInfoAvailable || patchEntryHeader)) {
				ed.StartNewEntry();
				if (headerInfoAvailable) {
					ed.AddLeLong(entry.Size);
					ed.AddLeLong(entry.CompressedSize);
				}
				else {
					ed.AddLeLong(-1);
					ed.AddLeLong(-1);
				}
				ed.AddNewEntry(1);

				if ( !ed.Find(1) ) {
					throw new ZipException("Internal error cant find extra data");
				}
				
				if ( patchData != null ) {
					patchData.SizePatchOffset = ed.CurrentReadIndex;
				}
			}
			else {
				ed.Delete(1);
			}
			
			byte[] extra = ed.GetEntryData();

			WriteLEShort(name.Length);
			WriteLEShort(extra.Length);

			if ( name.Length > 0 ) {
				stream_.Write(name, 0, name.Length);
			}
			
			if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) {
				patchData.SizePatchOffset += stream_.Position;
			}

			if ( extra.Length > 0 ) {
				stream_.Write(extra, 0, extra.Length);
			}
		}
Esempio n. 24
0
        public void PutNextEntry(ZipEntry entry)
        {
            if (entry == null)
            {
                throw new ArgumentNullException("entry");
            }
            if (this.entries == null)
            {
                throw new InvalidOperationException("ZipOutputStream was finished");
            }
            if (this.curEntry != null)
            {
                this.CloseEntry();
            }
            if (this.entries.Count == 2147483647)
            {
                throw new ZipException("Too many entries for Zip file");
            }
            CompressionMethod compressionMethod = entry.CompressionMethod;
            int level = this.defaultCompressionLevel;

            entry.Flags          &= 2048;
            this.patchEntryHeader = false;
            bool flag = true;

            if (compressionMethod == CompressionMethod.Stored)
            {
                entry.Flags &= -9;
                if (entry.CompressedSize >= 0L)
                {
                    if (entry.Size < 0L)
                    {
                        entry.Size = entry.CompressedSize;
                    }
                    else if (entry.Size != entry.CompressedSize)
                    {
                        throw new ZipException("Method STORED, but compressed size != size");
                    }
                }
                else if (entry.Size >= 0L)
                {
                    entry.CompressedSize = entry.Size;
                }
                if (entry.Size < 0L || entry.Crc < 0L)
                {
                    if (base.CanPatchEntries)
                    {
                        flag = false;
                    }
                    else
                    {
                        compressionMethod = CompressionMethod.Deflated;
                        level             = 0;
                    }
                }
            }
            if (compressionMethod == CompressionMethod.Deflated)
            {
                if (entry.Size == 0L)
                {
                    entry.CompressedSize = entry.Size;
                    entry.Crc            = 0L;
                    compressionMethod    = CompressionMethod.Stored;
                }
                else if (entry.CompressedSize < 0L || entry.Size < 0L || entry.Crc < 0L)
                {
                    flag = false;
                }
            }
            if (!flag)
            {
                if (!base.CanPatchEntries)
                {
                    entry.Flags |= 8;
                }
                else
                {
                    this.patchEntryHeader = true;
                }
            }
            if (base.Password != null)
            {
                entry.IsCrypted = true;
                if (entry.Crc < 0L)
                {
                    entry.Flags |= 8;
                }
            }
            entry.Offset            = this.offset;
            entry.CompressionMethod = compressionMethod;
            this.curMethod          = compressionMethod;
            if (this.useZip64_ == UseZip64.On || (entry.Size < 0L && this.useZip64_ == UseZip64.Dynamic))
            {
                entry.ForceZip64();
            }
            this.WriteLeInt(67324752);
            this.WriteLeShort(entry.Version);
            this.WriteLeShort(entry.Flags);
            this.WriteLeShort((int)((byte)compressionMethod));
            this.WriteLeInt((int)entry.DosTime);
            if (flag)
            {
                this.WriteLeInt((int)entry.Crc);
                if (entry.LocalHeaderRequiresZip64)
                {
                    this.WriteLeInt(-1);
                    this.WriteLeInt(-1);
                }
                else
                {
                    this.WriteLeInt(entry.IsCrypted ? ((int)entry.CompressedSize + 12) : ((int)entry.CompressedSize));
                    this.WriteLeInt((int)entry.Size);
                }
            }
            else
            {
                if (this.patchEntryHeader)
                {
                    this.crcPatchPos = this.baseOutputStream.Position;
                }
                this.WriteLeInt(0);
                if (this.patchEntryHeader)
                {
                    this.sizePatchPos = this.baseOutputStream.Position;
                }
                if (entry.LocalHeaderRequiresZip64)
                {
                    this.WriteLeInt(-1);
                    this.WriteLeInt(-1);
                }
                else
                {
                    this.WriteLeInt(0);
                    this.WriteLeInt(0);
                }
            }
            byte[] array = ZipConstants.ConvertToArray(entry.Flags, entry.Name);
            if (array.Length > 65535)
            {
                throw new ZipException("Entry name too long.");
            }
            ZipExtraData zipExtraData = new ZipExtraData(entry.ExtraData);

            if (entry.LocalHeaderRequiresZip64)
            {
                zipExtraData.StartNewEntry();
                zipExtraData.AddLeLong(-1L);
                zipExtraData.AddLeLong(-1L);
                zipExtraData.AddNewEntry(1);
                if (!zipExtraData.Find(1))
                {
                    throw new ZipException("Internal error cant find extra data");
                }
                if (this.patchEntryHeader)
                {
                    this.sizePatchPos = (long)zipExtraData.CurrentReadIndex;
                }
            }
            else
            {
                zipExtraData.Delete(1);
            }
            byte[] entryData = zipExtraData.GetEntryData();
            this.WriteLeShort(array.Length);
            this.WriteLeShort(entryData.Length);
            if (array.Length > 0)
            {
                this.baseOutputStream.Write(array, 0, array.Length);
            }
            if (entry.LocalHeaderRequiresZip64 && this.patchEntryHeader)
            {
                this.sizePatchPos += this.baseOutputStream.Position;
            }
            if (entryData.Length > 0)
            {
                this.baseOutputStream.Write(entryData, 0, entryData.Length);
            }
            this.offset  += (long)(30 + array.Length + entryData.Length);
            this.curEntry = entry;
            this.crc.Reset();
            if (compressionMethod == CompressionMethod.Deflated)
            {
                this.def.Reset();
                this.def.SetLevel(level);
            }
            this.size = 0L;
            if (entry.IsCrypted)
            {
                if (entry.Crc < 0L)
                {
                    this.WriteEncryptionHeader(entry.DosTime << 16);
                    return;
                }
                this.WriteEncryptionHeader(entry.Crc);
            }
        }
Esempio n. 25
0
 private long TestLocalHeader(ZipEntry entry, HeaderTest tests)
 {
     lock (_baseStream)
     {
         var flag = (tests & HeaderTest.Header) != 0;
         var flag2 = (tests & HeaderTest.Extract) != 0;
         _baseStream.Seek(_offsetOfFirstEntry + entry.Offset, SeekOrigin.Begin);
         if (ReadLeUint() != ZipConstants.LocalHeaderSignature)
         {
             throw new ZipException($"Wrong local header signature @{_offsetOfFirstEntry + entry.Offset:X}");
         }
         var num = (short)ReadLeUshort();
         var flags = (short)ReadLeUshort();
         var num3 = (short)ReadLeUshort();
         var num4 = (short)ReadLeUshort();
         var num5 = (short)ReadLeUshort();
         var num6 = ReadLeUint();
         long num7 = ReadLeUint();
         long num8 = ReadLeUint();
         int num9 = ReadLeUshort();
         int num10 = ReadLeUshort();
         var buffer = new byte[num9];
         StreamUtils.ReadFully(_baseStream, buffer);
         var buffer2 = new byte[num10];
         StreamUtils.ReadFully(_baseStream, buffer2);
         var data = new ZipExtraData(buffer2);
         if (data.Find(1))
         {
             num8 = data.ReadLong();
             num7 = data.ReadLong();
             if ((flags & 8) != 0)
             {
                 if ((num8 != -1L) && (num8 != entry.Size))
                 {
                     throw new ZipException("Size invalid for descriptor");
                 }
                 if ((num7 != -1L) && (num7 != entry.CompressedSize))
                 {
                     throw new ZipException("Compressed size invalid for descriptor");
                 }
             }
         }
         else if ((num >= 0x2d) && ((((uint)num8) == uint.MaxValue) || (((uint)num7) == uint.MaxValue)))
         {
             throw new ZipException("Required Zip64 extended information missing");
         }
         if (flag2 && entry.IsFile)
         {
             if (!entry.IsCompressionMethodSupported())
             {
                 throw new ZipException("Compression method not supported");
             }
             if ((num > 0x33) || ((num > 20) && (num < 0x2d)))
             {
                 throw new ZipException($"Version required to extract this entry not supported ({num})");
             }
             if ((flags & 0x3060) != 0)
             {
                 throw new ZipException("The library does not support the zip version required to extract this entry");
             }
         }
         if (flag)
         {
             if (((((num <= 0x3f) && (num != 10)) && ((num != 11) && (num != 20))) &&
                  (((num != 0x15) && (num != 0x19)) && ((num != 0x1b) && (num != 0x2d)))) &&
                 ((((num != ZipConstants.CentralHeaderBaseSize) && (num != 50)) && ((num != 0x33) && (num != 0x34))) &&
                  (((num != 0x3d) && (num != 0x3e)) && (num != 0x3f))))
             {
                 throw new ZipException($"Version required to extract this entry is invalid ({num})");
             }
             if ((flags & 0xc010) != 0)
             {
                 throw new ZipException("Reserved bit flags cannot be set.");
             }
             if (((flags & 1) != 0) && (num < 20))
             {
                 throw new ZipException(
                     $"Version required to extract this entry is too low for encryption ({num})");
             }
             if ((flags & 0x40) != 0)
             {
                 if ((flags & 1) == 0)
                 {
                     throw new ZipException("Strong encryption flag set but encryption flag is not set");
                 }
                 if (num < 50)
                 {
                     throw new ZipException(
                         $"Version required to extract this entry is too low for encryption ({num})");
                 }
             }
             if (((flags & 0x20) != 0) && (num < 0x1b))
             {
                 throw new ZipException($"Patched data requires higher version than ({num})");
             }
             if (flags != entry.Flags)
             {
                 throw new ZipException("Central header/local header flags mismatch");
             }
             if (entry.CompressionMethod != ((CompressionMethod)num3))
             {
                 throw new ZipException("Central header/local header compression method mismatch");
             }
             if (entry.Version != num)
             {
                 throw new ZipException("Extract version mismatch");
             }
             if (((flags & 0x40) != 0) && (num < 0x3e))
             {
                 throw new ZipException("Strong encryption flag set but version not high enough");
             }
             if (((flags & 0x2000) != 0) && ((num4 != 0) || (num5 != 0)))
             {
                 throw new ZipException("Header masked set but date/time values non-zero");
             }
             if (((flags & 8) == 0) && (num6 != ((uint)entry.Crc)))
             {
                 throw new ZipException("Central header/local header crc mismatch");
             }
             if (((num8 == 0L) && (num7 == 0L)) && (num6 != 0))
             {
                 throw new ZipException("Invalid CRC for empty entry");
             }
             if (entry.Name.Length > num9)
             {
                 throw new ZipException("File name length mismatch");
             }
             var name = ZipConstants.ConvertToStringExt(flags, buffer);
             if (name != entry.Name)
             {
                 throw new ZipException("Central header and local header file name mismatch");
             }
             if (entry.IsDirectory)
             {
                 if (num8 > 0L)
                 {
                     throw new ZipException("Directory cannot have size");
                 }
                 if (entry.IsCrypted)
                 {
                     if (num7 > 14L)
                     {
                         throw new ZipException("Directory compressed size invalid");
                     }
                 }
                 else if (num7 > 2L)
                 {
                     throw new ZipException("Directory compressed size invalid");
                 }
             }
             if (!ZipNameTransform.IsValidName(name, true))
             {
                 throw new ZipException("Name is invalid");
             }
         }
         if ((((flags & 8) == 0) || (num8 > 0L)) || (num7 > 0L))
         {
             if (num8 != entry.Size)
             {
                 throw new ZipException(
                     $"Size mismatch between central header({entry.Size}) and local header({num8})");
             }
             if (((num7 != entry.CompressedSize) && (num7 != 0xffffffffL)) && (num7 != -1L))
             {
                 throw new ZipException(
                     $"Compressed size mismatch between central header({entry.CompressedSize}) and local header({num7})");
             }
         }
         var num11 = num9 + num10;
         return (((_offsetOfFirstEntry + entry.Offset) + 30L) + num11);
     }
 }