/// <summary> /// Read ZIP's offsets and positions of offsets. /// </summary> /// <param name="reader">binary reader to zip archive</param> /// <returns>metadata with offsets and positions for entries</returns> public static SignedPackageArchiveMetadata ReadSignedArchiveMetadata(BinaryReader reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var metadata = new SignedPackageArchiveMetadata() { StartOfFileHeaders = reader.BaseStream.Length }; var endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord.Read(reader); metadata.EndOfCentralDirectoryRecordPosition = endOfCentralDirectoryRecord.OffsetFromStart; reader.BaseStream.Seek(endOfCentralDirectoryRecord.OffsetOfStartOfCentralDirectory, SeekOrigin.Begin); // Read central directory records var centralDirectoryRecords = new List <CentralDirectoryHeaderMetadata>(); CentralDirectoryHeader header; while (CentralDirectoryHeader.TryRead(reader, out header)) { if (header.RelativeOffsetOfLocalHeader < metadata.StartOfFileHeaders) { metadata.StartOfFileHeaders = header.RelativeOffsetOfLocalHeader; } var isPackageSignatureFile = SignedPackageArchiveUtility.IsPackageSignatureFileEntry( header.FileName, header.GeneralPurposeBitFlag); var centralDirectoryMetadata = new CentralDirectoryHeaderMetadata() { IsPackageSignatureFile = isPackageSignatureFile, HeaderSize = header.GetSizeInBytes(), OffsetToFileHeader = header.RelativeOffsetOfLocalHeader, Position = header.OffsetFromStart }; centralDirectoryRecords.Add(centralDirectoryMetadata); } if (centralDirectoryRecords.Count == 0) { throw new InvalidDataException(Strings.ErrorInvalidPackageArchive); } var lastCentralDirectoryRecord = centralDirectoryRecords.Last(); metadata.EndOfCentralDirectory = lastCentralDirectoryRecord.Position + lastCentralDirectoryRecord.HeaderSize; metadata.CentralDirectoryHeaders = centralDirectoryRecords; UpdateSignedPackageArchiveMetadata(reader, metadata); return(metadata); }
/// <summary> /// Read ZIP's offsets and positions of offsets. /// </summary> /// <param name="reader">binary reader to zip archive</param> /// <returns>metadata with offsets and positions for entries</returns> public static SignedPackageArchiveMetadata ReadSignedArchiveMetadata(BinaryReader reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } var metadata = new SignedPackageArchiveMetadata() { StartOfLocalFileHeaders = reader.BaseStream.Length }; var endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord.Read(reader); var endOfCentralDirectoryRecordPosition = endOfCentralDirectoryRecord.OffsetFromStart; reader.BaseStream.Seek(endOfCentralDirectoryRecord.OffsetOfStartOfCentralDirectory, SeekOrigin.Begin); var centralDirectoryRecords = new List <CentralDirectoryHeaderMetadata>(); var packageSignatureFileMetadataIndex = -1; var index = 0; while (CentralDirectoryHeader.TryRead(reader, out var header)) { metadata.StartOfLocalFileHeaders = Math.Min(metadata.StartOfLocalFileHeaders, header.RelativeOffsetOfLocalHeader); var isPackageSignatureFile = SignedPackageArchiveUtility.IsPackageSignatureFileEntry( header.FileName, header.GeneralPurposeBitFlag); if (isPackageSignatureFile) { if (packageSignatureFileMetadataIndex != -1) { throw new SignatureException(NuGetLogCode.NU3005, Strings.MultiplePackageSignatureFiles); } packageSignatureFileMetadataIndex = index; } var centralDirectoryMetadata = new CentralDirectoryHeaderMetadata() { Position = header.OffsetFromStart, OffsetToLocalFileHeader = header.RelativeOffsetOfLocalHeader, IsPackageSignatureFile = isPackageSignatureFile, HeaderSize = header.GetSizeInBytes(), IndexInHeaders = index }; centralDirectoryRecords.Add(centralDirectoryMetadata); ++index; } if (centralDirectoryRecords.Count == 0) { throw new InvalidDataException(Strings.ErrorInvalidPackageArchive); } if (packageSignatureFileMetadataIndex == -1) { throw new SignatureException(NuGetLogCode.NU3005, Strings.NoPackageSignatureFile); } var lastCentralDirectoryRecord = centralDirectoryRecords.Last(); var endOfCentralDirectoryPosition = lastCentralDirectoryRecord.Position + lastCentralDirectoryRecord.HeaderSize; var endOfLocalFileHeadersPosition = GetEndOfLocalFileHeadersPosition(reader, centralDirectoryRecords); metadata.EndOfCentralDirectory = lastCentralDirectoryRecord.Position + lastCentralDirectoryRecord.HeaderSize; metadata.CentralDirectoryHeaders = centralDirectoryRecords; metadata.EndOfLocalFileHeaders = endOfLocalFileHeadersPosition; metadata.SignatureCentralDirectoryHeaderIndex = packageSignatureFileMetadataIndex; AssertSignatureEntryMetadata(reader, metadata); return(metadata); }