From ed202ba48c15d3f6857ea58de439572b215a6d27 Mon Sep 17 00:00:00 2001 From: Roma Kolyago Date: Thu, 15 Oct 2026 22:55:17 +0300 Subject: [PATCH] Read encrypted zip entries written with a data descriptor --- .../Zip/SeekableZipHeaderFactory.Async.cs | 9 +- .../Common/Zip/SeekableZipHeaderFactory.cs | 6 +- .../Zip/StreamingZipHeaderFactory.Async.cs | 9 +- ...eamingZipHeaderFactory.CentralDirectory.cs | 253 +++++++++++++ .../Common/Zip/StreamingZipHeaderFactory.cs | 10 +- .../Common/Zip/ZipHeaderFactory.Async.cs | 20 +- .../Common/Zip/ZipHeaderFactory.cs | 22 +- .../Zip/ZipEncryptedDataDescriptorTests.cs | 347 ++++++++++++++++++ .../Zip.deflate.aes128.datadescriptor.zip | Bin 0 -> 3889 bytes .../Zip.deflate.aes192.datadescriptor.zip | Bin 0 -> 3909 bytes .../Zip.deflate.aes256.datadescriptor.zip | Bin 0 -> 3929 bytes .../Zip.deflate.zipcrypto.datadescriptor.zip | Bin 0 -> 3739 bytes .../Zip.store.aes256.datadescriptor.zip | Bin 0 -> 26506 bytes .../Zip.store.zipcrypto.datadescriptor.zip | Bin 0 -> 26316 bytes 14 files changed, 666 insertions(+), 10 deletions(-) create mode 100644 src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.CentralDirectory.cs create mode 100644 tests/SharpCompress.Test/Zip/ZipEncryptedDataDescriptorTests.cs create mode 100644 tests/TestArchives/Archives/Zip.deflate.aes128.datadescriptor.zip create mode 100644 tests/TestArchives/Archives/Zip.deflate.aes192.datadescriptor.zip create mode 100644 tests/TestArchives/Archives/Zip.deflate.aes256.datadescriptor.zip create mode 100644 tests/TestArchives/Archives/Zip.deflate.zipcrypto.datadescriptor.zip create mode 100644 tests/TestArchives/Archives/Zip.store.aes256.datadescriptor.zip create mode 100644 tests/TestArchives/Archives/Zip.store.zipcrypto.datadescriptor.zip diff --git a/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.Async.cs b/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.Async.cs index e9065f80..93b7dd63 100644 --- a/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.Async.cs +++ b/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.Async.cs @@ -138,15 +138,16 @@ internal sealed partial class SeekableZipHeaderFactory using var reader = new AsyncBinaryReader(stream, leaveOpen: true); #endif var signature = await reader.ReadUInt32Async().ConfigureAwait(false); - if ( - await ReadHeader(signature, reader, _zip64).ConfigureAwait(false) - is not LocalEntryHeader localEntryHeader - ) + if (signature != ENTRY_HEADER_BYTES) { throw new ArchiveOperationException(); } + // Sizes written to a data descriptor are only known from the central directory and are + // needed before the encryption header is loaded. + var localEntryHeader = await ReadLocalHeader(reader).ConfigureAwait(false); PopulateDirectoryEntryMetadata(localEntryHeader, directoryEntryHeader); + await LoadHeaderAsync(localEntryHeader, stream).ConfigureAwait(false); return localEntryHeader; } diff --git a/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs index c20163b9..52337b25 100644 --- a/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.cs @@ -146,12 +146,16 @@ internal sealed partial class SeekableZipHeaderFactory : ZipHeaderFactory stream.Seek(directoryEntryHeader.RelativeOffsetOfEntryHeader, SeekOrigin.Begin); var reader = new BinaryReader(stream); var signature = reader.ReadUInt32(); - if (ReadHeader(signature, reader, _zip64) is not LocalEntryHeader localEntryHeader) + if (signature != ENTRY_HEADER_BYTES) { throw new ArchiveOperationException(); } + // Sizes written to a data descriptor are only known from the central directory and are + // needed before the encryption header is loaded. + var localEntryHeader = ReadLocalHeader(reader); PopulateDirectoryEntryMetadata(localEntryHeader, directoryEntryHeader); + LoadHeader(localEntryHeader, stream); return localEntryHeader; } diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.Async.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.Async.cs index 3c5bd692..ca49a7d5 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.Async.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.Async.cs @@ -110,6 +110,8 @@ internal sealed partial class StreamingZipHeaderFactory continue; } + _headerFactory.SeekPastResolvedEntry(lastEntryHeader, _sharpCompressStream); + var pos = _sharpCompressStream.CanSeek ? (long?)_sharpCompressStream.Position : null; @@ -301,8 +303,12 @@ internal sealed partial class StreamingZipHeaderFactory localHeader.IsCrcAvailable = true; } + if (_headerFactory.IsResolvedDirectory(localHeader)) + { + header.HasData = false; + } // If we have CompressedSize, there is data to be read - if (localHeader.CompressedSize > 0) + else if (localHeader.CompressedSize > 0) { header.HasData = true; } // Check if zip is streaming ( Length is 0 and is declared in PostDataDescriptor ) @@ -317,6 +323,7 @@ internal sealed partial class StreamingZipHeaderFactory // Check if next data is PostDataDescriptor, streamed file with 0 length header.HasData = !IsHeader(nextHeaderBytes); + ThrowIfUnreadableEncryptedDirectory(localHeader, header.HasData); } else // We are not streaming and compressed size is 0, we have no data { diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.CentralDirectory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.CentralDirectory.cs new file mode 100644 index 00000000..86a56148 --- /dev/null +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.CentralDirectory.cs @@ -0,0 +1,253 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using SharpCompress.Common.Zip.Headers; +using SharpCompress.IO; + +namespace SharpCompress.Common.Zip; + +/// +/// Encrypted entries written with a post data descriptor have no sizes in their local header, and the +/// descriptor cannot be found by scanning encrypted data. When the archive stream is seekable, the sizes +/// are taken from the central directory, walked by a forward-only cursor so memory use stays constant +/// regardless of the number of entries. +/// +internal sealed partial class StreamingZipHeaderFactory +{ + private const string EncryptedDataDescriptorNotSupported = + "SharpCompress cannot currently read non-seekable Zip Streams with encrypted data that has been written in a non-seekable manner."; + + private IEnumerator? _centralDirectory; + private IAsyncEnumerator? _centralDirectoryAsync; + private bool _centralDirectoryUnavailable; + private bool _centralDirectoryExhausted; + private LocalEntryHeader? _resolvedEntry; + private long _resolvedEntryDataEnd; + + protected override bool TryResolveDescriptorSizes(ZipFileEntry entryHeader, Stream stream) + { + var seekableStream = GetSeekableStream(stream); + if ( + _centralDirectoryUnavailable + || seekableStream is null + || entryHeader is not LocalEntryHeader localHeader + ) + { + return false; + } + + var dataStart = seekableStream.Position; + try + { + var directoryEntry = FindDirectoryEntry(seekableStream, localHeader); + return directoryEntry is not null && Resolve(localHeader, directoryEntry, dataStart); + } + catch (Exception ex) when (ex is not OperationCanceledException) + { + // An unreadable central directory leaves the forward-only behavior in place. + _centralDirectoryUnavailable = true; + ResetCentralDirectory(); + return false; + } + finally + { + seekableStream.Position = dataStart; + } + } + + protected override async ValueTask TryResolveDescriptorSizesAsync( + ZipFileEntry entryHeader, + Stream stream + ) + { + var seekableStream = GetSeekableStream(stream); + if ( + _centralDirectoryUnavailable + || seekableStream is null + || entryHeader is not LocalEntryHeader localHeader + ) + { + return false; + } + + var dataStart = seekableStream.Position; + try + { + var directoryEntry = await FindDirectoryEntryAsync(seekableStream, localHeader) + .ConfigureAwait(false); + return directoryEntry is not null && Resolve(localHeader, directoryEntry, dataStart); + } + catch (Exception ex) when (ex is not OperationCanceledException) + { + // An unreadable central directory leaves the forward-only behavior in place. + _centralDirectoryUnavailable = true; + await ResetCentralDirectoryAsync().ConfigureAwait(false); + return false; + } + finally + { + seekableStream.Position = dataStart; + } + } + + private DirectoryEntryHeader? FindDirectoryEntry(Stream stream, LocalEntryHeader localHeader) + { + // The central directory normally lists entries in local header order, so the cursor only + // moves forward; a single restart covers archives that order it differently. + for (var pass = 0; pass < 2; pass++) + { + _centralDirectory ??= new SeekableZipHeaderFactory(null, ArchiveEncoding) + .ReadSeekableHeader(stream) + .GetEnumerator(); + while (!_centralDirectoryExhausted && _centralDirectory.MoveNext()) + { + if (IsMatch(_centralDirectory.Current, localHeader) is { } directoryEntry) + { + return directoryEntry; + } + } + + ResetCentralDirectory(); + } + + return null; + } + + private async ValueTask FindDirectoryEntryAsync( + Stream stream, + LocalEntryHeader localHeader + ) + { + // The central directory normally lists entries in local header order, so the cursor only + // moves forward; a single restart covers archives that order it differently. + for (var pass = 0; pass < 2; pass++) + { + _centralDirectoryAsync ??= new SeekableZipHeaderFactory(null, ArchiveEncoding) + .ReadSeekableHeaderAsync(stream) + .GetAsyncEnumerator(); + while ( + !_centralDirectoryExhausted + && await _centralDirectoryAsync.MoveNextAsync().ConfigureAwait(false) + ) + { + if (IsMatch(_centralDirectoryAsync.Current, localHeader) is { } directoryEntry) + { + return directoryEntry; + } + } + + await ResetCentralDirectoryAsync().ConfigureAwait(false); + } + + return null; + } + + private DirectoryEntryHeader? IsMatch(ZipHeader header, LocalEntryHeader localHeader) + { + switch (header) + { + case DirectoryEntryHeader directoryEntry + when string.Equals(directoryEntry.Name, localHeader.Name, StringComparison.Ordinal): + return directoryEntry; + case DirectoryEndHeader: + // The central directory enumerator does not stop at the end record. + _centralDirectoryExhausted = true; + return null; + default: + return null; + } + } + + private bool Resolve( + LocalEntryHeader localHeader, + DirectoryEntryHeader directoryEntry, + long dataStart + ) + { + localHeader.CompressedSize = directoryEntry.CompressedSize; + localHeader.UncompressedSize = directoryEntry.UncompressedSize; + localHeader.Crc = directoryEntry.Crc; + localHeader.IsCrcAvailable = true; + _resolvedEntry = localHeader; + _resolvedEntryDataEnd = dataStart + directoryEntry.CompressedSize; + return true; + } + + private void ResetCentralDirectory() + { + _centralDirectory?.Dispose(); + _centralDirectory = null; + _centralDirectoryExhausted = false; + } + + private async ValueTask ResetCentralDirectoryAsync() + { + if (_centralDirectoryAsync is not null) + { + await _centralDirectoryAsync.DisposeAsync().ConfigureAwait(false); + } + _centralDirectoryAsync = null; + _centralDirectoryExhausted = false; + } + + /// + /// Positions the stream at the data descriptor of an entry whose sizes came from the central + /// directory; decoders may stop short of the entry end (e.g. the WinZip AES authentication code). + /// + private void SeekPastResolvedEntry(LocalEntryHeader lastEntryHeader, Stream stream) + { + if (ReferenceEquals(lastEntryHeader, _resolvedEntry)) + { + stream.Position = _resolvedEntryDataEnd; + _resolvedEntry = null; + } + } + + /// + /// An encrypted directory resolved from the central directory carries only its encryption header, + /// which is skipped together with the data descriptor. + /// + private bool IsResolvedDirectory(LocalEntryHeader localHeader) => + localHeader.IsDirectory && ReferenceEquals(localHeader, _resolvedEntry); + + /// + /// Fails instead of silently ending the entry enumeration when an encrypted directory written with + /// a data descriptor has payload of unknown size (the following entries could not be located). + /// + private static void ThrowIfUnreadableEncryptedDirectory( + LocalEntryHeader localHeader, + bool hasData + ) + { + if ( + hasData + && localHeader.IsDirectory + && FlagUtility.HasFlag(localHeader.Flags, HeaderFlags.Encrypted) + ) + { + throw new NotSupportedException(EncryptedDataDescriptorNotSupported); + } + } + + /// + /// Returns the seekable stream underneath SharpCompress wrappers, or null when the archive can + /// only be read forward (a buffered only seeks within its buffer). + /// + private static Stream? GetSeekableStream(Stream stream) + { + while (stream is SharpCompressStream { IsPassthrough: true } sharpCompressStream) + { + stream = sharpCompressStream.BaseStream(); + } + + if (stream is SeekableSharpCompressStream seekableSharpCompressStream) + { + stream = seekableSharpCompressStream.BaseStream(); + } + + return stream is SharpCompressStream ? null + : stream.CanSeek ? stream + : null; + } +} diff --git a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs index df993a43..5684ed80 100644 --- a/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/StreamingZipHeaderFactory.cs @@ -6,7 +6,7 @@ using SharpCompress.IO; namespace SharpCompress.Common.Zip; -internal partial class StreamingZipHeaderFactory : ZipHeaderFactory +internal sealed partial class StreamingZipHeaderFactory : ZipHeaderFactory { private IEnumerable? _entries; @@ -47,6 +47,7 @@ internal partial class StreamingZipHeaderFactory : ZipHeaderFactory } // removed requirement for FixStreamedFileLocation() + SeekPastResolvedEntry(_lastEntryHeader, sharpCompressStream); var pos = sharpCompressStream.CanSeek ? (long?)sharpCompressStream.Position @@ -209,8 +210,12 @@ internal partial class StreamingZipHeaderFactory : ZipHeaderFactory localHeader.IsCrcAvailable = true; } + if (IsResolvedDirectory(localHeader)) + { + header.HasData = false; + } // If we have CompressedSize, there is data to be read - if (localHeader.CompressedSize > 0) + else if (localHeader.CompressedSize > 0) { header.HasData = true; } // Check if zip is streaming ( Length is 0 and is declared in PostDataDescriptor ) @@ -223,6 +228,7 @@ internal partial class StreamingZipHeaderFactory : ZipHeaderFactory // Check if next data is PostDataDescriptor, streamed file with 0 length header.HasData = !IsHeader(nextHeaderBytes); + ThrowIfUnreadableEncryptedDirectory(localHeader, header.HasData); } else // We are not streaming and compressed size is 0, we have no data { diff --git a/src/SharpCompress/Common/Zip/ZipHeaderFactory.Async.cs b/src/SharpCompress/Common/Zip/ZipHeaderFactory.Async.cs index bb420a59..2387a89c 100644 --- a/src/SharpCompress/Common/Zip/ZipHeaderFactory.Async.cs +++ b/src/SharpCompress/Common/Zip/ZipHeaderFactory.Async.cs @@ -93,13 +93,31 @@ internal partial class ZipHeaderFactory return entryHeader; } + /// + /// Asynchronous counterpart of . + /// + protected virtual ValueTask TryResolveDescriptorSizesAsync( + ZipFileEntry entryHeader, + Stream stream + ) => new(false); + /// /// Loads encryption metadata and stream positioning for a header using async reads where needed. /// - private async ValueTask LoadHeaderAsync(ZipFileEntry entryHeader, Stream stream) + protected async ValueTask LoadHeaderAsync(ZipFileEntry entryHeader, Stream stream) { if (FlagUtility.HasFlag(entryHeader.Flags, HeaderFlags.Encrypted)) { + if ( + entryHeader.CompressedSize == 0 + && FlagUtility.HasFlag(entryHeader.Flags, HeaderFlags.UsePostDataDescriptor) + ) + { + // The sizes are only in the data descriptor, which cannot be located by scanning + // encrypted data; a seekable stream can take them from the central directory. + await TryResolveDescriptorSizesAsync(entryHeader, stream).ConfigureAwait(false); + } + if ( !entryHeader.IsDirectory && entryHeader.CompressedSize == 0 diff --git a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs index cabe6376..d8c4fb25 100644 --- a/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs +++ b/src/SharpCompress/Common/Zip/ZipHeaderFactory.cs @@ -36,6 +36,16 @@ internal partial class ZipHeaderFactory _archiveEncoding = archiveEncoding; } + protected IArchiveEncoding ArchiveEncoding => _archiveEncoding; + + /// + /// Populates the sizes of an encrypted entry that was written with a post data descriptor and + /// therefore has no sizes in its local header. + /// + /// when was populated. + protected virtual bool TryResolveDescriptorSizes(ZipFileEntry entryHeader, Stream stream) => + false; + protected ZipHeader? ReadHeader(uint headerBytes, BinaryReader reader, bool zip64 = false) { switch (headerBytes) @@ -133,10 +143,20 @@ internal partial class ZipHeaderFactory } } - private void LoadHeader(ZipFileEntry entryHeader, Stream stream) + protected void LoadHeader(ZipFileEntry entryHeader, Stream stream) { if (FlagUtility.HasFlag(entryHeader.Flags, HeaderFlags.Encrypted)) { + if ( + entryHeader.CompressedSize == 0 + && FlagUtility.HasFlag(entryHeader.Flags, HeaderFlags.UsePostDataDescriptor) + ) + { + // The sizes are only in the data descriptor, which cannot be located by scanning + // encrypted data; a seekable stream can take them from the central directory. + TryResolveDescriptorSizes(entryHeader, stream); + } + if ( !entryHeader.IsDirectory && entryHeader.CompressedSize == 0 diff --git a/tests/SharpCompress.Test/Zip/ZipEncryptedDataDescriptorTests.cs b/tests/SharpCompress.Test/Zip/ZipEncryptedDataDescriptorTests.cs new file mode 100644 index 00000000..0eb13ab2 --- /dev/null +++ b/tests/SharpCompress.Test/Zip/ZipEncryptedDataDescriptorTests.cs @@ -0,0 +1,347 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpCompress.Archives.Zip; +using SharpCompress.Common; +using SharpCompress.Readers; +using SharpCompress.Readers.Zip; +using SharpCompress.Test.Mocks; +using Xunit; + +namespace SharpCompress.Test.Zip; + +/// +/// Archives written by streaming encryptors (these fixtures by Aspose.Zip) encrypt every entry, including +/// directories, and set the post data descriptor flag with zero sizes in the local header. The sizes are +/// only in the data descriptor and the central directory. +/// +public class ZipEncryptedDataDescriptorTests : TestBase +{ + private const string Password = "test"; + + public static TheoryData Archives => + new() + { + "Zip.deflate.zipcrypto.datadescriptor.zip", + "Zip.deflate.aes128.datadescriptor.zip", + "Zip.deflate.aes192.datadescriptor.zip", + "Zip.deflate.aes256.datadescriptor.zip", + "Zip.store.zipcrypto.datadescriptor.zip", + "Zip.store.aes256.datadescriptor.zip", + }; + + [Theory] + [MemberData(nameof(Archives))] + public void Reader_Reads_All_Entries(string archive) + { + using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archive)); + using var reader = ZipReader.OpenReader(stream, Options()); + + var contents = new Dictionary(); + while (reader.MoveToNextEntry()) + { + contents.Add(reader.Entry.Key!, reader.Entry.IsDirectory ? [] : Read(reader)); + } + + AssertExpected(contents); + } + + [Theory] + [MemberData(nameof(Archives))] + public async ValueTask Reader_Reads_All_Entries_Async(string archive) + { + using Stream stream = new AsyncOnlyStream( + File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archive)) + ); + await using var reader = await ReaderFactory.OpenAsyncReader(stream, Options()); + + var contents = new Dictionary(); + while (await reader.MoveToNextEntryAsync()) + { + contents.Add( + reader.Entry.Key!, + reader.Entry.IsDirectory ? [] : await ReadAsync(reader) + ); + } + + AssertExpected(contents); + } + + [Theory] + [MemberData(nameof(Archives))] + public void ReaderFactory_Reads_Entries_When_Some_Are_Skipped(string archive) + { + using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archive)); + using var reader = ReaderFactory.OpenReader(stream, Options().WithLookForHeader(true)); + + var keys = new List(); + while (reader.MoveToNextEntry()) + { + keys.Add(reader.Entry.Key!); + if (reader.Entry.Key == "data/sub/binary.bin") + { + // partially read, the rest is skipped by the reader + using var entryStream = reader.OpenEntryStream(); + Assert.Equal(1, entryStream.Read(new byte[1], 0, 1)); + } + else if (reader.Entry.Key == "data/empty.txt") + { + Assert.Empty(Read(reader)); + } + // data/readme.txt is never opened + } + + Assert.Equal(ExpectedEntries.Keys.OrderBy(k => k), keys.OrderBy(k => k)); + } + + [Theory] + [MemberData(nameof(Archives))] + public async ValueTask Reader_Reads_Entries_When_Some_Are_Skipped_Async(string archive) + { + using Stream stream = new AsyncOnlyStream( + File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archive)) + ); + await using var reader = await ReaderFactory.OpenAsyncReader(stream, Options()); + + string? readmeKey = null; + var count = 0; + while (await reader.MoveToNextEntryAsync()) + { + count++; + if (reader.Entry.Key == "data/readme.txt") + { + readmeKey = reader.Entry.Key; + Assert.Equal(ExpectedEntries[readmeKey], await ReadAsync(reader)); + } + // every other entry is skipped without being opened + } + + Assert.Equal(ExpectedEntries.Count, count); + Assert.NotNull(readmeKey); + } + + [Theory] + [MemberData(nameof(Archives))] + public void Reader_Reports_Sizes_From_Central_Directory(string archive) + { + using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archive)); + using var reader = ZipReader.OpenReader(stream, Options()); + + var files = 0; + while (reader.MoveToNextEntry()) + { + if (!reader.Entry.IsDirectory) + { + files++; + Assert.Equal(ExpectedEntries[reader.Entry.Key!].Length, reader.Entry.Size); + } + } + + Assert.Equal(3, files); + } + + [Theory] + [MemberData(nameof(Archives))] + public void Archive_Reads_All_Entries(string archive) + { + using var zip = ZipArchive.OpenArchive( + Path.Combine(TEST_ARCHIVES_PATH, archive), + Options() + ); + + var contents = new Dictionary(); + foreach (var entry in zip.Entries) + { + if (entry.IsDirectory) + { + contents.Add(entry.Key!, []); + continue; + } + + using var entryStream = entry.OpenEntryStream(); + using var output = new MemoryStream(); + entryStream.CopyTo(output); + contents.Add(entry.Key!, output.ToArray()); + } + + AssertExpected(contents); + } + + [Theory] + [MemberData(nameof(Archives))] + public async ValueTask Archive_Reads_All_Entries_Async(string archive) + { + using Stream stream = new AsyncOnlyStream( + File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archive)) + ); + await using var zip = await ZipArchive.OpenAsyncArchive(stream, Options()); + + var contents = new Dictionary(); + await foreach (var entry in zip.EntriesAsync) + { + if (entry.IsDirectory) + { + contents.Add(entry.Key!, []); + continue; + } + +#if LEGACY_DOTNET + using var entryStream = await entry.OpenEntryStreamAsync(); +#else + await using var entryStream = await entry.OpenEntryStreamAsync(); +#endif + using var output = new MemoryStream(); + await entryStream.CopyToAsync(output); + contents.Add(entry.Key!, output.ToArray()); + } + + AssertExpected(contents); + } + + [Theory] + [MemberData(nameof(Archives))] + public void Wrong_Password_Is_Rejected(string archive) + { + var options = Options() with { Password = "wrong" }; + var expected = archive.Contains("zipcrypto") + ? typeof(CryptographicException) + : typeof(InvalidFormatException); + + using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archive))) + { + using var reader = ZipReader.OpenReader(stream, options); + var exception = Record.Exception(() => + { + while (reader.MoveToNextEntry()) + { + if (!reader.Entry.IsDirectory) + { + Read(reader); + } + } + }); + Assert.IsType(expected, exception); + } + + using var zip = ZipArchive.OpenArchive(Path.Combine(TEST_ARCHIVES_PATH, archive), options); + var archiveException = Record.Exception(() => + { + foreach (var entry in zip.Entries.Where(e => !e.IsDirectory)) + { + using var entryStream = entry.OpenEntryStream(); + entryStream.CopyTo(Stream.Null); + } + }); + Assert.IsType(expected, archiveException); + } + + [Theory] + [MemberData(nameof(Archives))] + public void NonSeekable_Stream_Is_Not_Supported(string archive) + { + // Without the central directory the encrypted entries cannot be delimited; this must fail + // instead of silently ending the enumeration after the first entry. + using Stream stream = new ForwardOnlyStream( + File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archive)) + ); + using var reader = ZipReader.OpenReader(stream, Options()); + + Assert.Throws(() => + { + while (reader.MoveToNextEntry()) + { + if (!reader.Entry.IsDirectory) + { + Read(reader); + } + } + }); + } + + [Theory] + [MemberData(nameof(Archives))] + public async ValueTask NonSeekable_Stream_Is_Not_Supported_Async(string archive) + { + using Stream stream = new ForwardOnlyStream( + File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, archive)) + ); + // ZipReader directly: ReaderFactory format detection would report the failure as an unknown format. + await using var reader = (IAsyncReader) + ZipReader.OpenReader(new AsyncOnlyStream(stream, disposeStream: false), Options()); + + await Assert.ThrowsAsync(async () => + { + while (await reader.MoveToNextEntryAsync()) + { + if (!reader.Entry.IsDirectory) + { + await ReadAsync(reader); + } + } + }); + } + + private static ReaderOptions Options() => new() { Password = Password }; + + private static Dictionary ExpectedEntries => + new() + { + ["data/"] = [], + ["data/readme.txt"] = Encoding.UTF8.GetBytes( + string.Concat( + Enumerable + .Range(0, 100) + .Select(i => $"line {i}: the quick brown fox jumps over the lazy dog\n") + ) + ), + ["data/empty.txt"] = [], + ["data/sub/"] = [], + ["data/sub/binary.bin"] = Binary(20000), + }; + + internal static byte[] Binary(int length) + { + var bytes = new byte[length]; + for (var i = 0; i < length; i++) + { + bytes[i] = (byte)(((uint)i * 2654435761u) >> 24); + } + return bytes; + } + + private static void AssertExpected(Dictionary contents) + { + var expected = ExpectedEntries; + Assert.Equal(expected.Keys.OrderBy(k => k), contents.Keys.OrderBy(k => k)); + foreach (var entry in expected) + { + Assert.True( + entry.Value.SequenceEqual(contents[entry.Key]), + $"content mismatch for {entry.Key}" + ); + } + } + + private static byte[] Read(IReader reader) + { + using var entryStream = reader.OpenEntryStream(); + using var output = new MemoryStream(); + entryStream.CopyTo(output); + return output.ToArray(); + } + + private static async ValueTask ReadAsync(IAsyncReader reader) + { +#if LEGACY_DOTNET + using var entryStream = await reader.OpenEntryStreamAsync(); +#else + await using var entryStream = await reader.OpenEntryStreamAsync(); +#endif + using var output = new MemoryStream(); + await entryStream.CopyToAsync(output); + return output.ToArray(); + } +} diff --git a/tests/TestArchives/Archives/Zip.deflate.aes128.datadescriptor.zip b/tests/TestArchives/Archives/Zip.deflate.aes128.datadescriptor.zip new file mode 100644 index 0000000000000000000000000000000000000000..7ffe47f7074802af22ca95284f080021e42db37d GIT binary patch literal 3889 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 literal 0 HcmV?d00001 diff --git a/tests/TestArchives/Archives/Zip.deflate.aes192.datadescriptor.zip b/tests/TestArchives/Archives/Zip.deflate.aes192.datadescriptor.zip new file mode 100644 index 0000000000000000000000000000000000000000..8f3251f9f0ccf6efdd285d93a3564b0f1d2ba408 GIT binary patch literal 3909 zcmWIWW@h1H;ABW

