Esempio n. 1
0
 private void CopyEntryDataDirect(ZipUpdate update, Stream stream, bool updateCrc, ref long destinationPosition, ref long sourcePosition)
 {
     int num4;
     long compressedSize = update.Entry.CompressedSize;
     Crc32 crc = new Crc32();
     byte[] buffer = GetBuffer();
     long num2 = compressedSize;
     long num3 = 0L;
     do
     {
         int length = buffer.Length;
         if (compressedSize < length)
         {
             length = (int)compressedSize;
         }
         stream.Position = sourcePosition;
         num4 = stream.Read(buffer, 0, length);
         if (num4 > 0)
         {
             if (updateCrc)
             {
                 crc.Update(buffer, 0, num4);
             }
             stream.Position = destinationPosition;
             stream.Write(buffer, 0, num4);
             destinationPosition += num4;
             sourcePosition += num4;
             compressedSize -= num4;
             num3 += num4;
         }
     }
     while ((num4 > 0) && (compressedSize > 0L));
     if (num3 != num2)
     {
         throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", num2, num3));
     }
     if (updateCrc)
     {
         update.OutEntry.Crc = crc.Value;
     }
 }
Esempio n. 2
0
		void AddEntry(ZipFile workFile, ZipUpdate update)
		{
			Stream source = null;

			if ( update.Entry.IsFile ) {
				source = update.GetSource();
				
				if ( source == null ) {
					source = updateDataSource_.GetSource(update.Entry, update.Filename);
				}
			}

			if ( source != null ) {
				using ( source ) {
					long sourceStreamLength = source.Length;
					if ( update.OutEntry.Size < 0 ) {
						update.OutEntry.Size = sourceStreamLength;
					}
					else {
						// Check for errant entries.
						if ( update.OutEntry.Size != sourceStreamLength ) {
							throw new ZipException("Entry size/stream size mismatch");
						}
					}

					workFile.WriteLocalEntryHeader(update);

					long dataStart = workFile.baseStream_.Position;

					using ( Stream output = workFile.GetOutputStream(update.OutEntry) ) {
						CopyBytes(update, output, source, sourceStreamLength, true);
					}

					long dataEnd = workFile.baseStream_.Position;
					update.OutEntry.CompressedSize = dataEnd - dataStart;

					if ((update.OutEntry.Flags & (int)GeneralBitFlags.Descriptor) == (int)GeneralBitFlags.Descriptor)
					{
						ZipHelperStream helper = new ZipHelperStream(workFile.baseStream_);
						helper.WriteDataDescriptor(update.OutEntry);
					}
				}
			}
			else {
				workFile.WriteLocalEntryHeader(update);
				update.OutEntry.CompressedSize = 0;
			}

		}
Esempio n. 3
0
		void CopyEntryDirect(ZipFile workFile, ZipUpdate update, ref long destinationPosition)
		{
			bool skipOver = false;
			if ( update.Entry.Offset == destinationPosition ) {
				skipOver = true;
			}

			if ( !skipOver ) {
				baseStream_.Position = destinationPosition;
				workFile.WriteLocalEntryHeader(update);
				destinationPosition = baseStream_.Position;
			}

			long sourcePosition = 0;

			const int NameLengthOffset = 26;

			// TODO: Add base for SFX friendly handling
			long entryDataOffset = update.Entry.Offset + NameLengthOffset;

			baseStream_.Seek(entryDataOffset, SeekOrigin.Begin);

			// Clumsy way of handling retrieving the original name and extra data length for now.
			// TODO: Stop re-reading name and data length in CopyEntryDirect.
			uint nameLength = ReadLEUshort();
			uint extraLength = ReadLEUshort();

			sourcePosition = baseStream_.Position + nameLength + extraLength;

			if (skipOver) {
				if (update.OffsetBasedSize != -1)
					destinationPosition += update.OffsetBasedSize;
				else
					// TODO: Find out why this calculation comes up 4 bytes short on some entries in ODT (Office Document Text) archives.
					// WinZip produces a warning on these entries:
					// "caution: value of lrec.csize (compressed size) changed from ..."
					destinationPosition +=
						(sourcePosition - entryDataOffset) + NameLengthOffset +	// Header size
						update.Entry.CompressedSize + GetDescriptorSize(update);
			}
			else {
				if ( update.Entry.CompressedSize > 0 ) {
					CopyEntryDataDirect(update, baseStream_, false, ref destinationPosition, ref sourcePosition );
				}
				CopyDescriptorBytesDirect(update, baseStream_, ref destinationPosition, sourcePosition);
			}
		}
