private async Task <Tuple <byte[], DateTime> > Download(PartialZipInfo info, string filePath) { CentralDirectoryHeader cd = info.CentralDirectory.FirstOrDefault(c => c.FileName == filePath); DataProp dataProp; if (cd != null) { dataProp = cd.GetFileInfoStruct(); byte[] localFileBuffer = await _httpService.GetRange(dataProp.headerOffset, dataProp.headerOffset + LocalFileHeader.Size - 1); LocalFileHeader localFileHeader = new LocalFileHeader(localFileBuffer); ulong start = dataProp.headerOffset + LocalFileHeader.Size + localFileHeader.FileNameLength + localFileHeader.ExtraFieldLength; byte[] compressedContent = await _httpService.GetRange(start, start + dataProp.compressedSize - 1); var dateTimeModified = ConvertDOSDateTime(dataProp.modifiedDate, dataProp.modifiedTime); switch (localFileHeader.Compression) { case 0: return(Tuple.Create(compressedContent, dateTimeModified)); case 8: return(Tuple.Create(_deflateService.Inflate(compressedContent), dateTimeModified)); default: throw new PartialZipUnsupportedCompressionException("Unknown compression."); } } throw new PartialZipFileNotFoundException($"Could not find file in archive."); }
private async Task <byte[]> Download(PartialZipInfo info, string filePath) { CentralDirectoryHeader cd = info.CentralDirectory.FirstOrDefault(c => c.FileName == filePath); if (cd != null) { (ulong uncompressedSize, ulong compressedSize, ulong headerOffset, uint diskNum) = cd.GetFileInfo(); byte[] localFileBuffer = await this._httpService.GetRange(headerOffset, headerOffset + LocalFileHeader.Size - 1); LocalFileHeader localFileHeader = new LocalFileHeader(localFileBuffer); ulong start = headerOffset + LocalFileHeader.Size + localFileHeader.FileNameLength + localFileHeader.ExtraFieldLength; byte[] compressedContent = await this._httpService.GetRange(start, start + compressedSize - 1); switch (localFileHeader.Compression) { case 0: return(compressedContent); case 8: return(this._deflateService.Inflate(compressedContent)); default: throw new PartialZipUnsupportedCompressionException("Unknown compression."); } } throw new PartialZipFileNotFoundException($"Could not find file {filePath} in archive."); }
internal override void PrepareForZip(CentralDirectoryHeader header = null) { base.PrepareForZip(header); this.UseZipHeader = true; if (header == null) { return; } this.InternalStreamLength = (long)header.UncompressedSize; }
private async Task <PartialZipInfo> Open() { bool supportsPartialZip = await _httpService.SupportsPartialZip(); if (!supportsPartialZip) { throw new PartialZipNotSupportedException("The web server does not support PartialZip as byte ranges are not accepted."); } PartialZipInfo info = new PartialZipInfo(); info.Length = await _httpService.GetContentLength(); byte[] eocdBuffer = await _httpService.GetRange(info.Length - EndOfCentralDirectory.Size, info.Length - 1); info.EndOfCentralDirectory = new EndOfCentralDirectory(eocdBuffer); ulong startCD, endCD; if (info.EndOfCentralDirectory.IsZip64) { byte[] eocdLocator64Buffer = await _httpService.GetRange(info.Length - EndOfCentralDirectory.Size - EndOfCentralDirectoryLocator64.Size, info.Length - EndOfCentralDirectory.Size); info.EndOfCentralDirectoryLocator64 = new EndOfCentralDirectoryLocator64(eocdLocator64Buffer); byte[] eocd64Buffer = await _httpService.GetRange(info.EndOfCentralDirectoryLocator64.EndOfCentralDirectory64StartOffset, info.EndOfCentralDirectoryLocator64.EndOfCentralDirectory64StartOffset + EndOfCentralDirectory64.Size - 1); info.EndOfCentralDirectory64 = new EndOfCentralDirectory64(eocd64Buffer); startCD = info.EndOfCentralDirectory64.CentralDirectoryStartOffset; endCD = info.EndOfCentralDirectory64.CentralDirectoryStartOffset + info.EndOfCentralDirectory64.CentralDirectorySize + EndOfCentralDirectory64.Size - 1; info.CentralDirectoryEntries = info.EndOfCentralDirectory64.CentralDirectoryRecordCount; } else { startCD = info.EndOfCentralDirectory.CentralDirectoryStartOffset; endCD = info.EndOfCentralDirectory.CentralDirectoryStartOffset + info.EndOfCentralDirectory.CentralDirectorySize + EndOfCentralDirectory.Size - 1; info.CentralDirectoryEntries = info.EndOfCentralDirectory.CentralDirectoryRecordCount; } byte[] cdBuffer = await _httpService.GetRange(startCD, endCD); info.CentralDirectory = CentralDirectoryHeader.GetFromBuffer(cdBuffer, info.CentralDirectoryEntries); return(info); }
private PackageEntryEntity Initialize(PackageEntryEntity entity, CentralDirectoryHeader metadata) { entity.Comment = metadata.Comment; entity.CommentSize = metadata.CommentSize; entity.CompressedSize = metadata.CompressedSize; entity.CompressionMethod = metadata.CompressionMethod; entity.Crc32 = metadata.Crc32; entity.DiskNumberStart = metadata.DiskNumberStart; entity.ExternalAttributes = metadata.ExternalAttributes; entity.ExtraField = metadata.ExtraField; entity.ExtraFieldSize = metadata.ExtraFieldSize; entity.Flags = metadata.Flags; entity.InternalAttributes = metadata.InternalAttributes; entity.LastModifiedDate = metadata.LastModifiedDate; entity.LastModifiedTime = metadata.LastModifiedTime; entity.LocalHeaderOffset = metadata.LocalHeaderOffset; entity.Name = metadata.Name; entity.NameSize = metadata.NameSize; entity.UncompressedSize = metadata.UncompressedSize; entity.VersionMadeBy = metadata.VersionMadeBy; entity.VersionToExtract = metadata.VersionToExtract; return(entity); }
internal override void PrepareForZip(CentralDirectoryHeader header = null) { base.PrepareForZip(header); this.HeaderType = CompressedStreamHeader.None; }
public CentralDirectoryHeaderInfo(CentralDirectoryHeader header) : base((FileHeaderBase)header) { this.LocalHeaderOffsetOverflow = header.LocalHeaderOffset == uint.MaxValue; }
// Haven't figured out how to do this without borrowing code from the Parse function - compiler wont allow yield return in a lambda. public IEnumerator <CDEntry> GetEnumerator() { using (var fs = new FileStream(ZIPPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { EOCDOffset = LocateEOCD(fs); if (EOCDOffset == 0) { throw new Exception("Unable to locate EOCD"); } CDSize = fs.ParseInt32(EOCDOffset + 12); if (!fs.GetBytes(EOCDOffset - 76, 4).SequenceEqual(SeventySixHeader)) { Console.WriteLine("Warning: 0606 not found at EOCD-76"); } var cdStartOffset = EOCDOffset - CDSize - 76; fs.Seek(cdStartOffset, SeekOrigin.Begin); CentralDirectory = new byte[CDSize]; fs.Read(CentralDirectory, 0, CDSize); var curPos = 0; while (curPos < CentralDirectory.Length) { if (!CentralDirectoryHeader.SequenceEqual(CentralDirectory.Take(4))) { throw new Exception("Some sort of CentralDirectory parsing issue"); } var n = BitConverter.ToInt16(CentralDirectory, curPos + 28); var m = BitConverter.ToInt16(CentralDirectory, curPos + 30); var k = BitConverter.ToInt16(CentralDirectory, curPos + 32); var cd = new CDEntry() { Parent = this, RelativeOffset = curPos, AbsoluteOffset = cdStartOffset + curPos, Name = ASCIIEncoding.ASCII.GetString(CentralDirectory, curPos + 46, n), LengthFileNameN = n, LengthExtraFieldM = m, LengthCommentK = k, CompressionMethod = BitConverter.ToInt16(CentralDirectory, curPos + 10), }; if (StoringEntries) { CDEntries.Add(cd); } curPos += 46 + n + m + k; yield return(cd); } fs.Close(); TriggerParsingCompleted(); if (!StoringEntries) { CentralDirectory = null; } } }