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); }
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 CopyEntryDirect(ZipFile workFile, ZipUpdate update, ref long destinationPosition) { bool skipOver = update.Entry.Offset == destinationPosition; 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 AddEntry(ZipFile workFile, ZipUpdate update) { Stream source = null; if ( update.Entry.IsFile ) { source = update.GetSource() ?? _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; } }