Esempio n. 4
0
		void CopyBytes(ZipUpdate update, Stream destination, Stream source,
			long bytesToCopy, bool updateCrc)
		{
			if ( destination == source ) {
				throw new InvalidOperationException("Destination and source are the same");
			}

			// NOTE: Compressed size is updated elsewhere.
			Crc32 crc = new Crc32();
			byte[] buffer = GetBuffer();

			long targetBytes = bytesToCopy;
			long totalBytesRead = 0;

			int bytesRead;
			do {
				int readSize = buffer.Length;

				if ( bytesToCopy < readSize ) {
					readSize = (int)bytesToCopy;
				}

				bytesRead = source.Read(buffer, 0, readSize);
				if ( bytesRead > 0 ) {
					if ( updateCrc ) {
						crc.Update(buffer, 0, bytesRead);
					}
					destination.Write(buffer, 0, bytesRead);
					bytesToCopy -= bytesRead;
					totalBytesRead += bytesRead;
				}
			}
			while ( (bytesRead > 0) && (bytesToCopy > 0) );

			if ( totalBytesRead != targetBytes ) {
				throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead));
			}

			if ( updateCrc ) {
				update.OutEntry.Crc = crc.Value;
			}
		}
Esempio n. 5
0
		void CopyDescriptorBytesDirect(ZipUpdate update, Stream stream, ref long destinationPosition, long sourcePosition)
		{
			int bytesToCopy = GetDescriptorSize(update);

			while ( bytesToCopy > 0 ) {
				int readSize = (int)bytesToCopy;
				byte[] buffer = GetBuffer();

				stream.Position = sourcePosition;
				int bytesRead = stream.Read(buffer, 0, readSize);
				if ( bytesRead > 0 ) {
					stream.Position = destinationPosition;
					stream.Write(buffer, 0, bytesRead);
					bytesToCopy -= bytesRead;
					destinationPosition += bytesRead;
					sourcePosition += bytesRead;
				}
				else {
					throw new ZipException("Unxpected end of stream");
				}
			}
		}
Esempio n. 6
0
		void CopyEntryDirect(ZipFile workFile, ZipUpdate update, ref long destinationPosition)
		{
			bool skipOver = false;
			if ( update.Entry.Offset == destinationPosition ) {
				skipOver = true;
			}

			if ( !skipOver ) {
				baseStream_.Position = destinationPosition;
				workFile.WriteLocalEntryHeader(update);
				destinationPosition = baseStream_.Position;
			}

			long sourcePosition = 0;

			const int NameLengthOffset = 26;

			// TODO: Add base for SFX friendly handling
			long entryDataOffset = update.Entry.Offset + NameLengthOffset;

			baseStream_.Seek(entryDataOffset, SeekOrigin.Begin);

			// Clumsy way of handling retrieving the original name and extra data length for now.
			// TODO: Stop re-reading name and data length in CopyEntryDirect.
			uint nameLength = ReadLEUshort();
			uint extraLength = ReadLEUshort();

			sourcePosition = baseStream_.Position + nameLength + extraLength;

			if ( skipOver ) {
				destinationPosition += 
					(sourcePosition - entryDataOffset) + NameLengthOffset +	// Header size
					update.Entry.CompressedSize + GetDescriptorSize(update);
			}
			else {
				if ( update.Entry.CompressedSize > 0 ) {
					CopyEntryDataDirect(update, baseStream_, false, ref destinationPosition, ref sourcePosition );
				}
				CopyDescriptorBytesDirect(update, baseStream_, ref destinationPosition, sourcePosition);
			}
		}
