/// <summary> /// Initializes a new instance of the <see cref="DiskArchiveStorage" /> class. /// </summary> /// <param name="file">The file.</param> public DiskArchiveStorage(ZipFile file) : this(file, FileUpdateMode.Safe) {}
/// <summary> /// Extract the contents of a zip file. /// </summary> /// <param name="zipFileName">The zip file to extract from.</param> /// <param name="targetDirectory">The directory to save extracted information in.</param> /// <param name="overwrite">The style of <see cref="Overwrite">overwriting</see> to apply.</param> /// <param name="confirmDelegate">A delegate to invoke when confirming overwriting.</param> /// <param name="fileFilter">A filter to apply to files.</param> /// <param name="directoryFilter">A filter to apply to directories.</param> /// <param name="restoreDateTime">Flag indicating wether to restore the date and time for extracted files.</param> public void ExtractZip(string zipFileName, string targetDirectory, string fileFilter, string directoryFilter) { continueRunning_ = true; extractNameTransform_ = new WindowsNameTransform(targetDirectory); fileFilter_ = new NameFilter(fileFilter); directoryFilter_ = new NameFilter(directoryFilter); using (zipFile_ = new ZipFile(zipFileName)) { var enumerator = zipFile_.GetEnumerator(); while (continueRunning_ && enumerator.MoveNext()) { var entry = (ZipEntry) enumerator.Current; if (entry.IsFile) { // TODO Path.GetDirectory can fail here on invalid characters. if (directoryFilter_.IsMatch(Path.GetDirectoryName(entry.Name)) && fileFilter_.IsMatch(entry.Name)) { ExtractEntry(entry); } } } } }
/// <summary> /// Initialise a new instance of the <see cref="PartialInputStream" /> class. /// </summary> /// <param name="zipFile">The <see cref="ZipFile" /> containing the underlying stream to use for IO.</param> /// <param name="start">The start of the partial data.</param> /// <param name="length">The length of the partial data.</param> public PartialInputStream(ZipFile zipFile, long start, long length) { start_ = start; length_ = length; // Although this is the only time the zipfile is used // keeping a reference here prevents premature closure of // this zip file and thus the baseStream_. // Code like this will cause apparently random failures depending // on the size of the files and when garbage is collected. // // ZipFile z = new ZipFile (stream); // Stream reader = z.GetInputStream(0); // uses reader here.... baseStream_ = zipFile.baseStream_; readPos_ = start; end_ = start + length; }
/// <summary> /// Initializes a new instance of the <see cref="DiskArchiveStorage" /> class. /// </summary> /// <param name="file">The file.</param> /// <param name="updateMode">The update mode.</param> public DiskArchiveStorage(ZipFile file, FileUpdateMode updateMode) : base(updateMode) { if (file.Name == null) { throw new ZipException("Cant handle non file archives"); } fileName_ = file.Name; }
/// <summary> /// Create a new <see cref="ZipFile" /> whose data will be stored on a stream. /// </summary> /// <param name="outStream">The stream providing data storage.</param> /// <returns>Returns the newly created <see cref="ZipFile" /></returns> /// <exception cref="ArgumentNullException"> /// <paramref name="outStream"> is null</paramref> /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="outStream"> doesnt support writing.</paramref> /// </exception> public static ZipFile Create(Stream outStream) { if (outStream == null) { throw new ArgumentNullException("outStream"); } if (!outStream.CanWrite) { throw new ArgumentException("Stream is not writeable", "outStream"); } if (!outStream.CanSeek) { throw new ArgumentException("Stream is not seekable", "outStream"); } var result = new ZipFile(); result.baseStream_ = outStream; return result; }
private void CopyEntry(ZipFile workFile, ZipUpdate update) { workFile.WriteLocalEntryHeader(update); if (update.Entry.CompressedSize > 0) { const int NameLengthOffset = 26; var 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 CopyEntryDirect(ZipFile workFile, ZipUpdate update, ref long destinationPosition) { var skipOver = false; if (update.Entry.Offset == destinationPosition) { skipOver = true; } if (!skipOver) { baseStream_.Position = destinationPosition; workFile.WriteLocalEntryHeader(update); destinationPosition = baseStream_.Position; } const int NameLengthOffset = 26; // TODO: Add base for SFX friendly handling var 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(); var 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); } }
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; }
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, null); } } if (source != null) { using (source) { var 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); var dataStart = workFile.baseStream_.Position; using (var output = workFile.GetOutputStream(update.OutEntry)) { CopyBytes(update, output, source, sourceStreamLength, true); } var dataEnd = workFile.baseStream_.Position; update.OutEntry.CompressedSize = dataEnd - dataStart; if ((update.OutEntry.Flags & (int) GeneralBitFlags.Descriptor) == (int) GeneralBitFlags.Descriptor) { var helper = new ZipHelperStream(workFile.baseStream_); helper.WriteDataDescriptor(update.OutEntry); } } } else { workFile.WriteLocalEntryHeader(update); update.OutEntry.CompressedSize = 0; } }