Пример #1
0
        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.");
        }
Пример #2
0
        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.");
        }
Пример #3
0
 internal override void PrepareForZip(CentralDirectoryHeader header = null)
 {
     base.PrepareForZip(header);
     this.UseZipHeader = true;
     if (header == null)
     {
         return;
     }
     this.InternalStreamLength = (long)header.UncompressedSize;
 }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
 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;
 }
Пример #8
0
        // 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;
                }
            }
        }