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; } }
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; } }
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); } }
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; } }
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"); } } }
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); } }
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); } }
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); } }
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; } }
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); } }
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; }
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; }
private int GetDescriptorSize(ZipUpdate update) { int num = 0; if ((update.Entry.Flags & 8) != 0) { num = 12; if (update.Entry.LocalHeaderRequiresZip64) { num = 20; } } return num; }
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); } }
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"); } } } }
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); } }
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; }
/// <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; }
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); } }
/// <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); }
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"); } } } }
/// <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); }
/// <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; }
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"); } } } }
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; } }
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; }
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; }
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); } }
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_); }
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_); }