Esempio n. 7
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 CRC later.
				update.CrcPatchOffset = baseStream_.Position;
				WriteLEInt(( int )0);
			}
			else {
				WriteLEInt(unchecked(( 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 normal 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. 8
0
 private void AddUpdate(ZipUpdate update)
 {
     contentsEdited_ = true;
     int num = FindExistingUpdate(update.Entry.Name);
     if (num >= 0)
     {
         if (updates_[num] == null)
         {
             updateCount_ += 1L;
         }
         updates_[num] = update;
     }
     else
     {
         num = updates_.Add(update);
         updateCount_ += 1L;
         updateIndex_.Add(update.Entry.Name, num);
     }
 }
Esempio n. 9
0
 private void CopyBytes(ZipUpdate update, Stream destination, Stream source, long bytesToCopy, bool updateCrc)
 {
     int num3;
     if (destination == source)
     {
         throw new InvalidOperationException("Destination and source are the same");
     }
     Crc32 crc = new Crc32();
     byte[] buffer = GetBuffer();
     long num = bytesToCopy;
     long num2 = 0L;
     do
     {
         int length = buffer.Length;
         if (bytesToCopy < length)
         {
             length = (int)bytesToCopy;
         }
         num3 = source.Read(buffer, 0, length);
         if (num3 > 0)
         {
             if (updateCrc)
             {
                 crc.Update(buffer, 0, num3);
             }
             destination.Write(buffer, 0, num3);
             bytesToCopy -= num3;
             num2 += num3;
         }
     }
     while ((num3 > 0) && (bytesToCopy > 0L));
     if (num2 != num)
     {
         throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", num, num2));
     }
     if (updateCrc)
     {
         update.OutEntry.Crc = crc.Value;
     }
 }
Esempio n. 10
0
        private void WriteLocalEntryHeader(ZipUpdate update)
        {
            ZipEntry 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(0x4034b50);
            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);
            }
            byte[] buffer = ZipConstants.ConvertToArray(outEntry.Flags, outEntry.Name);
            if (buffer.Length > 0xffff)
            {
                throw new ZipException("Entry name too long.");
            }
            ZipExtraData 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. 11
0
 private void AddEntry(ZipFile workFile, ZipUpdate update)
 {
     Stream source = null;
     if (update.Entry.IsFile)
     {
         source = update.GetSource();
         if (source == null)
         {
             source = updateDataSource_.GetSource(update.Entry, update.Filename);
         }
     }
     if (source != null)
     {
         using (source)
         {
             long length = source.Length;
             if (update.OutEntry.Size < 0L)
             {
                 update.OutEntry.Size = length;
             }
             else if (update.OutEntry.Size != length)
             {
                 throw new ZipException("Entry size/stream size mismatch");
             }
             workFile.WriteLocalEntryHeader(update);
             long position = workFile.baseStream_.Position;
             using (Stream stream2 = workFile.GetOutputStream(update.OutEntry))
             {
                 CopyBytes(update, stream2, source, length, true);
             }
             long num3 = workFile.baseStream_.Position;
             update.OutEntry.CompressedSize = num3 - position;
             if ((update.OutEntry.Flags & 8) == 8)
             {
                 new ZipHelperStream(workFile.baseStream_).WriteDataDescriptor(update.OutEntry);
             }
             return;
         }
     }
     workFile.WriteLocalEntryHeader(update);
     update.OutEntry.CompressedSize = 0L;
 }
Esempio n. 12
0
 private void ModifyEntry(ZipFile workFile, ZipUpdate update)
 {
     workFile.WriteLocalEntryHeader(update);
     long position = workFile.baseStream_.Position;
     if (update.Entry.IsFile && (update.Filename != null))
     {
         using (Stream stream = workFile.GetOutputStream(update.OutEntry))
         {
             using (Stream stream2 = GetInputStream(update.Entry))
             {
                 CopyBytes(update, stream, stream2, stream2.Length, true);
             }
         }
     }
     long num2 = workFile.baseStream_.Position;
     update.Entry.CompressedSize = num2 - position;
 }
Esempio n. 13
0
 private int GetDescriptorSize(ZipUpdate update)
 {
     int num = 0;
     if ((update.Entry.Flags & 8) != 0)
     {
         num = 12;
         if (update.Entry.LocalHeaderRequiresZip64)
         {
             num = 20;
         }
     }
     return num;
 }
Esempio n. 14
0
 private void CopyEntryDirect(ZipFile workFile, ZipUpdate update, ref long destinationPosition)
 {
     bool flag = false;
     if (update.Entry.Offset == destinationPosition)
     {
         flag = true;
     }
     if (!flag)
     {
         baseStream_.Position = destinationPosition;
         workFile.WriteLocalEntryHeader(update);
         destinationPosition = baseStream_.Position;
     }
     long offset = update.Entry.Offset + 0x1aL;
     baseStream_.Seek(offset, SeekOrigin.Begin);
     uint num3 = ReadLEUshort();
     uint num4 = ReadLEUshort();
     long sourcePosition = (baseStream_.Position + num3) + num4;
     if (flag)
     {
         if (update.OffsetBasedSize != -1L)
         {
             destinationPosition += update.OffsetBasedSize;
         }
         else
         {
             destinationPosition += (((sourcePosition - offset) + 0x1aL) + update.Entry.CompressedSize) + GetDescriptorSize(update);
         }
     }
     else
     {
         if (update.Entry.CompressedSize > 0L)
         {
             CopyEntryDataDirect(update, baseStream_, false, ref destinationPosition, ref sourcePosition);
         }
         CopyDescriptorBytesDirect(update, baseStream_, ref destinationPosition, sourcePosition);
     }
 }
Esempio n. 15
0
		void CopyDescriptorBytes(ZipUpdate update, Stream dest, Stream source)
		{
			int bytesToCopy = 0;

			if ( (update.Entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) {
				bytesToCopy = 12;
				if ( update.Entry.LocalHeaderRequiresZip64 ) {
					bytesToCopy = 20;
				}
			}

			if ( bytesToCopy > 0 ) {
				byte[] buffer = GetBuffer();

				while ( bytesToCopy > 0 ) {
					int readSize = Math.Min(buffer.Length, bytesToCopy);

					int bytesRead = source.Read(buffer, 0, readSize);
					if ( bytesRead > 0 ) {
						dest.Write(buffer, 0, bytesRead);
						bytesToCopy -= bytesRead;
					}
					else {
						throw new ZipException("Unxpected end of stream");
					}
				}
			}
		}
Esempio n. 16
0
		void AddUpdate(ZipUpdate update)
		{
			_contentsEdited = true;

			int index = FindExistingUpdate(update.Entry.Name);

			if (index >= 0) {
				if ( _updates[index] == null ) {
					_updateCount += 1;
				}

				// Direct replacement is faster than delete and add.
				_updates[index] = update;
			}
			else {
				index = _updates.Add(update);
				_updateCount += 1;
				_updateIndex.Add(update.Entry.Name, index);
			}
		}
Esempio n. 17
0
		int GetDescriptorSize(ZipUpdate update)
		{
			int result = 0;
			if ( (update.Entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) {
				result = 12;
				if ( update.Entry.LocalHeaderRequiresZip64 ) {
					result = 20;
				}
			}
			return result;
		}
Esempio n. 18
0
        /// <summary>
        /// Compares two objects and returns a value indicating whether one is 
        /// less than, equal to or greater than the other.
        /// </summary>
        /// <param name="zx">First object to compare</param>
        /// <param name="zy">Second object to compare.</param>
        /// <returns>Compare result.</returns>
        private static int UpdateComparer(
            ZipUpdate zx,
            ZipUpdate zy) {

            int result;

            if (zx==null) {
                if (zy==null) {
                    result=0;
                } else {
                    result=-1;
                }
            } else if (zy==null) {
                result=1;
            } else {
                int xCmdValue=((zx.Command==UpdateCommand.Copy)||(zx.Command==UpdateCommand.Modify))?0:1;
                int yCmdValue=((zy.Command==UpdateCommand.Copy)||(zy.Command==UpdateCommand.Modify))?0:1;

                result=xCmdValue-yCmdValue;
                if (result==0) {
                    long offsetDiff=zx.Entry.Offset-zy.Entry.Offset;
                    if (offsetDiff<0) {
                        result=-1;
                    } else if (offsetDiff==0) {
                        result=0;
                    } else {
                        result=1;
                    }
                }
            }
            return result;
        }
Esempio n. 19
0
		void AddUpdate(ZipUpdate update)
		{
			contentsEdited_ = true;

			int index = FindExistingUpdate(update.Entry.Name);

			if (index >= 0) {
				if ( updates_[index] == null ) {
					updateCount_ += 1;
				}

				// Direct replacement is faster than delete and add.
				updates_[index] = update;
			}
			else {
				index = updates_.Add(update);
				updateCount_ += 1;
				updateIndex_.Add(update.Entry.Name, index);
			}
		}
Esempio n. 20
0
        /// <summary>
        /// Add a new entry to the archive.
        /// </summary>
        /// <param name="fileName">The name of the file to add.</param>
        /// <param name="compressionMethod">The compression method to use.</param>
        /// <param name="useUnicodeText">Ensure Unicode text is used for name and comment for this entry.</param>
        public void Add(string fileName, CompressionMethod compressionMethod, bool useUnicodeText )
        {
            if (fileName == null)
            {
                throw new ArgumentNullException("fileName");
            }

            if (!ZipEntry.IsCompressionMethodSupported(compressionMethod))
            {
                throw new ZipException("Compression method not supported");
            }

            CheckUpdating();
            contentsEdited_ = true;

            string zipEntryName = GetTransformedFileName(fileName);
            int index = FindExistingUpdate(zipEntryName);

            if (index >= 0)
            {
                updates_.RemoveAt(index);
            }

            ZipUpdate update = new ZipUpdate(fileName, zipEntryName, compressionMethod);
            update.Entry.IsUnicodeText = useUnicodeText;
            updates_.Add(update);
        }
Esempio n. 21
0
		void CopyDescriptorBytes(ZipUpdate update, Stream dest, Stream source)
		{
			int bytesToCopy = GetDescriptorSize(update);

			if ( bytesToCopy > 0 ) {
				byte[] buffer = GetBuffer();

				while ( bytesToCopy > 0 ) {
					int readSize = Math.Min(buffer.Length, bytesToCopy);

					int bytesRead = source.Read(buffer, 0, readSize);
					if ( bytesRead > 0 ) {
						dest.Write(buffer, 0, bytesRead);
						bytesToCopy -= bytesRead;
					}
					else {
						throw new ZipException("Unxpected end of stream");
					}
				}
			}
		}
Esempio n. 22
0
        /// <summary>
        /// Add a file entry with data.
        /// </summary>
        /// <param name="dataSource">The source of the data for this entry.</param>
        /// <param name="entryName">The name to give to the entry.</param>
        /// <param name="compressionMethod">The compression method to use.</param>
        /// <param name="useUnicodeText">Ensure Unicode text is used for name and comments for this entry.</param>
        public void Add(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod, bool useUnicodeText)
        {
            if (dataSource == null)
            {
                throw new ArgumentNullException("dataSource");
            }

            CheckUpdating();
            contentsEdited_ = true;
            ZipUpdate update = new ZipUpdate(dataSource, GetTransformedFileName(entryName),
                                       compressionMethod);
            update.Entry.IsUnicodeText = useUnicodeText;
            updates_.Add(update);
        }
Esempio n. 23
0
		/// <summary>
		/// Get the size of the source descriptor for a <see cref="ZipUpdate"/>.
		/// </summary>
		/// <param name="update">The update to get the size for.</param>
		/// <returns>The descriptor size, zero if there isnt one.</returns>
		int GetDescriptorSize(ZipUpdate update)
		{
			int result = 0;
			if ( (update.Entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) {
				result = ZipConstants.DataDescriptorSize - 4;
				if ( update.Entry.LocalHeaderRequiresZip64 ) {
					result = ZipConstants.Zip64DataDescriptorSize - 4;
				}
			}
			return result;
		}
Esempio n. 24
0
        void CopyDescriptorBytes(ZipUpdate update, Stream dest, Stream source)
        {
            int bytesToCopy = GetDescriptorSize(update);

            /* Use the above instead.  Remove once confirmed correct.
            if ( (update.Entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) {
                bytesToCopy = ZipConstants.DataDescriptorSize - 4; // 12
                if ( update.Entry.LocalHeaderRequiresZip64 ) {
                    bytesToCopy = ZipConstants.Zip64DataDescriptorSize - 4; // 20
                }
            }
            */
            if ( bytesToCopy > 0 ) {
                byte[] buffer = GetBuffer();

                while ( bytesToCopy > 0 ) {
                    int readSize = Math.Min(buffer.Length, bytesToCopy);

                    int bytesRead = source.Read(buffer, 0, readSize);
                    if ( bytesRead > 0 ) {
                        dest.Write(buffer, 0, bytesRead);
                        bytesToCopy -= bytesRead;
                    }
                    else {
                        throw new ZipException("Unxpected end of stream");
                    }
                }
            }
        }
Esempio n. 25
0
		void CopyEntryDataDirect(ZipUpdate update, Stream stream, bool updateCrc, ref long destinationPosition, ref long sourcePosition)
		{
			long bytesToCopy = update.Entry.CompressedSize;
			
			// NOTE: Compressed size is updated elsewhere.
			Crc32 crc = new Crc32();
			byte[] buffer = GetBuffer();

			long targetBytes = bytesToCopy;
			long totalBytesRead = 0;

			int bytesRead;
			do
			{
				int readSize = buffer.Length;

				if ( bytesToCopy < readSize ) {
					readSize = (int)bytesToCopy;
				}

				stream.Position = sourcePosition;
				bytesRead = stream.Read(buffer, 0, readSize);
				if ( bytesRead > 0 ) {
					if ( updateCrc ) {
						crc.Update(buffer, 0, bytesRead);
					}
					stream.Position = destinationPosition;
					stream.Write(buffer, 0, bytesRead);

					destinationPosition += bytesRead;
					sourcePosition += bytesRead;
					bytesToCopy -= bytesRead;
					totalBytesRead += bytesRead;
				}
			}
			while ( (bytesRead > 0) && (bytesToCopy > 0) );

			if ( totalBytesRead != targetBytes ) {
				throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead));
			}

			if ( updateCrc ) {
				update.OutEntry.Crc = crc.Value;
			}
		}
Esempio n. 26
0
    private static void ModifyEntry(ZipFile workFile, ZipUpdate update)
    {
      workFile.WriteLocalEntryHeader(update);
      var dataStart = workFile.baseStream_.Position;

      var dataEnd = workFile.baseStream_.Position;
      update.Entry.CompressedSize = dataEnd - dataStart;
    }
Esempio n. 27
0
		void ModifyEntry(ZipFile workFile, ZipUpdate update)
		{
			workFile.WriteLocalEntryHeader(update);
			long dataStart = workFile.baseStream_.Position;

			// TODO: This is slow if the changes don't effect the data!!
			if ( update.Entry.IsFile && (update.Filename != null) ) {
				using ( Stream output = workFile.GetOutputStream(update.OutEntry) ) {
					using ( Stream source = this.GetInputStream(update.Entry) ) {
						CopyBytes(update, output, source, source.Length, true);
					}
				}
			}

			long dataEnd = workFile.baseStream_.Position;
			update.Entry.CompressedSize = dataEnd - dataStart;
		}
Esempio n. 28
0
		void WriteLocalEntryHeader(ZipUpdate update)
		{
			ZipEntry entry = update.OutEntry;

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

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

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

			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 &= ~8;
			}

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

			// Force Zip64 if the size of an entry isnt known.
			// A more flexible strategy could be created here if required.
#if !FORCE_ZIP64
			if ( entry.Size < 0 )
#endif
			{
				entry.ForceZip64();
			}

			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.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. 29
0
		void CopyEntry(ZipFile workFile, ZipUpdate update)
		{
			workFile.WriteLocalEntryHeader(update);

			if ( update.Entry.CompressedSize > 0 ) {
				const int NameLengthOffset = 26;

				long entryDataOffset = update.Entry.Offset + NameLengthOffset;

				// TODO: This wont work for SFX files!
				baseStream_.Seek(entryDataOffset, SeekOrigin.Begin);

				uint nameLength = ReadLEUshort();
				uint extraLength = ReadLEUshort();

				baseStream_.Seek(nameLength + extraLength, SeekOrigin.Current);

				CopyBytes(update, workFile.baseStream_, baseStream_, update.Entry.CompressedSize, false);
			}
			CopyDescriptorBytes(update, workFile.baseStream_, baseStream_);
		}
Esempio n. 30
0
 private void CopyEntry(ZipFile workFile, ZipUpdate update)
 {
     workFile.WriteLocalEntryHeader(update);
     if (update.Entry.CompressedSize > 0L)
     {
         long offset = update.Entry.Offset + 0x1aL;
         baseStream_.Seek(offset, SeekOrigin.Begin);
         uint num2 = ReadLEUshort();
         uint num3 = ReadLEUshort();
         baseStream_.Seek(num2 + num3, SeekOrigin.Current);
         CopyBytes(update, workFile.baseStream_, baseStream_, update.Entry.CompressedSize, false);
     }
     CopyDescriptorBytes(update, workFile.baseStream_, baseStream_);
 }