J!6Wk3R~4EhWyi6x2pTnq|eVMYcChJp*TKhKD{%NUTd08GR9 zj5FC8m>3*gnHU(}r|K4_o$?WBwskcOTd-sQ``FX`cRun82Y9n{fXtBq5ey6rAe%+7 z+RP8LxhOR;B{x;Cq@o1b4GAkDZg?QJ66^*TAMOSYhLd&w7X-MzoV}>%$*PslZLHj4 zj+kuKto7ZV8FGbh%kt2`i6@xa%M~>n+0x?|u2j%u>zB))$J)Ow+UMWXaD09c1`^3M+?UCu46Gxh_wB8H2{7Ir`?dcD> z`q{d&787}9?$Mge%9JLN`ZO)S`n2U_me(!G*86Qws=c~)Qny3p!u>CvpRMspH++11qsd&EFn zpTE`l-19Y^LYo=l(W*zT}^==7W~ly1f-E zs+)|hPQQHCU7T234~sE3Mh1peBKTsA4;EvoxdkPa=n)1>Bnq1$5eDPKBaDGznXU6i zt<#J4AKP=gqR5LybZTj|9@j&X%^21>(FDP>d&+*f^XnQrq!1sx1;=7leFCV>Co#-%s zed5n`+0T|GA^&?Ij%og~^HuK~>)HwQSH;(nzdL*16nHzyNCOu1{etNu5yjTTdBo)Dxlai>CJ zjmB<6#XXxFCX`Ka`r~{(Mph%J&*sl8fu&Q{8AnK`&YbwI=U0pTuioo5YiGT_|Ds<< zZN`BmCX099pSvtET!K+qvnh#-Wm79(+61j>r_*F7&y|>a=1$1eP5gox(V@#EA78O) zb0)5Dd%eYzFkZd{wfwr|h8lc75%ii8R5VOe4u>?5SOe!1+$M~jtr zYp%Gp^Y*I3fVNE!tIenUcqO@-p4mQ*DZD%C*<#W zyDr{1zxrZVyW@kKzh3OB31~6YicYJIz1;M}rCwv}%*i|QO)FE5+}-lGqM+`Gt&Aoc z_sf^hFS8r{nBu_F)OvT*{vv_tA1WHG{gl-&{JAeFlcXXk`{;IUn$rJ1j_`2bi5<#| zSDh`(cywPbQ}QZj-?DjjiO-hzze_RkG1A*9;K@?JuXKFfyp(0;BD2|oSa(dn`DDwS z6ET6?pK9-W`ez!)8tsW{O4^NE57)JAcq6=7_|Ho_zvy?n*KbYt-dn!$;K3UcWBBGA zH2ZE@ur@55M<9l+YTwm~4C~h&U8r_TY>}nV|2uNCgFp3$VeGtkodZy`f)#aBVr zuZ3sM7k`O+QmehyGf6W6ob=AJFyye2dmT9!|^2=2dzWXiZ;O^Ah7q=pl^AuB1grk_$&Wn8S z+03-JJgk4c=tlZ2^Q@I2C+=mO+;nQ0>!Y8GjH4SfF0=kTWz{@;iGabL3u}CjNQVY? z=1VWWJULymc*URjOVVdt_c?5t^3>J+`hw``Oa5+|mD{`bXmCu9lZfFa-7u{!4}yzS z)}Jv>mq-w}D;n&x9xiWcgt;(FB9`fZH(-AGP zXN}utulxM8^3B^5lUlB@iWenDmY!fJd}c2rBq=!e#bQe<8K(%jYj2)Deqg*l7uM9$9QJ(@D{#Pd((o3||fD$)I1`IO7s#93dZPX6t_ z?^~L-ks&MGUU0_J|9SJaysWW|h~W6Oytr(;@ctft5smk;RN-150dZAzQHVS5_&vAW0sAjC+|*YiwSoO zoZq9=lwVT{<7M&h~4a762X^qwTxw(hA53 zhjs+3KC#uQK45HHY?64XcfP~P*7ogtgwkfZSf;#L^tEJ$wMk^V(XG#$zf10pcG&hO za`)=f?V7tIeA2>arZ14a8a-o|TK}I#MW=pk3Y7>{)7(6Rv-|kAvYRn`-yEA8o8`nK zZ!ej)^ozV`Q+n~jc5dGEqlvVt@RT87y9JdNtV)VU8hdLrqv(2k6k=xZ}frNy7T0p1B_0O!Y|8uz2T^S`egIe zWmdfYDVvSN7fS9a&o7c#Uw7)@s@)=*4;BU%@l}6Q&Qm#iUsGbr3(39pbxc!Jf2uUC zN{!g_xlDOyhq(TNSkWV;_N(Ot4N|fete*d$`|wj=u3yg?#7=SidcJdA<>ck(cm3bu zVr|sAFYwrte|4dMuB`gq3-F z?5Bu*6!`9T?(y^|?-p&Im%mE&&*BZwkIbw5@hnbYUqD(-+=WYK$}67UQfRc=u*%1o z``}#OT+c-Zr|LY&j$5l5Rp!}wO+Z=LX`iha-|YL5p0Uc^=B@pv_iwoW zfAh-1X21I!zNNDQe5CWcG;~YKXmp#1M<~zt1V3Xn1YYUOA)g zd(1?oz_iq7Jk{4Cmzo^5XDg2T@J%`lrFtTh)Fuk>hi>^PiP@ODG{;w=I)bp{{# zYI=9Bnr_k~xqZpI0|HOaGWl(q)g!?5KYK&;xA&z6Mz_9**z95#`{CL4zWl$r_JmCf zo|?)RIjVDqPw8U3k{s777Tc6_Cau5ivVyKcAcNg2V+pfoH4OQ;9tAyR&u{M)nfkhY z+V&Y&>y#D#E-TUzKb}=Bv^uwA!k%?;KmIJAxJ!>;CwJvdo`xccWpRhz);xE4QTNcq z^cAaP`AA zmjb*oZGg47K|LXmxgflRv5J8K(jz0gUxdvrm~TLBc#u6Hyo6DQ32GO)EqZ)bf!gXI zYe4ud<9e7?WVGC|*#e6?P@5cN0|+l+)MbWx2xJS{E%X3yRyL4%tPHFS{7eiC3cMg5 E0D2c&SO5S3 literal 0 HcmV?d00001 diff --git a/tests/TestArchives/Archives/Zip.deflate.aes256.datadescriptor.zip b/tests/TestArchives/Archives/Zip.deflate.aes256.datadescriptor.zip new file mode 100644 index 0000000000000000000000000000000000000000..cdb982366286e407037a08c78d6642a654f207ea GIT binary patch literal 3929 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 literal 0 HcmV?d00001 diff --git a/tests/TestArchives/Archives/Zip.deflate.zipcrypto.datadescriptor.zip b/tests/TestArchives/Archives/Zip.deflate.zipcrypto.datadescriptor.zip new file mode 100644 index 0000000000000000000000000000000000000000..8a78f052e772a317ad10c6d7f3f7731dbb7f7baa GIT binary patch literal 3739 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 W;LXYgGK7_ZmEi^>1H)Qyqyhj3HA~R| literal 0 HcmV?d00001 diff --git a/tests/TestArchives/Archives/Zip.store.aes256.datadescriptor.zip b/tests/TestArchives/Archives/Zip.store.aes256.datadescriptor.zip new file mode 100644 index 0000000000000000000000000000000000000000..e2b86db0e8f22088791c9c47e4c380cc6048b52c GIT binary patch literal 26506 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�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

nCgK^9idx}RtfT+QF(JxCN3zp)u{TjLA?L7 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 YS}?$yl?`MbD+4P7KNAB(YAT2a0Jg)FumAu6 literal 0 HcmV?d00001 diff --git a/tests/TestArchives/Archives/Zip.store.zipcrypto.datadescriptor.zip b/tests/TestArchives/Archives/Zip.store.zipcrypto.datadescriptor.zip new file mode 100644 index 0000000000000000000000000000000000000000..1a712b2a6684082dcc2a880a7e1edbe4b1b9d587 GIT binary patch literal 26316 zcmWIWW@h1H;ACK6P>J!6Wk3R~3@QvMi6x2pTnq|eVMYcChJp*TKhKD{%NUTd08GR9 zZd~&wi^Q|=&N%2YF~FOh1EhfmL@+Qg;I@JvW<^nIVoGkRUP(m>vSkS?A(lN5TM4!d z#;<$Gc5!ZjnP4)za-^Oh&(|{RgSS@M)Rl1io4*c8k%ncGd|a@H{U8p|!#cJ}SktY|tLW8L^-fzl== zzrHH}$u$RU=T2Goq$lLEi(&WwBv(7rY40{q&WxK~ecLf{`_7CB_a(GfJZqY3Ts(2^ z>KE+xfy*{1>ZKe=w&4%Cb0JAO{^1ACUk-l*xP;UmK6!o0RpG?b*X|lQ9Cqw=9@U%+ zTL0hpz*W1Z=i?&%oVz(kejZ}@Ys39x>t6}3Bn>HPyVbit-^jhfQPVMnO~m$N{dco# zOI^BLS5E#U-@i1utkgXxVb%1!hy4bewu^nI%(GcuVRBw5St_Cbd6bBf)jRWBe+rf3 zPR~(YS$^@}>ZCK==0*`;&x^(`H1N)kXpFf2H|_q7WS6`rDwg~2${5=-|JjrqzTUW0 zGQEJe)4o2%_gWM~e)b_50agbqThrx@lfqw|*dcFsuI+r2S-X-z-0bbG2GdVWJ*MQ# z8~SbQ%7dnL$!9%_kA9k26%g(#lq~z-H=p%i!iH07(sx5ntxzfMNZGXfTzspZqAtt( ze94MnvFfOUQ(J#4C$YW%b#PK;9mu^aoZP%ejBcz`_62;@2(rS0DH%d`qD0 zaZbcS(|s@Vga1vD@#~o{;@E3{dXl~U^L5J)uIt}y&Y^!bVu#xYt5Dh0>5?X`|PFW0=8oFuc4cRMFj!){sYfTtm?tsiwWmu~A5VUI64C@Na}?&Gqp&-h>J zo>4bRUozp{0V#iv*gIdEi|6PoBrOQ4Q4+k{ThF}7nQLC3sVK7&W7k=A(M4((a?{lV zOcsml=O1xj$@2VZ4WrLJN-w{vC6^qNadX1A;CERy*)|N49I8Gp8@(@MR0 zlO*R)j#XTjW#90++vob6*k!Y|e^#8Wsod@{b7uOob#o1`thL(wG3iQX^Sl2qG+ya` z_6psR;;}OCOkkYurT2+c$aidCsW$O)@5Irs!+VK z!JmIxH$PXk+zzq%-uQP4@Acf)GoJV2Hfc7qzRle*FCe1VYyI^(9#z~S7cz9G{a2k+ z;O>^lCozpx@J#;4UB5UFHp+V~_J6xVK$zT$WkA}z;;BwxyAM9HNMR&>{li?)vhS7YCF{+>Uiec6Z>?|tvhD5?OIXz za~{|I3-@EgR5TkHlX6u$qI+j>DL2K=o`0@iuJ=E;Md~Ha+|wPGqdmHJs5zeP^5oF^ z({sh|!a2>i_7(Tu*t}&aC<%0^dwz7oU!|LT>JAD=YL2}*^|UB@rtN-9k;>f#0S0{j zzqECKU0Dz^XSE{#@~XF|%#xXRJrhYeQCd}PuV$Tl>6>_*#NjC+EWR@tR4c;IIC#%# ze9~dK%f0q(uXqm4NO%%(W7FAxuDwCUR}PDG z{)mydzc~2b6}ju%?Sh1)4E`I1r5V=k_2RnpK<4C^yy{GD-?)^j)l)w(w5o0_G}vbM zW3^tD>r1y!OSyC{HD@eu$PRaO4cNqfi1F?0=>Nxf>YePuj^_xnetD7@zwUX#(d6c* z-pA@^UR%EI!>i>*^&Au!uGUFt95&6Xw*fM?eG1yMI0GUy%L$F z@l*Sn(Om}YoOA|NV#-^za{=WKL4^{YI+VUJYsk7|cO7aDE_%$lyhyU4e_uG8qwwVjs=E#Ay7So3E7T>0Az7<#`g%y?mT>x%w#l?QLF z{!W~1xBGVft&5jcIKTBbc_~fd487c{amVh4RpB-kgZG|uO;_<=;=j4AVbb)Z;?GS_i zht7yiu{y5No*C!iTpGErV1sCn^c4MuG?y*%>_+y_%$lxL@%;9l+t;vM|I(Uo$M^NU zt$Ju9(Kg>v$Z+>6me49xl>(PPy9=Z92PM(cVk2&(VWa`b;e3}|@-q*>%;I7zfTYrm(b5^eV zH{-$Fpg%FYmYTb4^o(=K{d#zbm~o_q!|X{0584)HsL0Kq@tMt*_tY+FHMhuoHfw|E zUGd+qGMw8oUwQq^LY^HwZ|BxOt+3qt;KLWrigO$0JrMJ75A)!VT>kNo=?U5MkDdBC z4NgrzF}>;8f)$HDmlv{kwkL2*S+wZ+znyNftsB}-1x@*8$6V}Z;af0;$u>l1hK;?n z&W#Qw!Gvaae{GMXE+eTG=dLy?x}=uPT{g2?SLg7Phx-%nY5PCh^s>ULeC?YH=heR7 zZcVA?n5h$Z;fHZ-Q~SBQ+A=fO+^SD=j_K#Wu(r>}XS332jkN0zCrnwh|F2k9@b6bY z-Z}r98|$+`w^he%NieUWj2Y+KXG;zoY0s>GYqxj#-#{C|_wn+ZB2OLWUU%Wct=Ma4 zPcKw{b}(x0BIap=iC-7~-|09-;_d4r8q%dlPY4~^6zKIK&w2j7C^y&NM`PLldH<}< z^9go(dXPK8-o4~iWCq{UqTnd5n_lsykBTx?I^$B`ANRcQ`byTb{$*2HR$Smn>6kb@ z%{@_O;?CxPOX!?8y>XVMmk&GG`ngS3T3PpiTfh0{<@}dU!Bs~Sx_SR} zF)!HokNei4iWgEW23_YLzUPlm{&S6=Bj(q;ESZbCyd_TS-J8V^JYH0s-0}3tv9mkB zK1>cb6kF&g#=dbw-=+{Y;f^hztN4r_WIfPvO#VFo>5Zm{Hb3=EZVMOv|5LQH_-9Z4 z8_u}DPfx|axPPGADebMgbK~;f+-5HBe;&~(+NJDPzeEan_@&`(d0#Aai|6c;k)tPn!)-`%L}h_v%(+WA!o- z5C0_#*ME3-@#nURj>d}(I&Sy!*RDS4nq<)PqWb0S#99BcnCIpD7;g;9;tVmcTsZ&U zDW?>HR-dk(_fc~g3OB5k+g0MZ`*!@^?I9c&itm(cvN31ccF^zjd(YFh6Qhl;&nUQL z*5X=eBf2;AsM1lvJ+5yV>Pk)@^x8kuz*F7MN2zQxQ$S=-j#W$Le|CA3AS0H$e2cEw zeUZ!1W#6#$M)+OUHz!ZLFX=a0a$;R)Vapl=lU0#Zc~Z>S*ZQs1JLSBqDpQv26zhZ& z{H1k!|He!!n>(*a!gKaA|K=viQwy3}L}msmN#}g?J5k8;$KoirNp`}UlSK`iWD}n0 zZTFab`-`0U%DS+d!OuJS)^6T-S>yD(1&vWp)0=MhSlqO_^Yg6K#{;$Z-MPDNO;`Uv;S8`ra zP@eZ-B7gRT=`Y4#@u$j_WS0K`^x$a&r9rC_VB}m2{A|h zuX@oF_fbatOjYOZq9=t_-sxLPQ(iEKOn#*HXi~dPhmi;CtK%QIzA!i2m;YJH$`CW> zCFcowgV2SG_no;d9OdzP%3LP_i&};U7nc6v-JKu4eu9G8^|`B8+Rt9OcK3drW1-IP zi~qU)Xi)gwc}~TZYfHIlqwlRXizY7FlE5`pDoSbbQBN1{lI_>nol^?V&XzL07ueo4 zdH%&lp;dJgH!Yq1|M8X!<(7gsf?AfpmNAuWT>E;Xh0x3wrY&Zb>$QITySs5pa3`nO zjU8`xt1r8`+1zaPY7xDo?>CtTdnB`U3YM$fyY|m*y9@7Pjpf&Drzh5A8s;&b?T)uU z^yqn5^a1q--)TkhOJc-IQuY4lSv&gdDdKx*ZFx?7)@tYFbIML69(7*Xcrla>H6?@D>fIzE}--|)Qgai>Jp?tj5={_58+Hi)*V?A;p_TD31LqS(A*e^GLE;I{n| z%Ig#tm|RIxIViV6`Nw~!wP{|vYa+PRB%b?7^xT;7<>!M>X>!jVvUE%6@H-r=519I6 z&cs`#65l7bKXaTid++7-UZ<A9<>>K^HMm;b8Fz2L{^c}fbILFKpI zrI$=P9I>3)my1((M!x?Ok-62+{1)~8-tbyP;bi&Bij;T9CjXi|=}1~<@rKB!5-T>m zTlm~Q;e2x2sTMxwyOnP&7caW<)>_yvKQl*nt^F;(#nwwCv#vVa^{-vc>G`p!cY1o! zKdB+I5k6 z-G)X-o5lCKKm0y@b|c$cmPZ}O>VzF{-Zi+%P@nhw)|Go)Zca=uuTJ1QX)Ew_!$K1| zMW>uiEH9o~9Q4nhde2EZx38Arm|ysXnSbOaPN@?)(#tAQ!!z&aTBbP7Uu)j#pHqB! z)s{1;VAnznq;*(V2OFO+juypyhS zmWf~7C&w1I@nw+Y?2Qh0mIh_K{VX(9?SQW00(tvSuO}Wl@Ak5LYoMoa?rPn>UnhTt z&#KNY5to0pGT+Ec^n@ALtY@cp>oUBqI4{3jH_+(xg%zK(mET#JZ(Vn-e}_(soUO|H z^N%k1$vJK*%+;{py0@M|=!ed=>A%gAn6C9q-J_yBUolwE_Wcam>TMtYEnoS3>7-44 z2X@yA?UJtUH7WJg?+lMUw$waG-s;4g;Ow_W3yzg(mK=)7mD|RDT>0;xf}YjEzCRBZ z@ybmW@^W4>f77IMABDKy96I9qM)m0CBbJf&Euy!Qj=3NFFe@mSN2c?g!&$Kz>u!oZ z{BOQy$+6c?7qu4acRtwJ9L*m4^Wd*IQAeg1D^_t|dOolC;fsU2@3hn@q}Cp;%S^Xd zW)PZU!?!POafq0&sM)ix(|i_RNWT>^^RX7^rMnq@ihQ;|9u{}Vd~JTbC7hXUi^BKY zE2JjL7N=D0a4&w(ujEkCe}1)`;uL=Vwovv*l_h`Mo=92CG?m-koA@X^X|tJc!j|>E zF^g_Zi?1)?>zWh%;%a7yN%4|<^TSSV@nVeG>G9%m=*hZEwb8o{MzBfAW~<0(+qA~M z-&9;>Vb2t`m(#@k#{4TLo60zks~lM_rg?I5-mx<}M?Uo3+@<@q{%17j>F0YEDkpyo z5>~q`8|%6J@cxNbTeW|53Qf;?oB43ooPV$OxA~kf-Or_-vS!x@X?vI8MH>z)mg`K- z=F6(veC5fsf1eKjkZWdS`xqDXtK+;*RdA@Uz^d>mhArQZuCvl@Okq_GU#aVsZqJsN zYT4PS!`D5h`>fF&pC7Abi}p=%5njad^OQ^Yw?8l0zZ=eS5sVgNjb?g#Jw{Hq#`K=# zimhq#zhlGaIZU{*&O5LnPA@Yd;(M8+f5J}=&iUWB1lFED+SRtT?4h_9%ac>0kykxt zc22sxNA^jz|D{W5#+DbhS*Pgk@vvO~K({6+-BNX5`D&q~H^k41c7Hj#wy}TaVjrj5+U5QS zi#3<4Ev#6qP{VQ1(d=k5pCU)%$z97IY<;2qCT)xB*4ek#Z+N*iNT=id?swmX&Yvt` z@#czc+~V-yk)qp!4KGvX)qarF6?k$xs%p()&WEnP`TG-(sA=j+O2{i{>$RQE7 zyHzB1R$q3s>itvJ@wxVM_)@Y(mRa0Q`6l#j(u7+_zp9-)v9j)C&mQ?p{QOfarl<6! zH#Kwrb-DEGGE->i;*I~yr%wBpc%hrrk{+OY>_v+|G67NBFpzHht|4JSh{K zwP|^DaZJj;>q60cPwm;nxG+rZtiyZB6wt6J_l$zK+e8=`R*B#n7UhEti>BrllvJXR zio%9m6*fagMPd924$KwH<}Z_;%E$8(WEW`kmGBTOC(N$m(j=@Sy$Ri@BfX4!_`l8F zdn0L|rC|y2)(9h8la!g4SX8N(l$nP-+6(hXg8wS;XfKTKJBvBt?dczLe&ya1WK(UG zbTkrZTU?)fq{xPKlJ?#A7ydLF=&pJb`1w{`bmOYI2bV3fOsUGTJs>mpRH9hl^BYBL z&fdA$sulKhRZY&H?MoitDF6LvKrbdwH{`$!4|v%wHSbi=^u-fgulP7y+lKC&ke*3VUdH<5NUSj$cF%Np5 znDFYe=C#}lpMPXRYs7sc;c}I}42OM!Zm-^R%-i&6YjaO}tWz6T>54zz356w1rx)pL zIOAsUSIpsP6szz%jw*%6t$Tu9RSsN8-MCDBepcbTEcYJsRYLEhg+9jSPwSCOb5FhO zba*_C{x-AGV)s&u(8mx$|PezxuGZpJ5-*l#NLt^e`X zbbF;~=+f;bO(*VpcjWRay%BR_5fpUXWt{js^;~WPHi7zPoi7S%_ddLIE)05=c#g4IF=Ktyclm^yfg3j!m#+~^+3d$3 z?%1{Xd?oMtbauNJyHB3GA}Mbc((d)7hgV{C z0dpb$xrg5_Ps&UP$lbzbHtlDG?!{SK7HUnE;MEkp#wnBAb0t+Sf46#8kkI7Nh{xO< zk$)Ch{hzNlFE#4@zFB{AR!qLan{t84sjh5>gJM`Tzt265X;=KbWmxSlz20gk_INSp zIl0ZXlRA9%KJr)WuUq!wx@oBP`v29L;ioQEh#Xryy;t~rZ1z1l%j6kj5Q>v;5!x1f0DeH+u&EUAE7ir&Q{8cpdKh7x^*dL4m4IT#MFKi%;uj zuH|{9+n32#TKL++kaNS2YgODS@-xFvz5m$l7jjiT$A*!^zxC7Y85>`<1vDh^i_SO{ zeUexB=7Un5TlfD@6}ao&f9=(w>DzkOzA>MWn14rb_b%sof%;EB2j1}WliPgE^-Pbj zLAqA!6ruH73LgIBomD&k>Dwg<3${0Au3whduA-J~b-Fi4cloQr1KS_Hx7{3BYwP#W zuV6xGcHP-3MX9^~4&V5yL$zik)t{?)E>nB<}rg0pHF1a{_XAyyw$}Fv18UOQJ z=U%?FOzMlp;+TJLxl9)3|JbwriT8#ag-eW2k7zV4|CXTE`oQk1#%!Z2E52WxGwDd? z)Pq6?idTNCy|p?yeHm-=Ast2c`@2)_CEcGg$9?6UT|%?GjTS!Mw%JAEOi_Nog`X^* z*Z8yx|882cax+gjKZn!(##~8{d8@Bav-*EDone*2XP>M~C6at=l&dF)B9qCX4x_|#669koha79|2Ap1+XC+l=wWb}}qQ{*YxaonL`pN9XpCu?p^VbpG`O`Ci4`Q#%h zYs)6b1a8ms|FQn%_2X}3YEK^zEpv7J(LCwg;h94Gl3PX26ctsqv&Ae)l*(p&9u+>j zC`R>M&4ML=?hDP`z4i0mzv7>Q-vu6HSDk8grS;H(yN{~!FPxj~>@L~7&Sd$!K+gnO z^WEn)w#DDv9~O9j@~;W!m0ADE>%}kO%VgQ{$-XteKRl4PswQ;3ZmLnj%rf@=Pu48C z_ttD(y*VxK!K4G9zRqx}nX`Ys(6jXg5{s`(AFAr$Tln42F-iW7wb?N}Kh^fTPG0jK zI~txkab%fORrQ})I@38;)QN?>VdytfikNTrfMZ2@hjM6oR$H|myU|-dujo>oyenUD3*Y^}OX zg*S_5et6k^__KN1%~@(GJLZ|l%D<0~`yVRbShCJ5qPM`@Xik#M`xaZT*PI`99+;_f zO`YV+TKsCM(&w2CamK71EuNP(rmH?a;^+Hhx_-zkEpNBotdW`y$vgUtp4V+O@Xr3G z+NkC9xjJ<6`j@dvU2e*=mN4%0l2X?ZDcQQHQ(ODZFS$BXmyZ&04Y9A8Z+~jAG1m&7 z9shOl5|8}#WhFV)cK&&XWQ8TP6w0d%+s^uAw7iSFWVxB8=69*4X<*)E_kyx+Ps{t? z^1fbNU3T&77k|MkJWcgKizDUGBGL1APkGGBG}VpsMG`x?I}6)+-kDvVX1czb{{Lb-w2BTIr&_Tr)3y ze9@QIT`%q+c%5&Bg~DoS_YcxXwxlfMwEEv(8_ebp7S`bAs}pOd-G*5}LSgzo2zw^pzW}NA@peR?%xNbS`T5zZ7xc&o8^U_~L5e_I0t1+viN&ot^vP zjQVrwYks`x5zoI)^$VOER$Mx#`R?BrM_a39swJM-`LlgI#1`09Ys|3jt_<5@EB(V$ zohA2gan27}boXP4^6|%8F7$L?jWL=Rqh|Xva0|=&FUuR8&D+cSnpPc)Am784q zl3YW{oqWM7`)6F9(eU1P&q?*>eOK9D#iod|ZO&}{sI^^h%`OqHgI}ZC;%tOY>rYK+ zj1VfVOi^)>SDJj`WwOje{xwU_cV14aZkkmkbE&~=(US)*77n{w4js&USLg3;=@quj zDrkm(#W7CB{@`SfE%J^T&*Jv2Iwdgas>rwZGozMXY?5kjjOS}}JAQWIO{vxFi>DW? z7npz6a4++Wx~auKo6jZP-D7k}Phz^&cJV}u#kPJ+Zs*>aa{TGT^Q~;#UcYhw|6yz3 zJ@XiQYn=&vS#n3@x5`^2b&F4tmb$eni0NVZpX4c~b=&jG)OW8jzZX0~r|rrb=|}q> z-m4Cf{mIhS8d)kg@2j)gT$TGV%hc!b^i~IraxR_0_W95N)6s-?~MGj);zoT>cfuL zQraT-v+}P=mPmX!w1m(08>`&SsnvcDmuoxo?Ppx{ZdD7bo$t;S^Fu#x`%uw5>&U^Q z78BY}uJ2A2t~_}ydD4cKntxRX8c%NdFfo>+fnU95^2=~F``wW*H%;MSd*Pc~bMLbB zzST2aUYgJDZ8=c7p2vpg`oo#07K$(D*T39f%WC`fPwLjC`a;t-RwrGYc5{n}`S-*N zZw&sriS5%Zsd_(s<(>sH9u8LhOMf29Zl4q~Kland=edl`4x`lM`j{iqh58St2-K%;NHvUl6Z3t6o>pe_j+0?lQ4_Am3*0N6 zEWAIl<5b&kbW)a&bZ@*47xSjme%vSqincKc^-)Ht@-!q-L zR`kT1T`AvQcIKIXyAbuTE+xXNeo@vM%RZI44QFCI^Gub`h^=h9Q5qAkzvj!8)r~=! zGenPlNV~+v6~A-qob{p8FB-(3vy~{amdvx(n9I&$EBCf~#x>!|YO0Kn`=4$)xuffy z^1<%T&WjViER)=}xz0~p@T^>S)RsM;KdiZ(@#NO0!)puY72fK~D+suA{n(R|XHmwe9H%kE9*8K^Li_|$#ucx{JpObo zJ^HBnT<+WSZ%-}lcAk8*?dr?D$B*BwHppYM2~@v!U`6Qs{j4H?&Lw|UpP6v)_2XS3 zE_yCcN*8?X=1b~YlzCF$;r`>g3Eby>&*uD?=4A6#FUR}e|5{7Zan)Al#NYHWVW=Wi5WYG*Aezv1+f0((~ZNPZXA z&J!9gV$6aO(Wmkmuc&=Zlbv@i`QP2`zYp`DS||LoB*EpcB>Z{Lb zdrJS3i1_?Z>%=$Jw|U>hTdMB<%}6e~U;nHmD@uSNIlt~t@5{*4%!A9P8Q%CDyDXsm z(yd~(U)3KK^`HCmB=GyK>v&nN&pB;RrIW##R*3`s93K{{$@@iw>OWGQFIfF4H_YbN zccmAPY&lGRgl!J{8M;Dx?SnX}*TH@4E7mW3zi#(4iTihVT?^YRw_$pS{ayw}2OZ{3 zUf(lj3nw1DfB19Fc0>6EA*QouFsFIEe!A=ix0}%8m?-&KnYEP@o?Kd-#&)bOtV^IT zWly5~#*p*=7L)2@43g|lotncbacC3gJ>8U*dRo62FaDgRUp@6!ol)zC1AA2eXl^Ow6?3L5bvr!16=vw(P%!a` zweU~vFPnW@mU@NDE2wN(SMK-VipPSzt7lB#eUK|8_3HBOyAvCeZJHDvrlhb zFx;?^b-VQcJ&mgSKklrbw@KL6l;slh*6^R5%9lD{iA?MMbvV0+_v0g{FJ9Aau74=s zzBJ?eKj-TUdTnlG?Oq<9{BrwJk6+AleqDQa|J6;_Tg%mcNM=XLCI+^h*taG9erBSw zuU(pbh1gCOdj&hqPRnxrEAN-CvHc>$X6F%~IB(&_YeBZt=XaS-%zWmvW6wq1;~7%t z4EPN>XKr}9&OBt>F|%9^r|p%6hcBG_K7(UYpjEeT8TXa*JNyobPgB??-g98mY`aX+(F#W_2mV>9ZoxV|~u}{-JrT*FO zvWU3ayKNiXjOHmUytudds@^QQMs7o!@;D~7OBM<5XO=nrS}V7-sLgJjX~OC?Uw%Ij z_G>?|`FOA6zr{9BR-CMLX--~Ier55!mf6#HzKu@WQJC{_*Hsp$c1uPv^}Q*Z-&+>C ze-f{Xk}z4gSng8Hw=1*dCb$#?tQWj~;B=FOqxP3idnETi?f3Le_MKwG;l%u`w(;Nn zz@j6M(=W}ce!BiP$3=w&S*qL5Rvl3jS@rj}`@26G@+$p}Y&Ki&Nxm?ev8ngje(sC! zKbcTe%q*<;QIEs}PKimMwc8+Ry*YWcTO$innUbeQ%c>N%&P~^H}Rg*Jbn9?iB(4 z%X!WvbvAIDK2Cojv$pj`_@}*#e$TtNdB(4_C(9ZZt!a~QTQuY5ek;z)mbXl{8ZNS8 zIAFQl(fb--EZe_^JKH+GSa3I51oK56Hqq6Zxk0Y)%*4Oq=h=#$$b9x*enR`}@n8SA zuiUvk@8qTY!aqIAtI|ICRx_X$)BsU+0rs2zS{j@ zQ_|z;yp;CCL*6eL(lB<3SranAutY-XxCuQNp}b%`y_7rl%cZE)8ymd#UuxexYxcQW?Yyt@bN6cP*ALWvqM^E~c~hiB!MX2M zQ*`y16Z*98FOl)o?D)8G%i@fHsac<&%zq`~xV!S2uIWeXW}j=_ui0NO-!x_6oCJw^ z3WD?aH>*5h5Uk-A-xDZ2r>n5HiTC~!-9!%20*+8`&mdln?@{IN_K9dV?)~q_bWAI~ zOvzN$+G_3JY4eXW&w4lW__y<)boTY=#r*GIy8M__&I)t&Hxm{5Zak_ldVFTpA;v)e zQl86fcXTe@3(j2HdcWYJnZrwkS7N#SQvYshls{cp0elJ|4x@3 ztlMTr?lhP+<5^^w>d}&qTX<6pb$HJU&wus*`-y#vdaN9;oacJ-%C+c#UC5gIGbbcu zytVzzG}Uu0d(~gT=_?+uladtv-+6s$mt~=+o2aAfM&F8!#m?WIo;X@=`PDqjJ=8`p z@~T;EQBR#_zRcV$-p7{T@3`=R$2<1E&6Cw1{C-+XJDk{gVU6;^x|?Migx1xkykrqM zXqfz|H22)KyH`c*4K?~=G;(hX6fRtJxy^TCec*u|GpAbKKP?qydBuCfJH?xI%PlH4 zKD{Y4iP_?IsoUeFYbP!~@~VvOr2UKzVS5X4zw}Rs?!0D}e%*QGzw^y$CB2)u_wUvF zF0ErV@!X8Nmp=Vay~DIw`s0ZyZ7Y78h~)+?wyEkqcr)pX%7*feU zX-h|q>*^OiwdU>@16(Bk%=snqI;)KYWKb z!c@M0|BTdayB|2)IN!6rJ?Y)&+R%R+)wwimGq$)(1??(X;i11zvpT`Pc*P3~)s4@C zs^o62v|Y#E5q999_gf{?-;cD@JXUXEzG3jiUM0Z%#Yg?QH)NJ|y?W*rn|i=Ad-Ij_ zhgCUg*Hx@%lx?e3E#7mcWlw)YP$Zm!W=4PB-a&S}0Y z|NLs_Gy&Uuhm_{oS+A6T#ARFy>YAtixM3^*hs%zxOIM~SHF5fFkYW?yXUpDTH6tq0 z)x$E$wL`&q(Zx!Gj29p4q*PpwWwJc^`2X4Ov*(tD_dd?!+F{{zFHJts_LS8Yvm^Qf z3-WJ>JKpMi$m;N1ziZjFQ%4Ms1TJ1@u>0!0Tdwnbrv}Ote$iG_UhdpG`Li~v26_pCT`MV}C z^;YpoURba2>cM}%9cPxhicJqVvPi7R#N}N>-u1iFv<3F{EG^U*(qB=!^#Er|T+Wu< z%KJ5rKIadKFmC(rN1YDTMjVy1fm!o_YIx|BDMh4_sd4b|O&X-Nod>9k-KbTQTwfWnc6s z_@*k8lt+WtqwC$Fi?QJN}rP_T$aA%d4jTy7-GlXl7TzlgcJO z{~v6EktNr4gJp01e|)ald-c;dj!o7n9EpCc$5|Gsss^=+-!@-!PV>UTlP4;Ki&qxT zNHk2;jaCVGy2;t^(=Nv+7q9)1Tp=l7pc@eNOX}@@jw=aivpMwIqKo@2cgfH7G1vTH z$3OMLhujqcVdk2fHy;fZ;oYF~0>@Sql^B$XPjoD z2V>lRCFZ>|E~%F1yFdH&D!|2+Wc7)@^6Nn;8)RC;IN#rM^$l` z$^*_{ud3WcmVev*(p}X>iSRniF~` zl)dM?u918)YxT|r-6wWWdA9c3<^snV*Mt0hdEI}WIec|Nw2A-6pVceneZG{{iey4 zsuyeR-*oC*HTNFNy=P~d)C)MI=()3n&&UkV;8`f%dm`?U<1Xgx>`k_5W-jm~ zKb6Z{vV}9c_37w-VVNY0W4qIu)#jJO?v;6htcJui~v2Ws8T}16Yrpy;- zzx=V$@yqck`*Os3^)CE++n)1la(wshy)!t)wf=3HwR(|!N@)R0!x#N|rrV0r*M9D4 zI50uyMmo=tB69Pw*Ps1N%YghcI7H$_wzO((unzGHu z>TZg%xh@lWK5xzk;e+b}>N_&bLoi&tJ6bJY-*+BXEB6mmNhn#1uDN5;qjNzmMuY2ueoBe(Q`o*m<=cU06Z^$FEnjV& zd}Gnfo!mMMXXghw?$^_vFF9{}X~3a5e2>peeQW4EDUx@l|0|CZLYMYj%<}YI74>D; zzVto5$^6s)PGgKRzW4p%8Wx6L^(9XJ9<>j(oCe6F~*HV52y+&4^_d*Hyi zy8ZU2V^z0ZJ5$AWeBlX&hF9hm(kFIjZn4zaJ<}%1`<`~p`o0Tn0j?2Kj6RCX$NcOu z+=xsq4d*Na zw{S+3Zv1HQo%N~c2_NBy{jEZqUO1fLUYAgoxi#U;_BT_`OrD?NRiM2xqBddH{GXircPz{EhN~Le{0vtglYd`S@m|;`TySH~-x^#^H-?3QbsBdpjR&tq2#$cDnX! z_7)GJtpRUhzW949v%m0OJl}BDyUlKri+3tBZDGuDKU!BhoAK8>_u`{V{sOV z2e0hU30xmlWiE*PZd`qrX@g3K?CC{jetPhPU);G4e{VM{k()oQlYdlSsKV8V+wX3sw>yHEB6MuP2RX;IR z^}C;bU)x1EDBxw~=GwXkJ^~z-WxA;@XB`(>_trO0{#zctM&Ihwp0=IW^wc_(WonKv z+_;?VXI66D=^bNQx$AqS*RN+V9Qd%qa89%T+Ep`(^sd_qIG&7~zGuRobv~Zf&i ztl4%M>krSR3sW}Vf1mj8L)Ds9m2ahlr}OWhma(<`$o^?OEz!q|8vdLVk=qv2_vsPW z*~aSoGgQS@BY&<>{jN6Ye&L@6m#O|X>&m{B*~ZBPi+Xz~-tNALz^AiLI!1x~&u*SmP6^i6a28oVW$N*$HSV{S z#TOb@>`P3Z5F_Umz;vRjDowbgiECxJdg(gH9ib(LGYp*7M6?YzOH@ueGJkir!?_?E z3p9k^9@e7l)YLzVq(HYUNM6mqf4m@T_;o zl9(rR=IwQp+{D!B?si2wN3)q@WuZ<&((y^n8r9pEIqt}ctaP^SnQ0$4w`=LUz2WMY|2|)4 znSrY4!oulNo9fFoqwnyf7lsL!O1#BEX3ck!sz0? z$Xj0mE#{aAdso!u@5)K~Te>j*)Yf&&V$aX5)@qPj#Zt_5qnMX#Kle(8h)0H>X9Xue zy0AApqdOu%%_OMQ*2ep_WW|*(-n{#7o@%m|NZhMh>vUW{Msxj+KX(i7X&ZdC`w^Td z@xsK!fAz8>E~^+{3*1!|l~G=CF}-sN^N(Ypv+~aCmnE*7VVL+L;6VE(mQ`sDruawL^kJ@QRD-Pi=pDcgc*sW}QX{CQpfUOb__3IsOCF*O@ov%%*CKJmq@6#^bqk zd)dZEl8ntO+$VZ5Xxz_8xbox2u~)Jj#~0-`*DF48|E|A&evaI`_sqtxcRvw3#kRD0 zvWvM)V&0mEd*e@TXI5tTcJspju;+=Iyn7iB>28s!+~2IYr0LS374iGF2OrjZ;Ss>{ zL`3|)@#nX5t+clu^sSTm7*iSX>)Lh6HHG#Qy8|694)DKN?9(N=J?gBd`mF`$Sw7B{ znRwQuW$DI~Qir;0yjKQz9&}i4QneyVxM=HvDCZ~rHg+!^nQxuB_+fReWXq<`Bwyj} z$3s$IO8lBGGXL38iAt@MFU`&mzW%ZL7PMphHCDDCFxliuVSI=9V zR=!=k%)ecB3sDFTSejhWz2?)mZ=AIqQkQ10vwK)!{6U~$S#$fleEG*_b!$tH9_s4+ z#`n$fMQU=6-5SXd8Jp_&>i&_|w^~Fmu}$$>ZOTZ}MROs%9GuD)_7;Jy+er)BdcXHpB-1YWf_6z%O9Q}m)d65d89z-?E~3)&lj~`+mW}>TP{w~#K`~0PS4XGZuV7w zZC&m*oX#lh{4Y=#`~Jfr!Qgy78!hGazn?zfU&{N_)aXL(Y2_CSKf0(cw9=Tl>4(Ah zs%dYZZ)Raj^!dOz_wcO=zD(6S+xI=SDb`-2m1f8LEzM~{EoZVrllE0H`RSXrVjE{g zO}Lj_-Io*Y=%eZKXoZ>3F{hf9k)_{0x*EkT-WcDekYUEZ?ojqlMz_qAyr*tjy7O(B z8kgmsUG;3{ORgqRp&$x<;471o%3Xy+6JeG zR+`U@eDj5NXN%3}7iOBQ*60+?^tkx!ajQjA7n9HNXW7l}ioI98QBUfk(&ICqPqKf{ zdh#@`LX-FD#?EfjC&KYss{ab!z4*O%p{~I+8-@udLnRkoe#UX8DN^Esgs{aG_WFc2 z9y3QVtr_=z|KE1;jQ^s;DY3iO$I3hV-!-!eDcQy#+0!t|)2buuYJX#SN$TP0+FMWZ zq{M$ZRBC3p=JCAqr46TSKF#{NfBBUfraFTke2VivDzBQVT`m3Q%9d%-6XZUKGj2bB zE9A+n+fC~j8K>U9_m$~Ge~s)TnU8(%4{zNy@4=F&Cfz4thVsv4XX-YuVpmAe`L-q9 zV6Wi!Al;t+t2*bd*gXx_VgTyUzfca-tJ$pA@b$R zgNq&ZYX4Dkm3lVA()aP_V&=A(Z<)*!<^=8)<5$${vM{?iSuY@|b>7>rmX&vmQlsuK zk}I^@PWS(YcT(@8Er2ese zqho7%#k@2-t37O-Nf%q5FkDpSivnoK89a zAcXBH>z|nuyp%uey&I_<@Ay32%VN{-jZPDi6}@cp%Wqg4=ht6;;d^9>3*UjIGg3p- z+IDVF^o?2b(Cb_N!f7>aua5BUQ1KA@#Zp~a_wGuayG_)Gv*$KXj$G|-{n4x>Z1vRR zS?AQhUcD|Yd&w(%N0+tkkSO^MVI%0FbY*hcc@!*lnU z_1WBGdDkVK3|NsLeP-Y7lUd#O;;VoEoNTd1s@~)hbAU|x-L|ESt>4VJxF4N4p6pV; z{{@Hj^?f^D-n6l=H$1v|Q`=jKx$ow-#@K&!=eR5*aWQyt{#@Sc-yOHGPU5XU@ov#! zyZy$xCnnrq_Ro@LEY zW!#YLmd>`5wf6AEz~Vi!)uQ?jL-;51biMsq#vdg;r&wn5oy3%Av0Lwa$|qI7RZ#mT zw|~RKjUL{d57zV`sa7s%~r4enXxPDT91BlO^d)R zkR*!|z4~5(@73+`R-Ic)`|T1kn(nB4;OAB}^-?f7yTGTl zxn-r-syE*9DF!o-FAqLoJKNcP)4l8St9CmVWJaC&bHMDksoBEmcS`-1)|Kuu{I+Vh z`sp_hU66fdbrae>hfW!6`cx86Ea#anVfPtQtqU}#Hzbb9~~@bPFws$mu;h4+m4O}&Rdt% zhr8F@UvWb6Mc?iTui2{=k7oUE_VH2Vc>n4Crt{Y(dYj(fl3S-PUut^6{#}v> zLf=i8_WF)Y$BPMjCRj~c@$18-<#!}Gj@tzPds!HJZP%;x-nI8X1n-=~6t-|u+FPqz zy)ExwXPijne)bLFX?-=bb}CYCa-Z!_OC%Lm9Y6(3YL)(^3sAJsGY z8cWN{Lf-z0CRR_EK>n#c^4sGse_8lm*hgsMpVA2~e%TXq15_B!d#w4CP%P6Td40>3 z2KWARif>Ks--u6KuiNo}Q(3J0?(Nv>q-pm#*s>ymHN{icIcte;@m#^uquGrAkFRO|wBxvn%3&+C z*?si8$fKDBM;6_^^sdLyc=^_X+tFFu=N&)#veidX?t$u|#h&`Q>4#jtOkqyu-(lIA zEy}%i>dHLIf%}bO0*RNPsD0wL%^l;JLI)Nn)Q}(>;o^j1~ z;v~*PkDggg^!u&5z1sd|Rr{L%^EGD_tkjL-@(?$ARJ3LFQx(DFzbB8!R8O7tli!&nJQB^~QlUI;$6;M&J^ znN3^ICY@4l5!@xIuv7QK`AMe^J~0XD`;d9g>So{byplVgDq~7B|DC`2=bnsHam(&w zvd-IH=A>>}zN6#X8Q!}5wA8$Oiw)g3Obd5aTWoZlC7)>cc~*+;PtFDRJSAk@-+mCV zEc|IzQn!7<((6p3r{qeGYVaCNJ9X}r!JEx@Gs^RqrljeZcNSgr^N+bUpUY)Fr-qz) z=A6Yd{V$rPgkQImPDz?^tZCxq+}hZ7hL1ac$!(k_zUJSiF2%45{{nAFXw6&C7cqe z4nMqk#uJNEesirC>lbZbwc1%MciFpZ;vEaN?AR4iYF9d+QSL|1-ELJU)*a8+-Hf;> z@!p3wafYkx-hj&m*UYtVRj+R?;;dGG`c>}z{oSsu2Mc!n(qr^BzM^Nq$J%RoYO0a^ zJ@ps1_4-@cZ}V)DF#T3$dE-p;%+yzVSH5}m_weliHtT&)9QN&c;JNG8vc#G?3$OIU zVQCJxFHUaYdFGU-9sa*%$9k)h7tfD2rseNBb^T4eVAZz}rP8!x3rH9^_cy3Gb-YQ@A#cNxt<^xZGFrgz3mosn8_&)c^+1t8dTO2(CcZw%8y*2K) z{j%(jb-mL!p+w2~D+COr|CTD|-4zXMSX0E}QnSJ1m00_MxQ~CAA1GX)m*UM8XzI;q zAie2lpaLcS1noR{Ab}L&!ysQzowsxV%+3u zzfMB&W&Vnvyo(vT_b~a-NU6@-{-j%AyT=RDGqp!;?pth|Gv)gY`PygKw5=K+{k~u{ zp?Kpx9-jjWt#wcIzg#|Hk$m>iHp%l@C)PQC3gBP!*8Tstm!*EYDs++@PI6p|YUe!l zQdc(Awd}m~1)Z!z5Au1Du$9wWB; zx83Ab@fVlAKVQcGenxMPLGv#&vq-PpE9&2Ozlkntj5(;+eqrML8+G;mE2assK6LX? zy?*}k%6n;S0S%WY7{5$PeERhYGt&>5n9PZHUKL%jROk}BVkb~|MUG4Nt>442z@7Q7 zrH;D--<2%&D6Q?2SpRp0UZc~y{^nD{D#Zf()KC3x{3mujrd84%hK<$Ar*keWv%IY3liT-7$MxEy-d?`&*54~H zd{N{&QYwDxU#{+nRm^{!WWIjs+f#Dt@Z$Sxr>o@}-42ghnOV!5eSc&5K6f5PagiDO z{hJm^^&H(0I6OJh)-gt8R#i34?rfQzk9C=^neYSUcwVfeYS?8{% z%A+3=Zk{uZZ%k{u5u@|xqvXP)ZoOycTzt>JeqY|l--$ns{#Y01I_>m+sXSk~`@yo` zvcGRGHhcO#;jZ7YoV~xo1lZR+^PLeq`AI`*+|%fO&g}bbfp)VxvM2B)WlvAuqr~-b zo7Hv4otzpATte*6U22cvJ-9*jfjrZJ6qPN!(sv}U=ll`Kdsq1OxB5@+C=6ZqdTX@uuYLCfi_XqC{UY+~Q{Gd$((j(l(%0#Ga56zu`O>#prVP$$ zVU^Wg8a-!QUtW&=CYPjYzBKfJv({d(@}-h16Bqt*Z{*_d@0tGbjExgVw7_wheBmoI zc3it&?m0^)EGYOEhs$}!Pwxzk<+rvU%YJ*1GyG&vnb+mFU#gNVw#2*U6+QCvO^ANA z&g8_CA9t@xOzseT6wsl(+pE0h^sKhLgf+R7mT?{nx9~dHJ7crO@2?`84o{vNEux8R55IJ1>#@Jz-yY z%C75it+Ef=WcB^lChiV-Qool+u%J;QSa%Wo;Zq;HHW_CJxKEc6P-W`dcGbS>veERp zdR6~5W(22R|9HveQcCvrE%)+PyWR@y7EXSjd4I*W41Zy@-yt>?QPrvswkF=xUZd8q zp(Aj?<(nHjm10vk{_V7qy0Pl?#t5(LCs>&{4sbVL74K)eV?TGhl<{lP`)s}hnP!j-&Uq0ETSZyueHeO)UZZm(6bWkyy&W~(hzw9iMr zGmZ~VY>7?VlH?}6B;Z$~yJ2+f{1Ai3PMe~C&63Q$e85-Q{jM29j_kybcZ0-ylfRmW zwdyl`wG~M)Jb~g38 zNZgPW`(eFQF0klFW4gstu}!~A^mhKe;_=70eecb@*QS#qtTfV<)tQS{Wp9gScL>tF z6#F=^ljq&qRhOpc7wpV1O8@ak;V6g4tu>$D|Fnv!AonG>R`*?u@Tlb8c zJm$w^>R0!g?P-2n#?iR_*yDt^+d5h7PV-Lqv(Q4AEB(?*35iAC&X237FPyPDLFaDo z{~g;;e&APlJn!|CLz#1V4hJwkEqv7^5yI@3oP5YSY5BuX3m(?!os7J?>$imAfv!0x z<+sJoT`3oO<m`EP_wFZ=o;u}gXOnyYpDT)Xld6&}Q$+PF$V_rZ!L zx2@0jSU7MvvR}=7>C3m$vDZ&qSN{n-JkN8J_y3aJ zu6(a^_~-XT9DBmN`rDqvC+r$?T>9>z?+8!?G%&y723!rvLD98`Ll8*$FG=8B8C zlVqyk-!zNUf)`eAn(8lmR7~{sja`j*XXnf0ZL{%@J+>lIO?2zSU96XaIM=P6Hm9SI zoAvFg$11b>PFt%fub+Ep=5cc`*(EC!Vp-NQcUiCgb%wI>HDi=5B$Vjm# zUthDoJk0P|+VRz0r{)-JFVX#WZ^HA3Zr3!I+i%up>C7|SnXt3s$@I(z_tmrVlmp(m zZgcOlK6$cKbPB`E8N250s;)^_JD>9-*!OqPJNAt#uP)yxP7B|Vy~cdj^V^>@q6?Qj zf9?O_#QC}NdKO4pid!bOKG-p@L~z*}R>L!SKbBS*Z!2=>PMo!U>BYLme=0nW*{wbP zu+o{;H@M32MG_C^ZtbbceU-1mh|2|rn>Qo z+D-pO--X=SzJICLn9$^6{kuzr(Ou!??X`JF(l6c6Tg0LFDzV3?+B)3mb$Ut3wpVpm z+n(gSudJDIptMwKd(^F$Yg}rh!<_7e6yr_bNzb~z*1Ib8$Yw>KHZ!qx^{ry7f4pC) z`Dj;2;4I~=X&3&)znZt=iNm?p#Qz62?a)x0ZLirkEB|O>Pu;U)^}TQ7nSR!AS>0Ie z)oUbtM696VfQ2xdqxD=5y~#&3nnJ68amI@(`mZ*(yS*#B`T7pM*O}Y4SzVGlccMJ{ zo@qAA?$1x!PCGoziDT&HE1Kr$_a$3);-&IS#xwdPcsC?zf6||lrs11&uD0paQE?^n zi&9fNPW{`-vAXtbo%mU?)8)ob&&@iy_CWK&i?6<}KQ%3oL-bMb%|f0xzqeJN3h31P zQIh5ArEPl7Mq117d*tF@=dOnY1{YaQl6d`Q|8XAG-Fbmr$5T!msZ$Wu`#iOh;n|Yz z$J=9%D6Km(&!XL;Jwx-+PPc8`E1s{nU-Q4Rvr%c+k*HJk+mrb0Y434_vxiDk}LVdvdXSxu^Y&kgiy-uiQ&k zs_lL7cd=~89tYWQ^D7a%_Xq#4sSoX1W-DvPwS(htnw?LWP4r}S<|j>f>{f|~X00=Lb6l*~UGR+qt~yqAvUUuautOvntBBht)tcS57U~ z%(|Xgu4^HAD&X#Wg;PaeFJ?K*Z>`#u9msizf4k)LWg!=Q+q%vfJ4K#)x_HN`X{A%d zHZQdM<@PFi?frjsi;{~Qazz&IYSTV*?B@jTs}uelv;8_TowLXMXXhN_vZag>JSpBc zR`C8#U+3<>`0ZWo3?9$jE=`LwGk0%dnA!OL_`jf+Y8Oq;IlE{CSsq_z@YnTSjqd-P zv-!*odNMi}&u_oTxPF04dex`klGoggQH82=7&3F?FdO~n!I)L+0GSi@n_1CblR34;#17H?!0+tQi4MvPwD41{;Q{1 z*N0!5uq;e6Wxgd#of*Tv=xe9BEH4BvZIyFu>yD0Gp;XeJ$Tvs##NjiMidU-k&NFkt3qwVHlsf5lNmOBTdgjO!^`O~!CAnLjGKKGI}vwzRJ>^aFzz3>3KAL(ihp!*K{gPPky&IW6eLPmGbrJ zqfP9wR!!T_iG)0L`4Zr|L)O^oY~EVVnFT&^M)&*wZL$m&aDEtVS3co#`Z|`Y!Sb8T za<9yc>nq+Gy2W?Sv_nzJ{w|wno^GG>AZVG({Z@u` zUNP$=KOHSoZfDI~Tr$Jx5;&%I$c=sqQey&-0lB2d{y~o47>hqpyyf@Xo_m%tU(utn}ax3%VEyH%)2Q zVcVj-;I-zVhZV0+NBM45xyhAK-!I3Y6Z-1q96#+ZhjP8WUezRqtU21sFHVKT^zWnJAFVAT;NlJ#KeOJmf zjju4U+QWN%(XQMhM>cN%)FL+Pr`oJ}xok=XFS|0YfB4WDbmzqEnR<~L>)+khJ;+$# z@>;`YlY8yC?zi1d=CP+MLf+lJBrN@{aPO41n+hH!=j?YLziwgt^X0eAr|fDYCtW!l zk?xgrRV4KJzUlWWPb~RR^hY-9u#Em{)qRdCM$M~C-^6b)JGSu6c?lEm;ILQD`wZ>X zzdldh(6D6k&(Dj*zI-T(=3QI$C$`}J8EI>=)VO{H zLmB6^NfW%+dvIK<0s?A>!|^Z7EsO=>9-LeX&u4;Jh?}D`Jy^8T8zu zo&MbSmPk4o%mzJR2jIRGj z_f^_VZ<*d-X0TwzyU+iR?P}FNd{|lNNY#{$*}oBw5o^%eEN z+~?cxDl8HGeYI{$Q~1jO>8yr%&EFN{e()7ZcKbMq8AvW~I4EQw{52v>=tmfb)qTap zu&iqL1>3pngm>Gx&&ghS;HKzF-qIHlyq+CP_QXdjpZ;~;MSb#pOMC12S1xCpK0MED zJbA_Qg@0VWIX3Fb+h+Prm@$oIed6L-n|Mwy*tcP-LT>6^yP*8ugpwIf-V)_`d9@1{ zJafJ)weHQ$z6>3`6B^sX)^K0R{@H#ZOI=;%;wiow5uq*1Iv(*~s$1CRa(~PFBckk+ zU6P*Lm?|_xY}UDa&$_Tby+`EWmW`I`yoGUpj~u;rJzODU%SG`+>{qVxuNUq}+rQd; z!Rc$~c6H}it-bwAaYMp&sh#D=|K?h}UvQSm#fxcKWXNwfQ){1BtEPYO@m;j#p!9t$ z9?`jP-o~H#1wI&=@SmKm?Z_@Aj zCb4s~JE|*WR!`a08L;$ND09%#U)?IPYEOmNZ*S@@PruNeO(mmVMei^_AANEqSMTjku4g@16hGiOJ{x0*RCrYeSx2dZlb-e{!>9r@N{-hyCAQ zhpn1D4)VO6a&jr(iDuhx%X4aEZgPm)yq=kDSa@^qvW+5()(B?KUjF{D+n+n@-p){o z2;k~msPyob_^*%mxQ`gDT^jXp>v4JS6O4k527#p=L56~RBnv~Y9pwCz#>U&WYiYK- z;+g4dC;QhrvY(xOLi_j|-s`zsMzd!f?&j)f(O4i>BzJ4cg#yvpB@Vv3R3EPoo_Ql7 zD52ohF4wg;OUoW!KkB>bq}zrw{SO*X{@&srbuVUad{;ky0P z0rw73D<(@7hDvGeBSTB@k-zz?M}Var_w@(;O{8Hw)?*qT&4 zW9j8(X8%tuk8Ih{F|W5}>zY#^_=}crFF1Gmm~T~qd_X<_|Z zN#7s)|1(e4pF8in%+hZwe(RoI@^Eg+OiA@ci#8whXO&Q>R{itul8C*$ZMCI zTg?5n*DLw{1jbzB=X(uSJAAjFRM_nOGSKh}>(mARWq&T6An>bY&q^7swkt_9e@xoE zq3T7-8==P+?@0gMK5g>zzm>shWmevM4!UnIEx6vhO83vlW|140bydzT-m_r)idu!u z2?vDdtcq$)aPRQ>Rrb&2g!LK0lgH~#chn121)W`;6u~RF+;ieF(*QTMN0Zfr<}MVw z{i~zYsU}s0@tDT;16M8bWDWlFZ%p}P_dWEB-{r(-Zv}Ou%(xssT=$r3_Hs$xRn7B=HIWe2=9c#5udB9}&`tzH5{(Ea~$vR6~Os}(f%vaiN=xS4o4Jys zXhL{+){(%dTQ6J$_r2G2m>6HQZw=eErULWd4~rZfIqg%zlk^S8;AF?}ofmOLx!IGx!pFQADv+ z{|ImK#nqxI?N_u49Tb0NoN%0(*eIqNGeOs6@RlLmn*m5 zTC)7lqjv2>H7`o1+*o;Ambv5ilMa#DdVf!()h9-}bXV-?)W|Qm?)rT8jN8ZWnBLAg z#CgZcIMU9xea783&x(&%`guOAd!`?^=Kb-2ryOmsdO!3hemrJ*K5{wl=6>~euMVB7 zz3%7Sz4N$iNxBvLoSWv)S34d#wQr;N@dGDJX1$59RO84G&j0E#F=&74?-t+6r`^-{ zKB>6CSJMB?TT^)YpK{ZjNqGm1q*UM8Zhx+(u_J4>+4V_x1Wz1M{a3%_OV!;1jSQ=2 zul*Aicf5T(&*oy!P8Z+h>nF>wUUAghuu;w|G-)f-R4yq#!LMvPbgKi*VmGkg_t|{vsE@a-pXB*CWCe65Z_x9^N`!4-8+hLjGR(DU{Y=Z6; zj!5-ohFfZnWNgs9HShbi@I{O=d*(kpd_dYW((qR1O5rE0msgs|saqVsB-bACJmj!s zLv+TzXo%`w*&i}4T365Zl-_ksoEWK z{A5uu^J=|4i#DIXen#QT#hZVpTu}Mm^Nz=0VsdBs0dEF-?&5M4jtx=!E@d-G|7P0b zs_~?l>9Ot2!%PAu>_+p&3+;BW3g+#2vg=@YqE_@Yb8jZLRd%&UcN*N23wdARspQ5Y z%cy$2G&(Q#rH}rFo&VxR1uyOmSmO6#W4Wr?Rx4)Z6w}ZX!85N1KC~*Fb3yGK!B z6>UBtYWG5_j52TY&wOYwr(NW*-b%yHWl}tE!kzBw@}EsvBsAxfX-xI@O&WZS^}GFF zeF*)#y7EJJv~J_g`yc$4?$DcVCX;OLtzT@;mh`t{p5v?e%k0Vw_Q`nnu?Mqk&C=cX zW_C@@IdwVyGj_4nj{a=M{u~Dm&hcJZAH70<=Y+F~e}01wq-%ch`J#>=1A~Ge=!`u^ zCJ_b^l>1F!XX3FksDO^h1LL=hASxx1$lFc=yitusKGu&P$=D@~$qWn(U}H(U;RM|R zkn3RX=0mZdN)&1VNoNJ(Gaqy!Ajm!te#`g_W