diff options
| author | Martin Matuska <mm@FreeBSD.org> | 2026-07-07 10:36:51 +0000 |
|---|---|---|
| committer | Martin Matuska <mm@FreeBSD.org> | 2026-07-07 10:58:25 +0000 |
| commit | 77a6696abb6946edaa8cef0fcd9f666d3c69514b (patch) | |
| tree | 2c0504c3841abc432fc302151ef6df3e670681eb | |
| parent | f2cd95a372000681bafe284df6ba857d5c2541c2 (diff) | |
359 files changed, 43941 insertions, 3340 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f95e1ad0a69c..dcd948275bfb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,13 +6,34 @@ permissions: contents: read jobs: + FreeBSD: + runs-on: ubuntu-latest + strategy: + matrix: + bs: [autotools, cmake] + steps: + - name: Build and test on a FreeBSD 15 firecracker VM + uses: acj/freebsd-firecracker-action@ff79eb955fd19c697a708a02834995e47a6e58ed # v0.10.0 + with: + run-in-vm: | + chflags -R noschg / && \ + fetch -o - https://download.freebsd.org/releases/amd64/15.0-RELEASE/base.txz | bsdtar -x -C / -f - && \ + pkg bootstrap -y && \ + cd firecracker-freebsd && \ + env BS=${{ matrix.bs }} ./build/ci/github_actions/freebsd.sh prepare && \ + env BS=${{ matrix.bs }} CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./build/ci/build.sh -a autogen && \ + env BS=${{ matrix.bs }} MAKE=gmake CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./build/ci/build.sh -a configure && \ + env BS=${{ matrix.bs }} MAKE=gmake MAKE_ARGS="-j 2" ./build/ci/build.sh -a build && \ + env BS=${{ matrix.bs }} MAKE=gmake SKIP_TEST_RESTORE_ATIME=1 MAKE_ARGS="-j 2" ./build/ci/build.sh -a test && \ + env BS=${{ matrix.bs }} ./build/ci/github_actions/freebsd.sh test && \ + env BS=${{ matrix.bs }} MAKE=gmake MAKE_ARGS="-j 2" ./build/ci/build.sh -a install MacOS: runs-on: macos-15 strategy: matrix: bs: [autotools, cmake] steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install dependencies run: ./build/ci/github_actions/install-macos-dependencies.sh - name: Autogen @@ -47,7 +68,7 @@ jobs: run: ./build/ci/build.sh -a artifact env: BS: ${{ matrix.bs }} - - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: libarchive-macos-${{ matrix.bs }}-${{ github.sha }} path: libarchive.tar.xz @@ -59,7 +80,7 @@ jobs: bs: [autotools, cmake] crypto: [mbedtls, nettle, openssl] steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Update apt cache run: sudo apt-get update - name: Install dependencies @@ -93,14 +114,14 @@ jobs: run: ./build/ci/build.sh -a artifact env: BS: ${{ matrix.bs }} - - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: libarchive-ubuntu-${{ matrix.bs }}-${{ matrix.crypto }}-${{ github.sha }} path: libarchive.tar.xz Ubuntu-distcheck: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Update package definitions run: sudo apt-get update - name: Install dependencies @@ -115,7 +136,7 @@ jobs: SKIP_OPEN_FD_ERR_TEST: 1 - name: Dist-Artifact run: ./build/ci/build.sh -a dist-artifact - - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: libarchive-${{ github.sha }} path: libarchive-dist.tar @@ -125,18 +146,36 @@ jobs: strategy: fail-fast: false matrix: - be: [mingw-gcc, msvc] + be: [mingw-gcc, cygwin-gcc, msvc] steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - name: Install mingw + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - name: Install Cygwin + uses: cygwin/cygwin-install-action@3f0a3f9f988f7e96b8c18098ae05eaec175f5b52 # v6 + if: ${{ matrix.be=='cygwin-gcc' }} + with: + install-dir: "D:\\cygwin" + packages: |- + make autoconf automake cmake + gcc-core binutils libtool pkg-config + bison zlib-devel libbz2-devel liblzma-devel + liblz4-devel libiconv-devel libxml2-devel + libzstd-devel libssl-devel + - name: Install MinGW (msys2) + uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0 if: ${{ matrix.be=='mingw-gcc' }} - run: choco install mingw - shell: cmd - - name: Install library dependencies - run: ./build/ci/github_actions/ci.cmd deplibs - shell: cmd - env: - BE: ${{ matrix.be }} + with: + location: "D:\\" + install: |- + mingw-w64-x86_64-gcc + mingw-w64-x86_64-autotools + mingw-w64-x86_64-binutils + mingw-w64-x86_64-pkgconf + mingw-w64-x86_64-cmake + mingw-w64-x86_64-make + mingw-w64-x86_64-zlib + mingw-w64-x86_64-bzip2 + mingw-w64-x86_64-xz + mingw-w64-x86_64-zstd - name: Configure run: ./build/ci/github_actions/ci.cmd configure shell: cmd @@ -163,7 +202,7 @@ jobs: shell: cmd env: BE: ${{ matrix.be }} - - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: libarchive-windows-${{ matrix.be }}-${{ github.sha }} - path: libarchive.zip + path: ${{ matrix.be=='cygwin-gcc' && 'libarchive.tar.xz' || 'libarchive.zip' }} diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index 2a0d88398f43..bb37ce89efe3 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -21,7 +21,7 @@ jobs: fuzz-seconds: 600 dry-run: false - name: Upload Crash - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: failure() && steps.build.outcome == 'success' with: name: artifacts diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 38e3bc9cc432..98de73181557 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -26,18 +26,18 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Initialize CodeQL - uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: languages: ${{ matrix.language }} queries: +security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 5e25858e3e42..b8835e7ed7a5 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -29,7 +29,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false @@ -52,7 +52,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: SARIF file path: results.sarif @@ -60,6 +60,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: sarif_file: results.sarif diff --git a/.gitignore b/.gitignore index 1e60b50dcf05..6bb1d029f850 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ *.lo *.recipe *.sln +*.slnx *.tlog *.cmake *.vcxproj @@ -27,6 +28,8 @@ bsdcat bsdcpio bsdtar bsdunzip +build/.ninja_deps +build/.ninja_log build/autoconf/compile build/autoconf/config.guess build/autoconf/config.sub @@ -39,8 +42,10 @@ build/autoconf/ltsugar.m4 build/autoconf/ltversion.m4 build/autoconf/lt~obsolete.m4 build/autoconf/missing +build/build.ninja build/build/pkgconfig/libarchive.pc build/cat/test/list.h +build/compile_commands.json build/cpio/test/list.h build/libarchive/test/list.h build/pkgconfig/libarchive.pc @@ -59,6 +64,8 @@ libtool stamp-h1 tar/test/list.h unzip/test/list.h +CLAUDE.md +GEMINI.md CMakeCache.txt CMakeFiles/ DartConfiguration.tcl @@ -80,9 +87,9 @@ libarchive-*.tar.gz libarchive-*.zip Testing/ -libarchive/libarchive.a -libarchive/libarchive.so -libarchive/libarchive.so.* +**/libarchive/libarchive.a +**/libarchive/libarchive.so +**/libarchive/libarchive.so.* .DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d9c5ccfe5b6..8591b6323f82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -341,27 +341,69 @@ INCLUDE(CheckTypeSize) # # Generate list.h # -MACRO (GENERATE_LIST_H _listfile _cmlist __list_sources) +MACRO (GENERATE_LIST_H _listfile _cmlist _target __list_sources) SET(_argv ${ARGV}) - # Remove _listfile and _cmlist from _argv - LIST(REMOVE_AT _argv 0 1) - IF (NOT EXISTS "${_listfile}" OR - ${_cmlist} IS_NEWER_THAN "${_listfile}") + # Remove _listfile, _cmlist, and _target from _argv + LIST(REMOVE_AT _argv 0 1 2) + # Convert source paths to absolute so discover_tests.cmake can find them + # regardless of the working directory when cmake -P runs. + SET(_gl_abs_sources "") + FOREACH(_gl_src ${_argv}) + IF(IS_ABSOLUTE "${_gl_src}") + LIST(APPEND _gl_abs_sources "${_gl_src}") + ELSE() + LIST(APPEND _gl_abs_sources "${CMAKE_CURRENT_SOURCE_DIR}/${_gl_src}") + ENDIF() + ENDFOREACH() + # Stamp out discover_tests.cmake with source list and output path baked in. + SET(SOURCES "${_gl_abs_sources}") + SET(OUTPUT "${_listfile}") + CONFIGURE_FILE( + ${CMAKE_SOURCE_DIR}/build/cmake/discover_tests.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/discover_tests.cmake + @ONLY) + UNSET(SOURCES) + UNSET(OUTPUT) + # list.h is regenerated at build time whenever any test .c file changes. + ADD_CUSTOM_COMMAND( + OUTPUT "${_listfile}" + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/discover_tests.cmake + DEPENDS ${_gl_abs_sources} + COMMENT "Generating ${_listfile}" + VERBATIM) + # Attaching list.h to the target tells CMake to build it before compiling. + TARGET_SOURCES(${_target} PRIVATE "${_listfile}") +ENDMACRO (GENERATE_LIST_H) - MESSAGE(STATUS "Generating ${_listfile}") - FILE(WRITE ${_listfile} "") - FOREACH (testfile ${_argv}) - IF (testfile MATCHES "^test_[^/]+[.]c$") - FILE(STRINGS ${testfile} testvar REGEX "^DEFINE_TEST") - FOREACH (deftest ${testvar}) - FILE(APPEND ${_listfile} "${deftest}\n") - ENDFOREACH (deftest) - ENDIF (testfile MATCHES "^test_[^/]+[.]c$") - ENDFOREACH (testfile) +# +# Register individual tests with CTest by scanning DEFINE_TEST() declarations. +# +MACRO (DISCOVER_TESTS _component __list_sources) + IF(ENABLE_TEST) + SET(_sources ${ARGV}) + LIST(REMOVE_AT _sources 0) + FOREACH (_src ${_sources}) + IF (_src MATCHES "test_[^/]+\\.c$") + FILE(STRINGS "${_src}" _lines REGEX "^DEFINE_TEST\(.*\)") + FOREACH (_line ${_lines}) + STRING(REGEX MATCH "DEFINE_TEST\((.*)\)" _full_match ${_line}) + # CMake REGEX seems to handle ( and \( rather inconsistently... + # So we go through an extra dance to definitively strip the parens + STRING(REPLACE "(" "" _test_name_with_paren "${CMAKE_MATCH_1}") + STRING(REPLACE ")" "" _test_name "${_test_name_with_paren}") + SET(_full_test_name "${_component}_${_test_name}") + ADD_TEST(NAME ${_full_test_name} + COMMAND ${_component}_test -vv + -r ${CMAKE_CURRENT_SOURCE_DIR} + -s + ${_test_name}) + SET_TESTS_PROPERTIES(${_full_test_name} PROPERTIES SKIP_RETURN_CODE 2) + ENDFOREACH (_line) + ENDIF (_src MATCHES "test_[^/]+\\.c$") + ENDFOREACH (_src) + ENDIF(ENABLE_TEST) +ENDMACRO (DISCOVER_TESTS __list_sources) - ENDIF (NOT EXISTS "${_listfile}" OR - ${_cmlist} IS_NEWER_THAN "${_listfile}") -ENDMACRO (GENERATE_LIST_H) # # Generate installation rules for man pages. # @@ -663,7 +705,7 @@ IF(ENABLE_ZSTD) ENDIF() FIND_PATH(ZSTD_INCLUDE_DIR zstd.h HINTS ${PC_ZSTD_INCLUDEDIR} ${PC_ZSTD_INCLUDE_DIRS}) - FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd HINTS ${PC_ZSTD_LIBDIR} ${PC_ZSTD_LIBRARY_DIRS}) + FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd zstd_static HINTS ${PC_ZSTD_LIBDIR} ${PC_ZSTD_LIBRARY_DIRS}) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZSTD DEFAULT_MSG ZSTD_LIBRARY ZSTD_INCLUDE_DIR) ELSE(ENABLE_ZSTD) @@ -732,6 +774,7 @@ CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h> #include <linux/fs.h> int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS) +LA_CHECK_INCLUDE_FILE("intsafe.h" HAVE_INTSAFE_H) LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H) LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H) LA_CHECK_INCLUDE_FILE("membership.h" HAVE_MEMBERSHIP_H) @@ -746,6 +789,7 @@ LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H) LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H) LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H) LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H) +LA_CHECK_INCLUDE_FILE("stdckdint.h" HAVE_STDCKDINT_H) LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H) LA_CHECK_INCLUDE_FILE("stdio.h" HAVE_STDIO_H) LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H) @@ -781,12 +825,22 @@ IF(ENABLE_CNG) LA_CHECK_INCLUDE_FILE("bcrypt.h" HAVE_BCRYPT_H) IF(HAVE_BCRYPT_H) LIST(APPEND ADDITIONAL_LIBS "bcrypt") + # bcrypt supports these algorithms on all available versions + SET(ARCHIVE_CRYPTO_MD5 1) + SET(ARCHIVE_CRYPTO_MD5_WIN 1) + SET(ARCHIVE_CRYPTO_SHA1 1) + SET(ARCHIVE_CRYPTO_SHA1_WIN 1) + SET(ARCHIVE_CRYPTO_SHA256 1) + SET(ARCHIVE_CRYPTO_SHA256_WIN 1) + SET(ARCHIVE_CRYPTO_SHA384 1) + SET(ARCHIVE_CRYPTO_SHA384_WIN 1) + SET(ARCHIVE_CRYPTO_SHA512 1) + SET(ARCHIVE_CRYPTO_SHA512_WIN 1) ENDIF(HAVE_BCRYPT_H) ELSE(ENABLE_CNG) UNSET(HAVE_BCRYPT_H CACHE) ENDIF(ENABLE_CNG) # Following files need windows.h, so we should test it after windows.h test. -LA_CHECK_INCLUDE_FILE("wincrypt.h" HAVE_WINCRYPT_H) LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H) # @@ -814,11 +868,14 @@ IF(ENABLE_MBEDTLS) LIST(APPEND ADDITIONAL_LIBS ${MBEDCRYPTO_LIBRARY}) INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIRS}) + CMAKE_PUSH_CHECK_STATE() LIST(APPEND CMAKE_REQUIRED_INCLUDES ${MBEDTLS_INCLUDE_DIRS}) LA_CHECK_INCLUDE_FILE("mbedtls/aes.h" HAVE_MBEDTLS_AES_H) LA_CHECK_INCLUDE_FILE("mbedtls/md.h" HAVE_MBEDTLS_MD_H) LA_CHECK_INCLUDE_FILE("mbedtls/pkcs5.h" HAVE_MBEDTLS_PKCS5_H) LA_CHECK_INCLUDE_FILE("mbedtls/version.h" HAVE_MBEDTLS_VERSION_H) + CMAKE_POP_CHECK_STATE() + ENDIF(MBEDTLS_FOUND) MARK_AS_ADVANCED(CLEAR MBEDTLS_INCLUDE_DIRS) MARK_AS_ADVANCED(CLEAR MBEDCRYPTO_LIBRARY) @@ -834,6 +891,7 @@ IF(ENABLE_NETTLE) LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARIES}) INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR}) + CMAKE_PUSH_CHECK_STATE() LIST(APPEND CMAKE_REQUIRED_INCLUDES ${NETTLE_INCLUDE_DIR}) LA_CHECK_INCLUDE_FILE("nettle/aes.h" HAVE_NETTLE_AES_H) LA_CHECK_INCLUDE_FILE("nettle/hmac.h" HAVE_NETTLE_HMAC_H) @@ -842,6 +900,8 @@ IF(ENABLE_NETTLE) LA_CHECK_INCLUDE_FILE("nettle/ripemd160.h" HAVE_NETTLE_RIPEMD160_H) LA_CHECK_INCLUDE_FILE("nettle/sha.h" HAVE_NETTLE_SHA_H) LA_CHECK_INCLUDE_FILE("nettle/version.h" HAVE_NETTLE_VERSION_H) + CMAKE_POP_CHECK_STATE() + ENDIF(NETTLE_FOUND) MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR) MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES) @@ -857,11 +917,15 @@ IF(ENABLE_OPENSSL AND NOT CMAKE_SYSTEM_NAME MATCHES "Darwin") SET(HAVE_LIBCRYPTO 1) INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_CRYPTO_LIBRARY}) + + CMAKE_PUSH_CHECK_STATE() SET(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) LA_CHECK_INCLUDE_FILE("openssl/evp.h" HAVE_OPENSSL_EVP_H) LA_CHECK_INCLUDE_FILE("openssl/opensslv.h" HAVE_OPENSSL_OPENSSLV_H) CHECK_FUNCTION_EXISTS(PKCS5_PBKDF2_HMAC_SHA1 HAVE_PKCS5_PBKDF2_HMAC_SHA1) + CMAKE_POP_CHECK_STATE() + ENDIF(OPENSSL_FOUND) ELSE() SET(OPENSSL_FOUND FALSE) # Override cached value @@ -882,9 +946,13 @@ ENDIF(NOT OPENSSL_FOUND) # libbsd for readpassphrase on Haiku IF("${CMAKE_SYSTEM_NAME}" MATCHES "Haiku") MESSAGE(STATUS "Adding libbsd for Haiku") + + CMAKE_PUSH_CHECK_STATE() SET(CMAKE_REQUIRED_LIBRARIES "bsd") FIND_LIBRARY(LIBBSD_LIBRARY NAMES bsd) LIST(APPEND ADDITIONAL_LIBS ${LIBBSD_LIBRARY}) + CMAKE_POP_CHECK_STATE() + ENDIF("${CMAKE_SYSTEM_NAME}" MATCHES "Haiku") # @@ -996,85 +1064,6 @@ main(int argc, char **argv) ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) # -# CRYPTO functions on Windows is defined at archive_windows.c, thus we do not -# need the test what the functions can be mapped to archive_{crypto name}_init, -# archive_{crypto name}_update and archive_{crypto name}_final. -# The functions on Windows use CALG_{crypto name} macro to create a crypt object -# and then we need to know what CALG_{crypto name} macros is available to show -# ARCHIVE_CRYPTO_{crypto name}_WIN macros because Windows 2000 and earlier version -# of Windows XP do not support SHA256, SHA384 and SHA512. -# -MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) - IF(WIN32 AND NOT CYGWIN) - FOREACH(CRYPTO ${CRYPTO_LIST}) - IF(NOT ARCHIVE_CRYPTO_${CRYPTO}) - IF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN) - STRING(TOUPPER "${CRYPTO}" crypto) - SET(ALGID "") - IF ("${CRYPTO}" MATCHES "^MD5$") - SET(ALGID "CALG_MD5") - ENDIF ("${CRYPTO}" MATCHES "^MD5$") - IF ("${CRYPTO}" MATCHES "^SHA1$") - SET(ALGID "CALG_SHA1") - ENDIF ("${CRYPTO}" MATCHES "^SHA1$") - IF ("${CRYPTO}" MATCHES "^SHA256$") - SET(ALGID "CALG_SHA_256") - ENDIF ("${CRYPTO}" MATCHES "^SHA256$") - IF ("${CRYPTO}" MATCHES "^SHA384$") - SET(ALGID "CALG_SHA_384") - ENDIF ("${CRYPTO}" MATCHES "^SHA384$") - IF ("${CRYPTO}" MATCHES "^SHA512$") - SET(ALGID "CALG_SHA_512") - ENDIF ("${CRYPTO}" MATCHES "^SHA512$") - - CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h) - FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h" - CONFDEFS_H) - - SET(SOURCE "${CONFDEFS_H} - -#define ${crypto}_COMPILE_TEST -#include <windows.h> -#include <wincrypt.h> - -int -main(int argc, char **argv) -{ - return ${ALGID}; -} -") - SET(SOURCE_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_win.c") - - FILE(WRITE "${SOURCE_FILE}" "${SOURCE}") - MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN") - - TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN - ${CMAKE_BINARY_DIR} - ${SOURCE_FILE} - CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive" - OUTPUT_VARIABLE OUTPUT) - - IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN) - MESSAGE(STATUS - "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- found") - SET(ARCHIVE_CRYPTO_${CRYPTO} 1) - ELSE (ARCHIVE_CRYPTO_${CRYPTO}_WIN) - MESSAGE(STATUS - "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- not found") - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN failed with the following output:\n" - "${OUTPUT}\n" - "Source file was:\n${SOURCE}\n") - ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN) - ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN) - ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO}) - ENDFOREACH(CRYPTO) - ENDIF(WIN32 AND NOT CYGWIN) -ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) - -# # Find iconv # POSIX defines the second arg as const char ** # and requires it to be in libc. But we can accept @@ -2176,18 +2165,19 @@ ENDIF(ENABLE_ACL) # Check MD5/RMD160/SHA support # NOTE: Crypto checks must be run last before generating config.h # -CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" LIBC) -CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC2) -CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC3) -CHECK_CRYPTO("MD5;SHA1;SHA256;SHA384;SHA512" LIBSYSTEM) -CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" MBEDTLS) -CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" NETTLE) -CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" OPENSSL) - -# Libmd has to be probed after OpenSSL. -CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA512" LIBMD) +IF(CMAKE_SYSTEM_NAME MATCHES "Darwin") + CHECK_CRYPTO("MD5;SHA1;SHA256;SHA384;SHA512" LIBSYSTEM) +ELSE() + CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" LIBC) + CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC2) + CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC3) + CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" MBEDTLS) + CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" NETTLE) + CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" OPENSSL) -CHECK_CRYPTO_WIN("MD5;SHA1;SHA256;SHA384;SHA512") + # Libmd has to be probed after OpenSSL. + CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA512" LIBMD) +ENDIF() # Check visibility annotations SET(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") diff --git a/Makefile.am b/Makefile.am index c34e8da922d2..58bc73ec227f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,6 +19,8 @@ BUILT_SOURCES= libarchive/test/list.h tar/test/list.h cpio/test/list.h cat/test/ check_PROGRAMS= libarchive_test $(bsdtar_test_programs) $(bsdcpio_test_programs) $(bsdcat_test_programs) $(bsdunzip_test_programs) TESTS= libarchive_test $(bsdtar_test_programs) $(bsdcpio_test_programs) $(bsdcat_test_programs) $(bsdunzip_test_programs) TESTS_ENVIRONMENT= $(libarchive_TESTS_ENVIRONMENT) $(bsdtar_TESTS_ENVIRONMENT) $(bsdcpio_TESTS_ENVIRONMENT) $(bsdcat_TESTS_ENVIRONMENT) $(bsdunzip_TESTS_ENVIRONMENT) +# Uncomment the following to enable verbose test output: +# TESTS_ENVIRONMENT += _VERBOSITY_LEVEL=2 # Always build and test both bsdtar and bsdcpio as part of 'distcheck' DISTCHECK_CONFIGURE_FLAGS = --enable-bsdtar --enable-bsdcpio # The next line is commented out by default in shipping libarchive releases. @@ -64,6 +66,11 @@ dist-hook: -rm -f $(distdir)/*/Makefile $(distdir)/*/*/Makefile cd $(distdir)/doc && /bin/sh update.sh +# Verify dist includes all files needed by CMake +distcheck-hook: + mkdir $(distdir)/_build/cmake + cd $(distdir)/_build/cmake && cmake ../.. && make && make test + # # Extra rules for cleanup # @@ -107,6 +114,7 @@ noinst_HEADERS= \ libarchive/archive_entry_locale.h \ libarchive/archive_entry_private.h \ libarchive/archive_hmac_private.h \ + libarchive/archive_integer.h \ libarchive/archive_openssl_evp_private.h \ libarchive/archive_openssl_hmac_private.h \ libarchive/archive_options_private.h \ @@ -372,10 +380,13 @@ libarchive_test_SOURCES= \ libarchive/test/read_open_memory.c \ libarchive/test/test_7zip_filename_encoding.c \ libarchive/test/test_acl_nfs4.c \ + libarchive/test/test_acl_nfs4_null_id_overflow.c \ + libarchive/test/test_acl_nfs4_text.c \ libarchive/test/test_acl_pax.c \ libarchive/test/test_acl_platform_nfs4.c \ libarchive/test/test_acl_platform_posix1e.c \ libarchive/test/test_acl_posix1e.c \ + libarchive/test/test_acl_posix1e_text.c \ libarchive/test/test_acl_text.c \ libarchive/test/test_ar_mode.c \ libarchive/test/test_archive_api_feature.c \ @@ -387,6 +398,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_archive_match_time.c \ libarchive/test/test_archive_parse_date.c \ libarchive/test/test_archive_pathmatch.c \ + libarchive/test/test_archive_pathmatch_oob.c \ libarchive/test/test_archive_read.c \ libarchive/test/test_archive_read_add_passphrase.c \ libarchive/test/test_archive_read_close_twice.c \ @@ -404,6 +416,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_archive_set_error.c \ libarchive/test/test_archive_string.c \ libarchive/test/test_archive_string_conversion.c \ + libarchive/test/test_archive_write_add_filter.c \ libarchive/test/test_archive_write_add_filter_by_name.c \ libarchive/test/test_archive_write_set_filter_option.c \ libarchive/test/test_archive_write_set_format_by_name.c \ @@ -455,20 +468,24 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_disk_entry_from_file.c \ libarchive/test/test_read_extract.c \ libarchive/test/test_read_file_nonexistent.c \ + libarchive/test/test_read_files_compressed.c \ libarchive/test/test_read_filter_compress.c \ libarchive/test/test_read_filter_grzip.c \ libarchive/test/test_read_filter_gzip_recursive.c \ libarchive/test/test_read_filter_lrzip.c \ + libarchive/test/test_read_filter_lz4_raw.c \ libarchive/test/test_read_filter_lzop.c \ libarchive/test/test_read_filter_lzop_multiple_parts.c \ libarchive/test/test_read_filter_program.c \ libarchive/test/test_read_filter_program_signature.c \ + libarchive/test/test_read_filter_zstd_raw.c \ libarchive/test/test_read_filter_uudecode.c \ libarchive/test/test_read_filter_uudecode_raw.c \ libarchive/test/test_read_format_7zip.c \ libarchive/test/test_read_format_7zip_encryption_data.c \ libarchive/test/test_read_format_7zip_encryption_partially.c \ libarchive/test/test_read_format_7zip_encryption_header.c \ + libarchive/test/test_read_format_7zip_entries_oom.c \ libarchive/test/test_read_format_7zip_issue2765.c \ libarchive/test/test_read_format_7zip_malformed.c \ libarchive/test/test_read_format_7zip_packinfo_digests.c \ @@ -476,6 +493,9 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_cab.c \ libarchive/test/test_read_format_cab_filename.c \ libarchive/test/test_read_format_cab_lzx_oob.c \ + libarchive/test/test_read_format_cab_mszip_oob.c \ + libarchive/test/test_read_format_cab_multi.c \ + libarchive/test/test_read_format_cab_skip_malformed.c \ libarchive/test/test_read_format_cpio_afio.c \ libarchive/test/test_read_format_cpio_bin.c \ libarchive/test/test_read_format_cpio_bin_Z.c \ @@ -502,6 +522,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_gtar_sparse_skip_entry.c \ libarchive/test/test_read_format_huge_rpm.c \ libarchive/test/test_read_format_iso_Z.c \ + libarchive/test/test_read_format_iso_joliet_utf16be_overflow.c \ libarchive/test/test_read_format_iso_multi_extent.c \ libarchive/test/test_read_format_iso_xorriso.c \ libarchive/test/test_read_format_isojoliet_bz2.c \ @@ -510,6 +531,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_isojoliet_versioned.c \ libarchive/test/test_read_format_isorr_bz2.c \ libarchive/test/test_read_format_isorr_ce.c \ + libarchive/test/test_read_format_isorr_ce_loop.c \ libarchive/test/test_read_format_isorr_new_bz2.c \ libarchive/test/test_read_format_isorr_rr_moved.c \ libarchive/test/test_read_format_isozisofs_bz2.c \ @@ -531,9 +553,13 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_rar_invalid1.c \ libarchive/test/test_read_format_rar_overflow.c \ libarchive/test/test_read_format_rar5.c \ + libarchive/test/test_read_format_rar5_bad_filter.c \ + libarchive/test/test_read_format_rar5_bad_tables.c \ + libarchive/test/test_read_format_rar5_block_hdr_fail_loop.c \ libarchive/test/test_read_format_rar5_loop_bug.c \ libarchive/test/test_read_format_raw.c \ libarchive/test/test_read_format_tar.c \ + libarchive/test/test_read_format_tar_acl_oob_read.c \ libarchive/test/test_read_format_tar_V_negative_size.c \ libarchive/test/test_read_format_tar_concatenated.c \ libarchive/test/test_read_format_tar_empty_pax.c \ @@ -545,6 +571,8 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_tar_pax_g_large.c \ libarchive/test/test_read_format_tar_pax_large_attr.c \ libarchive/test/test_read_format_tar_pax_negative_time.c \ + libarchive/test/test_read_format_tar_pax_timestamps.c \ + libarchive/test/test_read_format_tar_timestamp_overflow.c \ libarchive/test/test_read_format_tbz.c \ libarchive/test/test_read_format_tgz.c \ libarchive/test/test_read_format_tlz.c \ @@ -575,6 +603,8 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_zip_winzip_aes.c \ libarchive/test/test_read_format_zip_winzip_aes_large.c \ libarchive/test/test_read_format_zip_zip64.c \ + libarchive/test/test_read_format_zip_zipx_encrypted.c \ + libarchive/test/test_read_format_zip_zipx_lzma_oom.c \ libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c \ libarchive/test/test_read_large.c \ libarchive/test/test_read_pax_empty_val_no_nl.c \ @@ -638,22 +668,29 @@ libarchive_test_SOURCES= \ libarchive/test/test_write_format_gnutar_filenames.c \ libarchive/test/test_write_format_iso9660.c \ libarchive/test/test_write_format_iso9660_boot.c \ + libarchive/test/test_write_format_iso9660_bugs.c \ libarchive/test/test_write_format_iso9660_empty.c \ libarchive/test/test_write_format_iso9660_filename.c \ + libarchive/test/test_write_format_iso9660_joliet_id.c \ + libarchive/test/test_write_format_iso9660_rockridge.c \ libarchive/test/test_write_format_iso9660_zisofs.c \ libarchive/test/test_write_format_mtree.c \ + libarchive/test/test_write_format_mtree_absolute.c \ libarchive/test/test_write_format_mtree_absolute_path.c \ libarchive/test/test_write_format_mtree_classic.c \ libarchive/test/test_write_format_mtree_classic_indent.c\ + libarchive/test/test_write_format_mtree_dotdot.c \ libarchive/test/test_write_format_mtree_fflags.c \ libarchive/test/test_write_format_mtree_no_separator.c \ libarchive/test/test_write_format_mtree_preset_digests.c \ libarchive/test/test_write_format_mtree_quoted_filename.c\ + libarchive/test/test_write_format_mtree_null_deref.c \ libarchive/test/test_write_format_pax.c \ libarchive/test/test_write_format_raw.c \ libarchive/test/test_write_format_raw_b64.c \ libarchive/test/test_write_format_shar_empty.c \ libarchive/test/test_write_format_tar.c \ + libarchive/test/test_write_format_tar_empty_dirname.c \ libarchive/test/test_write_format_tar_empty.c \ libarchive/test/test_write_format_tar_sparse.c \ libarchive/test/test_write_format_tar_ustar.c \ @@ -661,7 +698,9 @@ libarchive_test_SOURCES= \ libarchive/test/test_write_format_warc.c \ libarchive/test/test_write_format_warc_empty.c \ libarchive/test/test_write_format_xar.c \ + libarchive/test/test_write_format_xar_bugs.c \ libarchive/test/test_write_format_xar_empty.c \ + libarchive/test/test_write_format_xar_fflags.c \ libarchive/test/test_write_format_zip.c \ libarchive/test/test_write_format_zip64_stream.c \ libarchive/test/test_write_format_zip_compression_store.c \ @@ -669,11 +708,13 @@ libarchive_test_SOURCES= \ libarchive/test/test_write_format_zip_compression_bzip2.c \ libarchive/test/test_write_format_zip_compression_lzmaxz.c \ libarchive/test/test_write_format_zip_empty.c \ + libarchive/test/test_write_format_zip_empty_pathname.c \ libarchive/test/test_write_format_zip_empty_zip64.c \ libarchive/test/test_write_format_zip_entry_size_unset.c \ libarchive/test/test_write_format_zip_file.c \ libarchive/test/test_write_format_zip_file_zip64.c \ libarchive/test/test_write_format_zip_large.c \ + libarchive/test/test_write_format_zip_long_pathname.c \ libarchive/test/test_write_format_zip_stream.c \ libarchive/test/test_write_format_zip_windows_path.c \ libarchive/test/test_write_format_zip_zip64.c \ @@ -701,9 +742,12 @@ libarchive_TESTS_ENVIRONMENT= LIBARCHIVE_TEST_FILES=`cd $(top_srcdir);/bin/pwd`/ libarchive_test_EXTRA_DIST=\ libarchive/test/list.h \ + libarchive/test/test_fuzz_consumer.h \ libarchive/test/test_acl_pax_posix1e.tar.uu \ libarchive/test/test_acl_pax_nfs4.tar.uu \ libarchive/test/test_archive_string_conversion.txt.Z.uu \ + libarchive/test/test_archive_pathmatch_oob_bracket.bin.uu \ + libarchive/test/test_archive_pathmatch_oob_strchr.bin.uu \ libarchive/test/test_compat_bzip2_1.tbz.uu \ libarchive/test/test_compat_bzip2_2.tbz.uu \ libarchive/test/test_compat_cpio_1.cpio.uu \ @@ -783,13 +827,17 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_rar_multivolume_uncompressed_files.part08.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part09.rar.uu \ libarchive/test/test_rar_multivolume_uncompressed_files.part10.rar.uu \ + libarchive/test/test_read_files_compressed.part01.uu \ + libarchive/test/test_read_files_compressed.part02.uu \ libarchive/test/test_read_filter_grzip.tar.grz.uu \ libarchive/test/test_read_filter_gzip_recursive.gz.uu \ libarchive/test/test_read_filter_lrzip.tar.lrz.uu \ + libarchive/test/test_read_filter_lz4_raw_skip.uu \ libarchive/test/test_read_filter_lzop.tar.lzo.uu \ libarchive/test/test_read_filter_lzop_multiple_parts.tar.lzo.uu \ libarchive/test/test_read_filter_uudecode_raw.uu \ libarchive/test/test_read_filter_uudecode_base64_raw.uu \ + libarchive/test/test_read_filter_zstd_raw_loop.uu \ libarchive/test/test_read_format_mtree_crash747.mtree.bz2.uu \ libarchive/test/test_read_format_mtree_noprint.mtree.uu \ libarchive/test/test_read_format_7zip_bcj2_bzip2.7z.uu \ @@ -821,6 +869,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_7zip_encryption.7z.uu \ libarchive/test/test_read_format_7zip_encryption_header.7z.uu \ libarchive/test/test_read_format_7zip_encryption_partially.7z.uu \ + libarchive/test/test_read_format_7zip_entries_oom.7z.uu \ libarchive/test/test_read_format_7zip_extract_second.7z.uu \ libarchive/test/test_read_format_7zip_issue2765.7z.uu \ libarchive/test/test_read_format_7zip_lzma1.7z.uu \ @@ -835,6 +884,8 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_7zip_malformed.7z.uu \ libarchive/test/test_read_format_7zip_malformed2.7z.uu \ libarchive/test/test_read_format_7zip_malformed3.7z.uu \ + libarchive/test/test_read_format_7zip_malformed4.7z.uu \ + libarchive/test/test_read_format_7zip_malformed_numfiles_oom.7z.uu \ libarchive/test/test_read_format_7zip_packinfo_digests.7z.uu \ libarchive/test/test_read_format_7zip_ppmd.7z.uu \ libarchive/test/test_read_format_7zip_sfx_elf.elf.uu \ @@ -855,6 +906,11 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_cab_3.cab.uu \ libarchive/test/test_read_format_cab_filename_cp932.cab.uu \ libarchive/test/test_read_format_cab_lzx_oob.cab.uu \ + libarchive/test/test_read_format_cab_multi.p1.cab.uu \ + libarchive/test/test_read_format_cab_multi.p2.cab.uu \ + libarchive/test/test_read_format_cab_skip_malformed.cab.uu \ + libarchive/test/test_read_format_cpio_afio_header.part1.cpio.uu \ + libarchive/test/test_read_format_cpio_afio_header.part2.cpio.uu \ libarchive/test/test_read_format_cpio_bin_be.cpio.uu \ libarchive/test/test_read_format_cpio_bin_le.cpio.uu \ libarchive/test/test_read_format_cpio_filename_cp866.cpio.uu \ @@ -884,9 +940,11 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_iso_joliet_by_nero.iso.Z.uu \ libarchive/test/test_read_format_iso_joliet_long.iso.Z.uu \ libarchive/test/test_read_format_iso_joliet_rockridge.iso.Z.uu \ + libarchive/test/test_read_format_iso_joliet_utf16be_overflow.iso.uu \ libarchive/test/test_read_format_iso_multi_extent.iso.Z.uu \ libarchive/test/test_read_format_iso_rockridge.iso.Z.uu \ libarchive/test/test_read_format_iso_rockridge_ce.iso.Z.uu \ + libarchive/test/test_read_format_iso_rockridge_ce_loop.iso.Z.uu \ libarchive/test/test_read_format_iso_rockridge_new.iso.Z.uu \ libarchive/test/test_read_format_iso_rockridge_rr_moved.iso.Z.uu \ libarchive/test/test_read_format_iso_xorriso.iso.Z.uu \ @@ -919,11 +977,13 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_rar_filter.rar.uu \ libarchive/test/test_read_format_rar_invalid1.rar.uu \ libarchive/test/test_read_format_rar_multi_lzss_blocks.rar.uu \ + libarchive/test/test_read_format_rar3_lowdist_reset.rar.uu \ libarchive/test/test_read_format_rar_multivolume.part0001.rar.uu \ libarchive/test/test_read_format_rar_multivolume.part0002.rar.uu \ libarchive/test/test_read_format_rar_multivolume.part0003.rar.uu \ libarchive/test/test_read_format_rar_multivolume.part0004.rar.uu \ libarchive/test/test_read_format_rar_newsub_huge.rar.uu \ + libarchive/test/test_read_format_rar_newsub_rr_over_1m.rar.uu \ libarchive/test/test_read_format_rar_noeof.rar.uu \ libarchive/test/test_read_format_rar_overflow.rar.uu \ libarchive/test/test_read_format_rar_ppmd_lzss_conversion.rar.uu \ @@ -932,13 +992,16 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_rar_sfx.exe.uu \ libarchive/test/test_read_format_rar_subblock.rar.uu \ libarchive/test/test_read_format_rar_symlink_huge.rar.uu \ + libarchive/test/test_read_format_rar_unbound_staticdata.rar.uu \ libarchive/test/test_read_format_rar_unicode.rar.uu \ libarchive/test/test_read_format_rar_windows.rar.uu \ libarchive/test/test_read_format_rar4_encrypted.rar.uu \ libarchive/test/test_read_format_rar4_encrypted_filenames.rar.uu \ libarchive/test/test_read_format_rar4_solid_encrypted.rar.uu \ libarchive/test/test_read_format_rar4_solid_encrypted_filenames.rar.uu \ + libarchive/test/test_read_format_rar5_main_block_extra_bytes.rar.uu \ libarchive/test/test_read_format_rar5_only_crypt_exfld.rar.uu \ + libarchive/test/test_read_format_rar5_skip_block_extra_bytes.rar.uu \ libarchive/test/test_read_format_rar5_unsupported_exfld.rar.uu \ libarchive/test/test_read_format_rar5_invalid_hash_valid_htime_exfld.rar.uu \ libarchive/test/test_read_format_rar5_encrypted.rar.uu \ @@ -947,6 +1010,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_rar5_solid_encrypted_filenames.rar.uu \ libarchive/test/test_read_format_rar5_arm.rar.uu \ libarchive/test/test_read_format_rar5_blake2.rar.uu \ + libarchive/test/test_read_format_rar5_bytes_remaining_underflow.rar.uu \ libarchive/test/test_read_format_rar5_compressed.rar.uu \ libarchive/test/test_read_format_rar5_different_window_size.rar.uu \ libarchive/test/test_read_format_rar5_different_solid_window_size.rar.uu \ @@ -989,6 +1053,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu \ libarchive/test/test_read_format_rar5_decode_number_out_of_bounds_read.rar.uu \ libarchive/test/test_read_format_rar5_window_buf_and_size_desync.rar.uu \ + libarchive/test/test_read_format_rar5_bad_tables.rar.uu \ libarchive/test/test_read_format_rar5_bad_window_sz_in_mltarc_file.rar.uu \ libarchive/test/test_read_format_rar5_data_ready_pointer_leak.rar.uu \ libarchive/test/test_read_format_raw.bufr.uu \ @@ -996,6 +1061,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_raw.data.Z.uu \ libarchive/test/test_read_format_raw.data.uu \ libarchive/test/test_read_format_tar_V_negative_size.tar.uu \ + libarchive/test/test_read_format_tar_acl_oob_read.tar.uu \ libarchive/test/test_read_format_tar_concatenated.tar.uu \ libarchive/test/test_read_format_tar_empty_filename.tar.uu \ libarchive/test/test_read_format_tar_empty_with_gnulabel.tar.uu \ @@ -1006,6 +1072,8 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_tar_pax_g_large.tar.uu \ libarchive/test/test_read_format_tar_pax_large_attr.tar.Z.uu \ libarchive/test/test_read_format_tar_pax_negative_time.tar.uu \ + libarchive/test/test_read_format_tar_pax_timestamps.tar.uu \ + libarchive/test/test_read_format_tar_timestamp_overflow.tar.uu \ libarchive/test/test_read_format_ustar_filename_cp866.tar.Z.uu \ libarchive/test/test_read_format_ustar_filename_eucjp.tar.Z.uu \ libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \ @@ -1013,6 +1081,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_warc_incomplete.warc.uu \ libarchive/test/test_read_format_xar_doublelink.xar.uu \ libarchive/test/test_read_format_xar_duplicate_filename_node.xar.uu \ + libarchive/test/test_read_format_xar_large_mode.xar.uu \ libarchive/test/test_read_format_zip.zip.uu \ libarchive/test/test_read_format_zip_7075_utf8_paths.zip.uu \ libarchive/test/test_read_format_zip_7z_deflate.zip.uu \ @@ -1058,11 +1127,17 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_zip_winzip_aes128.zip.uu \ libarchive/test/test_read_format_zip_winzip_aes256.zip.uu \ libarchive/test/test_read_format_zip_winzip_aes256_large.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes256_large_bzip2.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes256_large_lzma.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes256_large_ppmd.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes256_large_xz.zip.uu \ + libarchive/test/test_read_format_zip_winzip_aes256_large_zstd.zip.uu \ libarchive/test/test_read_format_zip_winzip_aes256_stored.zip.uu \ libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.zip.uu \ libarchive/test/test_read_format_zip_xz_multi.zipx.uu \ libarchive/test/test_read_format_zip_zip64a.zip.uu \ libarchive/test/test_read_format_zip_zip64b.zip.uu \ + libarchive/test/test_read_format_zip_zipx_lzma_oom.zipx.uu \ libarchive/test/test_read_format_zip_zstd.zipx.uu \ libarchive/test/test_read_format_zip_zstd_multi.zipx.uu \ libarchive/test/test_read_large_splitted_rar_aa.uu \ @@ -1086,20 +1161,28 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_write_disk_hfs_compression.tgz.uu \ libarchive/test/test_write_disk_mac_metadata.tar.gz.uu \ libarchive/test/test_write_disk_no_hfs_compression.tgz.uu \ + libarchive/test/test_write_format_iso9660_joliet_overflow.bin.uu \ + libarchive/test/test_write_format_iso9660_null_deref.bin.uu \ + libarchive/test/test_write_format_iso9660_underflow.bin.uu \ + libarchive/test/test_write_format_mtree_null_deref.bin.uu \ + libarchive/test/test_write_format_xar_strcpy_overlap.bin.uu \ + libarchive/test/test_write_format_xar_underflow.bin.uu \ libarchive/test/CMakeLists.txt \ libarchive/test/README # -# Common code for libarchive frontends (cpio, tar) +# Common code for libarchive frontends (cat, cpio, tar, unzip) # noinst_HEADERS+= \ libarchive_fe/lafe_err.h \ + libarchive_fe/lafe_fnmatch.h \ libarchive_fe/lafe_getline.h \ libarchive_fe/lafe_platform.h \ libarchive_fe/line_reader.h \ libarchive_fe/passphrase.h libarchive_fe_la_SOURCES= \ libarchive_fe/lafe_err.c \ + libarchive_fe/lafe_fnmatch.c \ libarchive_fe/lafe_getline.c \ libarchive_fe/line_reader.c \ libarchive_fe/passphrase.c @@ -1,3 +1,5 @@ +Jun 23, 2026: libarchive 3.8.8 released + Apr 13, 2026: libarchive 3.8.7 released Mar 10, 2026: libarchive 3.8.6 released diff --git a/SECURITY.md b/SECURITY.md index f2f60e792a57..33c37e470004 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,9 +1,10 @@ # Security Policy -If you have discovered a security vulnerability in this project, please report it -privately. **Do not disclose it as a public issue.** This gives us time to work with you -to fix the issue before public exposure, reducing the chance that the exploit will be -used before a patch is released. +If you have discovered a security vulnerability in this project, +please report it privately. +**Do not disclose it as a public issue.** +This gives us time to work with you to fix the issue before public exposure, +reducing the chance that the exploit will be used before a patch is released. You may submit the report in the following ways: @@ -15,5 +16,11 @@ Please provide the following information in your report: - A description of the vulnerability and its impact - How to reproduce the issue -This project is maintained by volunteers on a reasonable-effort basis. As such, we ask -that you give us 90 days to work on a fix before public exposure. +While we welcome all reports, we can act most quickly if the report +includes a complete libarchive test case and a proposed fix. +See [doc/WRITING_TESTS.md](doc/WRITING_TESTS.md) for guidance on creating a reproduction test case. +You can provide the test case and proposed fix as separate patch files +prepared with `git format-patch` or `git diff`. + +This project is maintained by volunteers on a reasonable-effort basis. +We ask that you give us 90 days to work on a fix before public exposure. diff --git a/build/ci/github_actions/ci.cmd b/build/ci/github_actions/ci.cmd index 1d80cc5d98bf..47600aa4bdf0 100755 --- a/build/ci/github_actions/ci.cmd +++ b/build/ci/github_actions/ci.cmd @@ -1,126 +1,32 @@ @ECHO OFF -SET ZLIB_VERSION=1.3 -SET BZIP2_VERSION=1ea1ac188ad4b9cb662e3f8314673c63df95a589 -SET XZ_VERSION=5.6.3 IF NOT "%BE%"=="mingw-gcc" ( IF NOT "%BE%"=="msvc" ( - ECHO Environment variable BE must be mingw-gcc or msvc - EXIT /b 1 + IF NOT "%BE%"=="cygwin-gcc" ( + ECHO Environment variable BE must be cygwin-gcc, mingw-gcc or msvc + EXIT /b 1 + ) ) ) -REM v1.5.6 has a bug with the CMake files & MSVC -REM https://github.com/facebook/zstd/issues/3999 -REM Fall back to 1.5.5 for MSVC until fixed -IF "%BE%"=="msvc" ( - SET ZSTD_VERSION=1.5.5 -) ELSE ( - SET ZSTD_VERSION=1.5.6 -) - SET ORIGPATH=%PATH% IF "%BE%"=="mingw-gcc" ( - SET MINGWPATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files\cmake\bin;C:\ProgramData\mingw64\mingw64\bin + SET MINGWPATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\msys64\mingw64\bin;C:\Program Files\cmake\bin ) -IF "%1"=="deplibs" ( - IF NOT EXIST build_ci\libs ( - MKDIR build_ci\libs - ) - CD build_ci\libs - IF NOT EXIST zlib-%ZLIB_VERSION%.zip ( - ECHO Downloading https://github.com/libarchive/zlib/archive/v%ZLIB_VERSION%.zip - curl -L -o zlib-%ZLIB_VERSION%.zip https://github.com/libarchive/zlib/archive/v%ZLIB_VERSION%.zip || EXIT /b 1 - ) - IF NOT EXIST zlib-%ZLIB_VERSION% ( - ECHO Unpacking zlib-%ZLIB_VERSION%.zip - C:\windows\system32\tar.exe -x -f zlib-%ZLIB_VERSION%.zip || EXIT /b 1 - ) - IF NOT EXIST bzip2-%BZIP2_VERSION%.zip ( - echo Downloading https://github.com/libarchive/bzip2/archive/%BZIP2_VERSION%.zip - curl -L -o bzip2-%BZIP2_VERSION%.zip https://github.com/libarchive/bzip2/archive/%BZIP2_VERSION%.zip || EXIT /b 1 - ) - IF NOT EXIST bzip2-%BZIP2_VERSION% ( - echo Unpacking bzip2-%BZIP2_VERSION%.zip - C:\windows\system32\tar.exe -x -f bzip2-%BZIP2_VERSION%.zip || EXIT /b 1 - ) - IF NOT EXIST xz-%XZ_VERSION%.zip ( - echo Downloading https://github.com/libarchive/xz/archive/%XZ_VERSION%.zip - curl -L -o xz-%XZ_VERSION%.zip https://github.com/libarchive/xz/archive/v%XZ_VERSION%.zip || EXIT /b 1 - ) - IF NOT EXIST xz-%XZ_VERSION% ( - echo Unpacking xz-%XZ_VERSION%.zip - C:\windows\system32\tar.exe -x -f xz-%XZ_VERSION%.zip || EXIT /b 1 - ) - IF NOT EXIST zstd-%ZSTD_VERSION%.zip ( - echo Downloading https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD_VERSION%.zip - curl -L -o zstd-%ZSTD_VERSION%.zip https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD_VERSION%.zip || EXIT /b 1 - ) - IF NOT EXIST zstd-%ZSTD_VERSION% ( - echo Unpacking zstd-%ZSTD_VERSION%.zip - C:\windows\system32\tar.exe -x -f zstd-%ZSTD_VERSION%.zip || EXIT /b 1 - ) - CD zlib-%ZLIB_VERSION% - IF "%BE%"=="mingw-gcc" ( - SET PATH=%MINGWPATH% - cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1 - mingw32-make -j %NUMBER_OF_PROCESSORS% || EXIT /b 1 - mingw32-make test || EXIT /b 1 - mingw32-make install || EXIT /b 1 - ) ELSE IF "%BE%"=="msvc" ( - cmake -G "Visual Studio 17 2022" . || EXIT /b 1 - cmake --build . --target ALL_BUILD --config Release || EXIT /b 1 - cmake --build . --target RUN_TESTS --config Release || EXIT /b 1 - cmake --build . --target INSTALL --config Release || EXIT /b 1 - ) - CD .. - CD bzip2-%BZIP2_VERSION% - IF "%BE%"=="mingw-gcc" ( - SET PATH=%MINGWPATH% - cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" -D ENABLE_LIB_ONLY=ON -D ENABLE_SHARED_LIB=OFF -D ENABLE_STATIC_LIB=ON . || EXIT /b 1 - mingw32-make -j %NUMBER_OF_PROCESSORS% || EXIT /b 1 - REM mingw32-make test || EXIT /b 1 - mingw32-make install || EXIT /b 1 - ) ELSE IF "%BE%"=="msvc" ( - cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" -D ENABLE_LIB_ONLY=ON -D ENABLE_SHARED_LIB=OFF -D ENABLE_STATIC_LIB=ON . || EXIT /b 1 - cmake --build . --target ALL_BUILD --config Release || EXIT /b 1 - REM cmake --build . --target RUN_TESTS --config Release || EXIT /b 1 - cmake --build . --target INSTALL --config Release || EXIT /b 1 - ) - CD .. - CD xz-%XZ_VERSION% - IF "%BE%"=="mingw-gcc" ( - SET PATH=%MINGWPATH% - cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1 - mingw32-make -j %NUMBER_OF_PROCESSORS% || EXIT /b 1 - mingw32-make install || EXIT /b 1 - ) ELSE IF "%BE%"=="msvc" ( - cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1 - cmake --build . --target ALL_BUILD --config Release || EXIT /b 1 - cmake --build . --target INSTALL --config Release || EXIT /b 1 - ) - CD .. - CD zstd-%ZSTD_VERSION%\build\cmake - IF "%BE%"=="mingw-gcc" ( - SET PATH=%MINGWPATH% - cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1 - mingw32-make -j %NUMBER_OF_PROCESSORS% || EXIT /b 1 - mingw32-make install || EXIT /b 1 - ) ELSE IF "%BE%"=="msvc" ( - cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1 - cmake --build . --target ALL_BUILD --config Release || EXIT /b 1 - cmake --build . --target INSTALL --config Release || EXIT /b 1 - ) -) ELSE IF "%1%"=="configure" ( +IF "%1%"=="configure" ( IF "%BE%"=="mingw-gcc" ( SET PATH=%MINGWPATH% MKDIR build_ci\cmake CD build_ci\cmake - cmake -G "MinGW Makefiles" -D ZLIB_LIBRARY="C:/Program Files (x86)/zlib/lib/libzlibstatic.a" -D ZLIB_INCLUDE_DIR="C:/Program Files (x86)/zlib/include" -D BZIP2_LIBRARIES="C:/Program Files (x86)/bzip2/lib/libbz2_static.a" -D BZIP2_INCLUDE_DIR="C:/Program Files (x86)/bzip2/include" -D LIBLZMA_LIBRARY="C:/Program Files (x86)/xz/lib/liblzma.a" -D LIBLZMA_INCLUDE_DIR="C:/Program Files (x86)/xz/include" -D ZSTD_LIBRARY="C:/Program Files (x86)/zstd/lib/libzstd.a" -D ZSTD_INCLUDE_DIR="C:/Program Files (x86)/zstd/include" ..\.. || EXIT /b 1 + cmake -G "MinGW Makefiles" ..\.. || EXIT /b 1 ) ELSE IF "%BE%"=="msvc" ( MKDIR build_ci\cmake CD build_ci\cmake - cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" -D ZLIB_LIBRARY="C:/Program Files (x86)/zlib/lib/zlibstatic.lib" -D ZLIB_INCLUDE_DIR="C:/Program Files (x86)/zlib/include" -D BZIP2_LIBRARIES="C:/Program Files (x86)/bzip2/lib/bz2_static.lib" -D BZIP2_INCLUDE_DIR="C:/Program Files (x86)/bzip2/include" -D LIBLZMA_LIBRARY="C:/Program Files (x86)/xz/lib/lzma.lib" -D LIBLZMA_INCLUDE_DIR="C:/Program Files (x86)/xz/include" -D ZSTD_LIBRARY="C:/Program Files (x86)/zstd/lib/zstd_static.lib" -D ZSTD_INCLUDE_DIR="C:/Program Files (x86)/zstd/include" ..\.. || EXIT /b 1 + cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" --toolchain "%VCPKG_INSTALLATION_ROOT%\scripts\buildsystems\vcpkg.cmake" -D VCPKG_TARGET_TRIPLET=x64-windows-static -D VCPKG_MANIFEST_DIR=%GITHUB_WORKSPACE%\build\ci\github_actions ..\.. || EXIT /b 1 + ) ELSE IF "%BE%"=="cygwin-gcc" ( + SET BS=cmake + SET CYGWIN_NOWINPATH=1 + D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a configure" || EXIT /b 1 ) ) ELSE IF "%1%"=="build" ( IF "%BE%"=="mingw-gcc" ( @@ -130,6 +36,11 @@ IF "%1"=="deplibs" ( ) ELSE IF "%BE%"=="msvc" ( CD build_ci\cmake cmake --build . --target ALL_BUILD --config Release || EXIT /b 1 + ) ELSE IF "%BE%"=="cygwin-gcc" ( + SET BS=cmake + SET MAKE_ARGS=-j + SET CYGWIN_NOWINPATH=1 + D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a build" || EXIT /b 1 ) ) ELSE IF "%1%"=="test" ( IF "%BE%"=="mingw-gcc" ( @@ -140,6 +51,13 @@ IF "%1"=="deplibs" ( ) ELSE IF "%BE%"=="msvc" ( CD build_ci\cmake cmake --build . --target RUN_TESTS --config Release || EXIT /b 1 + ) ELSE IF "%BE%"=="cygwin-gcc" ( + REM SET BS=cmake + REM SET CYGWIN_NOWINPATH=1 + REM SET SKIP_TEST_SPARSE=1 + ECHO "Skipping tests on this platform" + REM D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a test" || EXIT /b 1 + EXIT /b 0 ) ) ELSE IF "%1%"=="install" ( IF "%BE%"=="mingw-gcc" ( @@ -149,10 +67,23 @@ IF "%1"=="deplibs" ( ) ELSE IF "%BE%"=="msvc" ( CD build_ci\cmake cmake --build . --target INSTALL --config Release || EXIT /b 1 + ) ELSE IF "%BE%"=="cygwin-gcc" ( + SET BS=cmake + SET CYGWIN_NOWINPATH=1 + D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a install" || EXIT /b 1 + REM Exit early here; the build.sh install step for Cygwin prints the version. + EXIT /b 0 ) "C:\Program Files (x86)\libarchive\bin\bsdtar.exe" --version ) ELSE IF "%1"=="artifact" ( - C:\windows\system32\tar.exe -c -C "C:\Program Files (x86)" --format=zip -f libarchive.zip libarchive + IF "%BE%"=="cygwin-gcc" ( + SET BS=cmake + SET CYGWIN_NOWINPATH=1 + D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a artifact" || EXIT /b 1 + EXIT /b 0 + ) + + C:\windows\system32\tar.exe -c -C "C:\Program Files (x86)" --format=zip -f libarchive.zip libarchive ) ELSE ( ECHO "Usage: %0% deplibs|configure|build|test|install|artifact" @EXIT /b 0 diff --git a/build/ci/github_actions/freebsd.sh b/build/ci/github_actions/freebsd.sh new file mode 100755 index 000000000000..fff74f6a6f0c --- /dev/null +++ b/build/ci/github_actions/freebsd.sh @@ -0,0 +1,41 @@ +#!/bin/sh +set -eu + +if [ $# != 1 ] +then + echo "Usage: $0 prepare | test" + exit 1 +fi + +if [ "$1" = "prepare" ] +then + set -x -e + env ASSUME_ALWAYS_YES=yes pkg bootstrap -f + sed -i.bak -e 's,pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly,pkg+http://pkg.FreeBSD.org/\${ABI}/latest,' /etc/pkg/FreeBSD.conf + pkg update + mount -u -o acls / + mkdir /tmp_acl_nfsv4 + MD=`mdconfig -a -t swap -s 128M` + newfs /dev/$MD + tunefs -N enable /dev/$MD + mount /dev/$MD /tmp_acl_nfsv4 + chmod 1777 /tmp_acl_nfsv4 + pkg install -y autoconf automake cmake gmake libiconv libtool pkgconf expat libxml2 liblz4 zstd +elif [ "$1" = "test" ] +then + set -e + echo "Additional NFSv4 ACL tests" + CURDIR=`pwd` + if [ "${BS}" = "cmake" ] + then + BIN_SUBDIR="bin" + else + BIN_SUBDIR=. + fi + BUILDDIR="${CURDIR}/build_ci/${BS}" + cd "$BUILDDIR" + TMPDIR=/tmp_acl_nfsv4 ${BIN_SUBDIR}/libarchive_test -r "${CURDIR}/libarchive/test" -v test_acl_platform_nfs4 +else + echo "Usage: $0 prepare | test" + exit 1 +fi diff --git a/build/ci/github_actions/vcpkg.json b/build/ci/github_actions/vcpkg.json new file mode 100644 index 000000000000..c636361a3533 --- /dev/null +++ b/build/ci/github_actions/vcpkg.json @@ -0,0 +1,15 @@ +{ + "dependencies": [ + "zlib", + "bzip2", + "liblzma", + "zstd" + ], + "vcpkg-configuration": { + "default-registry": { + "kind": "git", + "repository": "https://github.com/microsoft/vcpkg", + "baseline": "44819aa2a6c10e56065e2b0330e7d6c89d1d2574" + } + } +} diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index 97ff59476720..a082e6298652 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -684,6 +684,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the <iconv.h> header file. */ #cmakedefine HAVE_ICONV_H 1 +/* Define to 1 if you have the <intsafe.h> header file. */ +#cmakedefine HAVE_INTSAFE_H 1 + /* Define to 1 if you have the <inttypes.h> header file. */ #cmakedefine HAVE_INTTYPES_H 1 @@ -1025,6 +1028,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the <stdarg.h> header file. */ #cmakedefine HAVE_STDARG_H 1 +/* Define to 1 if you have the <stdckdint.h> header file. */ +#cmakedefine HAVE_STDCKDINT_H 1 + /* Define to 1 if you have the <stdint.h> header file. */ #cmakedefine HAVE_STDINT_H 1 diff --git a/build/cmake/discover_tests.cmake.in b/build/cmake/discover_tests.cmake.in new file mode 100644 index 000000000000..1a054bc63fe7 --- /dev/null +++ b/build/cmake/discover_tests.cmake.in @@ -0,0 +1,13 @@ +# Generated by CMake at configure time -- do not edit. +# Scans test source files for DEFINE_TEST() declarations and writes list.h. +set(_sources @SOURCES@) +set(_output "@OUTPUT@") +file(WRITE "${_output}" "") +foreach(_src ${_sources}) + if(_src MATCHES "test_[^/]+\\.c$") + file(STRINGS "${_src}" _lines REGEX "^DEFINE_TEST") + foreach(_line ${_lines}) + file(APPEND "${_output}" "${_line}\n") + endforeach() + endif() +endforeach() diff --git a/build/makerelease.sh b/build/makerelease.sh index 82843d677309..142056d84bd5 100755 --- a/build/makerelease.sh +++ b/build/makerelease.sh @@ -50,8 +50,8 @@ export MAKE_LIBARCHIVE_RELEASE="1" /bin/sh build/autogen.sh # Get the newest config.guess/config.sub from savannah.gnu.org -curl 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' > build/autoconf/config.guess -curl 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' > build/autoconf/config.sub +curl -fsSL 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' > build/autoconf/config.guess +curl -fsSL 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' > build/autoconf/config.sub ./configure make distcheck diff --git a/build/release/Dockerfile b/build/release/Dockerfile index 619b67f4b626..96d33e0c4156 100644 --- a/build/release/Dockerfile +++ b/build/release/Dockerfile @@ -3,8 +3,8 @@ ENV DEBIAN_FRONTEND=noninteractive RUN ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime RUN apt-get update && apt-get install -y build-essential autoconf automake libtool pkg-config cmake zlib1g-dev libssl-dev libacl1-dev libbz2-dev liblzma-dev liblz4-dev libzstd-dev lzop groff ghostscript bsdmainutils zip ADD . $HOME/libarchive/ -ADD "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD" $HOME/libarchive/build/autoconf/config.guess -ADD "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD" $HOME/libarchive/build/autoconf/config.sub +ADD "https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD" $HOME/libarchive/build/autoconf/config.guess +ADD "https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD" $HOME/libarchive/build/autoconf/config.sub WORKDIR $HOME/libarchive RUN /bin/sh build/clean.sh RUN /bin/sh build/autogen.sh diff --git a/build/version b/build/version index 99c36462af96..07e7c74e793a 100644 --- a/build/version +++ b/build/version @@ -1 +1 @@ -3008007 +3008008 diff --git a/cat/test/CMakeLists.txt b/cat/test/CMakeLists.txt index e76b47608728..1d5634146020 100644 --- a/cat/test/CMakeLists.txt +++ b/cat/test/CMakeLists.txt @@ -3,7 +3,7 @@ # ############################################ # -# How to build bsdtar_test +# How to build bsdcat_test # ############################################ IF(ENABLE_CAT AND ENABLE_TEST) @@ -51,25 +51,12 @@ IF(ENABLE_CAT AND ENABLE_TEST) # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. # GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h - ${CMAKE_CURRENT_LIST_FILE} ${bsdcat_test_SOURCES}) + ${CMAKE_CURRENT_LIST_FILE} bsdcat_test ${bsdcat_test_SOURCES}) SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}) - # list.h has a line DEFINE_TEST(testname) for every - # test. We can use that to define the tests for cmake by - # defining a DEFINE_TEST macro and reading list.h in. - MACRO (DEFINE_TEST _testname) - ADD_TEST( - NAME bsdcat_${_testname} - COMMAND bsdcat_test -vv - -p $<TARGET_FILE:bsdcat> - -r ${CMAKE_CURRENT_SOURCE_DIR} - -s - ${_testname}) - SET_TESTS_PROPERTIES(bsdcat_${_testname} PROPERTIES SKIP_RETURN_CODE 2) - ENDMACRO (DEFINE_TEST _testname) + DISCOVER_TESTS(bsdcat ${bsdcat_test_SOURCES}) - INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/cat/test) diff --git a/configure.ac b/configure.ac index 84fe33fd8a9d..1ef0ef8bbbf1 100644 --- a/configure.ac +++ b/configure.ac @@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front. dnl In particular, this allows the version macro to be used in AC_INIT dnl These first two version numbers are updated automatically on each release. -m4_define([LIBARCHIVE_VERSION_S],[3.8.7]) -m4_define([LIBARCHIVE_VERSION_N],[3008007]) +m4_define([LIBARCHIVE_VERSION_S],[3.8.8]) +m4_define([LIBARCHIVE_VERSION_N],[3008008]) dnl bsdtar and bsdcpio versioning tracks libarchive m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S()) @@ -365,9 +365,9 @@ AS_VAR_IF([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes], [AC_DEFINE_UNQUOTED([HAVE_WORKING_FS_IOC_GETFLAGS], [1], [Define to 1 if you have a working FS_IOC_GETFLAGS])]) -AC_CHECK_HEADERS([locale.h membership.h paths.h poll.h pthread.h pwd.h]) -AC_CHECK_HEADERS([readpassphrase.h signal.h spawn.h]) -AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.h]) +AC_CHECK_HEADERS([intsafe.h locale.h membership.h paths.h poll.h pthread.h]) +AC_CHECK_HEADERS([pwd.h readpassphrase.h signal.h spawn.h]) +AC_CHECK_HEADERS([stdarg.h stdckdint.h stdint.h stdlib.h string.h]) AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/ea.h sys/extattr.h]) AC_CHECK_HEADERS([sys/ioctl.h sys/mkdev.h sys/mount.h]) AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/richacl.h]) @@ -377,7 +377,7 @@ AC_CHECK_HEADERS([time.h unistd.h utime.h wchar.h wctype.h]) AC_CHECK_TYPE([suseconds_t]) AC_CHECK_HEADERS([windows.h]) # check windows.h first; the other headers require it. -AC_CHECK_HEADERS([wincrypt.h winioctl.h],[],[], +AC_CHECK_HEADERS([winioctl.h],[],[], [[#ifdef HAVE_WINDOWS_H # include <windows.h> #endif @@ -1291,24 +1291,26 @@ main(int argc, char **argv) case "$host_os" in *mingw* | *cygwin* | *msys*) ;; + *darwin*) + CRYPTO_CHECK(MD5, LIBSYSTEM, md5) + CRYPTO_CHECK(SHA1, LIBSYSTEM, sha1) + CRYPTO_CHECK(SHA256, LIBSYSTEM, sha256) + CRYPTO_CHECK(SHA384, LIBSYSTEM, sha384) + CRYPTO_CHECK(SHA512, LIBSYSTEM, sha512) + ;; *) CRYPTO_CHECK(MD5, LIBC, md5) - CRYPTO_CHECK(MD5, LIBSYSTEM, md5) CRYPTO_CHECK(RMD160, LIBC, rmd160) CRYPTO_CHECK(SHA1, LIBC, sha1) - CRYPTO_CHECK(SHA1, LIBSYSTEM, sha1) CRYPTO_CHECK(SHA256, LIBC, sha256) CRYPTO_CHECK(SHA256, LIBC2, sha256) CRYPTO_CHECK(SHA256, LIBC3, sha256) - CRYPTO_CHECK(SHA256, LIBSYSTEM, sha256) CRYPTO_CHECK(SHA384, LIBC, sha384) CRYPTO_CHECK(SHA384, LIBC2, sha384) CRYPTO_CHECK(SHA384, LIBC3, sha384) - CRYPTO_CHECK(SHA384, LIBSYSTEM, sha384) CRYPTO_CHECK(SHA512, LIBC, sha512) CRYPTO_CHECK(SHA512, LIBC2, sha512) CRYPTO_CHECK(SHA512, LIBC3, sha512) - CRYPTO_CHECK(SHA512, LIBSYSTEM, sha512) ;; esac diff --git a/contrib/android/Android.mk b/contrib/android/Android.mk index 1fdd2bf7cf35..9e1c72f6d021 100644 --- a/contrib/android/Android.mk +++ b/contrib/android/Android.mk @@ -159,6 +159,7 @@ libarchive_host_src_files := endif libarchive_fe_src_files := libarchive_fe/lafe_err.c \ + libarchive_fe/lafe_fnmatch.c \ libarchive_fe/lafe_getline.c \ libarchive_fe/line_reader.c \ libarchive_fe/passphrase.c diff --git a/contrib/android/config/windows_host.h b/contrib/android/config/windows_host.h index 2e24be1d3d75..2eb9a8df66bf 100644 --- a/contrib/android/config/windows_host.h +++ b/contrib/android/config/windows_host.h @@ -899,9 +899,6 @@ /* Define to 1 if you have the <wctype.h> header file. */ #define HAVE_WCTYPE_H 1 -/* Define to 1 if you have the <wincrypt.h> header file. */ -#define HAVE_WINCRYPT_H 1 - /* Define to 1 if you have the <windows.h> header file. */ #define HAVE_WINDOWS_H 1 diff --git a/contrib/oss-fuzz/libarchive_write_disk_fuzzer.cc b/contrib/oss-fuzz/libarchive_write_disk_fuzzer.cc index 056bd1639550..7392e394aa52 100644 --- a/contrib/oss-fuzz/libarchive_write_disk_fuzzer.cc +++ b/contrib/oss-fuzz/libarchive_write_disk_fuzzer.cc @@ -7,6 +7,7 @@ #include <stdint.h> #include <string.h> #include <stdlib.h> +#include <stdio.h> #include <unistd.h> #include <sys/stat.h> @@ -17,10 +18,134 @@ static constexpr size_t kMaxInputSize = 64 * 1024; static char g_temp_dir[256] = {0}; +static char g_start_dir[512] = {0}; +static char g_extract_dir[512] = {0}; +static char g_outside_dir[512] = {0}; +static char g_sentinel_path[512] = {0}; + +static int write_file(const char* path, const char* data) { + FILE* f = fopen(path, "wb"); + size_t len = strlen(data); + size_t written; + if (f == NULL) { + return -1; + } + written = fwrite(data, 1, len, f); + if (fclose(f) != 0) { + return -1; + } + return written == len ? 0 : -1; +} + +static int sentinel_is_unchanged() { + char buf[32]; + FILE* f = fopen(g_sentinel_path, "rb"); + if (f == NULL) { + return 0; + } + size_t n = fread(buf, 1, sizeof(buf) - 1, f); + fclose(f); + buf[n] = '\0'; + return strcmp(buf, "outside-original") == 0; +} + +static int reset_temp_tree() { + if (g_start_dir[0] != '\0') { + if (chdir(g_start_dir) != 0) { + return -1; + } + } + remove_directory_tree(g_temp_dir); + if (mkdir(g_temp_dir, 0700) != 0) { + return -1; + } + + snprintf(g_extract_dir, sizeof(g_extract_dir), "%s/extract", g_temp_dir); + snprintf(g_outside_dir, sizeof(g_outside_dir), "%s/outside", g_temp_dir); + snprintf(g_sentinel_path, sizeof(g_sentinel_path), "%s/outside/sentinel", + g_temp_dir); + + if (mkdir(g_extract_dir, 0700) != 0 || mkdir(g_outside_dir, 0700) != 0) { + return -1; + } + + char existing[512]; + char existing_dir[512]; + char nested_existing[512]; + snprintf(existing, sizeof(existing), "%s/extract/existing", g_temp_dir); + snprintf(existing_dir, sizeof(existing_dir), "%s/extract/dir", g_temp_dir); + snprintf(nested_existing, sizeof(nested_existing), + "%s/extract/dir/existing", g_temp_dir); + if (mkdir(existing_dir, 0700) != 0) { + return -1; + } + + return write_file(g_sentinel_path, "outside-original") || + write_file(existing, "inside") || + write_file(nested_existing, "inside"); +} + +static void consume_path(DataConsumer* consumer, char* out, size_t out_size) { + static const char* const kPaths[] = { + "file", + "dir/file", + "dir/./file", + "dir//file", + "link", + "link/file", + "link/./file", + "link//file", + "../outside/sentinel", + "../outside/new-file", + "./../outside/sentinel", + "dir/../file", + "hardlink", + "hardlink-with-data", + "symlink", + "existing", + "dir/existing", + }; + uint8_t selector = consumer->consume_byte(); + if ((selector & 0x80) != 0) { + snprintf(out, out_size, "%s/extract/absolute-%u", g_temp_dir, selector); + } else if ((selector & 0x40) != 0) { + snprintf(out, out_size, "%s/outside/sentinel", g_temp_dir); + } else { + snprintf(out, out_size, "%s", + kPaths[selector % (sizeof(kPaths) / sizeof(kPaths[0]))]); + } +} + +static void consume_linkname(DataConsumer* consumer, char* out, + size_t out_size) { + static const char* const kTargets[] = { + "existing", + "dir/existing", + "link/sentinel", + "link/./sentinel", + "link//sentinel", + "../outside/sentinel", + "./../outside/sentinel", + "dir/../existing", + "missing-target", + }; + uint8_t selector = consumer->consume_byte(); + if ((selector & 0x80) != 0) { + snprintf(out, out_size, "%s/outside/sentinel", g_temp_dir); + } else if ((selector & 0x40) != 0) { + snprintf(out, out_size, "%s/extract/existing", g_temp_dir); + } else { + snprintf(out, out_size, "%s", + kTargets[selector % (sizeof(kTargets) / sizeof(kTargets[0]))]); + } +} extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) { (void)argc; (void)argv; + if (getcwd(g_start_dir, sizeof(g_start_dir)) == NULL) { + g_start_dir[0] = '\0'; + } // Create a temporary directory for extraction snprintf(g_temp_dir, sizeof(g_temp_dir), "/tmp/fuzz_extract_XXXXXX"); if (mkdtemp(g_temp_dir) == NULL) { @@ -38,10 +163,19 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { return 0; } + if (reset_temp_tree() != 0 || chdir(g_extract_dir) != 0) { + return 0; + } + DataConsumer consumer(buf, len); struct archive *disk = archive_write_disk_new(); if (disk == NULL) { + if (g_start_dir[0] != '\0') { + if (chdir(g_start_dir) != 0) { + return 0; + } + } return 0; } @@ -54,8 +188,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { if (opt_flags & 0x08) flags |= ARCHIVE_EXTRACT_FFLAGS; if (opt_flags & 0x10) flags |= ARCHIVE_EXTRACT_OWNER; if (opt_flags & 0x20) flags |= ARCHIVE_EXTRACT_XATTR; - if (opt_flags & 0x40) flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS; - if (opt_flags & 0x80) flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT; + if (opt_flags & 0x40) flags |= ARCHIVE_EXTRACT_UNLINK; + if (opt_flags & 0x80) flags |= ARCHIVE_EXTRACT_SAFE_WRITES; + + flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS | + ARCHIVE_EXTRACT_SECURE_NODOTDOT | + ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS; archive_write_disk_set_options(disk, flags); archive_write_disk_set_standard_lookup(disk); @@ -66,45 +204,45 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { struct archive_entry *entry = archive_entry_new(); if (entry == NULL) break; - // Build a safe path within our temp directory - char safe_path[512]; - const char *name = consumer.consume_string(32); - snprintf(safe_path, sizeof(safe_path), "%s/%s", g_temp_dir, name); + char pathname[512]; + char linkname[512]; + consume_path(&consumer, pathname, sizeof(pathname)); + archive_entry_set_pathname(entry, pathname); - // Sanitize path to prevent traversal - char *p = safe_path; - while (*p) { - if (p[0] == '.' && p[1] == '.') { - p[0] = '_'; - p[1] = '_'; - } - p++; - } - - archive_entry_set_pathname(entry, safe_path); - - uint8_t ftype = consumer.consume_byte() % 3; + uint8_t ftype = consumer.consume_byte() % 4; mode_t mode; switch (ftype) { case 0: mode = S_IFREG | 0644; break; case 1: mode = S_IFDIR | 0755; break; + case 2: mode = S_IFLNK | 0777; break; default: mode = S_IFREG | 0644; break; } archive_entry_set_mode(entry, mode); + if (S_ISLNK(mode)) { + consume_linkname(&consumer, linkname, sizeof(linkname)); + archive_entry_set_symlink(entry, linkname); + archive_entry_set_size(entry, 0); + } else if (ftype == 3) { + consume_linkname(&consumer, linkname, sizeof(linkname)); + archive_entry_set_hardlink(entry, linkname); + } + archive_entry_set_uid(entry, 1000); archive_entry_set_gid(entry, 1000); archive_entry_set_mtime(entry, consumer.consume_i64(), 0); + uint8_t data_buf[256]; + size_t data_len = 0; + if (S_ISREG(mode)) { + data_len = consumer.consume_bytes(data_buf, 256); + archive_entry_set_size(entry, data_len); + } + // Write the entry header if (archive_write_header(disk, entry) == ARCHIVE_OK) { - if (S_ISREG(mode)) { - uint8_t data_buf[256]; - size_t data_len = consumer.consume_bytes(data_buf, 256); - archive_entry_set_size(entry, data_len); - if (data_len > 0) { - archive_write_data(disk, data_buf, data_len); - } + if (S_ISREG(mode) && data_len > 0) { + archive_write_data(disk, data_buf, data_len); } archive_write_finish_entry(disk); } @@ -116,6 +254,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { archive_write_close(disk); archive_write_free(disk); + if (!sentinel_is_unchanged()) { + abort(); + } + + if (g_start_dir[0] != '\0') { + if (chdir(g_start_dir) != 0) { + abort(); + } + } + // Clean up extracted files using nftw (safer than system()) remove_directory_tree(g_temp_dir); // Recreate the temp directory for next iteration diff --git a/cpio/cpio.c b/cpio/cpio.c index 6e6c2c3356c0..ebdace394cea 100644 --- a/cpio/cpio.c +++ b/cpio/cpio.c @@ -1002,7 +1002,10 @@ mode_in(struct cpio *cpio) lafe_errc(1, archive_errno(a), "%s", archive_error_string(a)); } - if (archive_match_path_excluded(cpio->matching, entry)) + r = archive_match_path_excluded(cpio->matching, entry); + if (r < 0) + lafe_errc(1, 0, "%s", archive_error_string(cpio->matching)); + if (r) continue; if (cpio->option_rename) cpio_rename(entry); @@ -1117,7 +1120,10 @@ mode_list(struct cpio *cpio) lafe_errc(1, archive_errno(a), "%s", archive_error_string(a)); } - if (archive_match_path_excluded(cpio->matching, entry)) + r = archive_match_path_excluded(cpio->matching, entry); + if (r < 0) + lafe_errc(1, 0, "%s", archive_error_string(cpio->matching)); + if (r) continue; if (cpio->verbose) list_item_verbose(cpio, entry); diff --git a/cpio/cpio_windows.c b/cpio/cpio_windows.c index 144814186a1f..ce50b9bdeb26 100644 --- a/cpio/cpio_windows.c +++ b/cpio/cpio_windows.c @@ -140,7 +140,7 @@ cpio_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode, CREATEFILE2_EXTENDED_PARAMETERS createExParams; #endif -#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) +#if WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) handle = CreateFileA(path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt index fe6ab968d3dd..bb1455ec9c92 100644 --- a/cpio/test/CMakeLists.txt +++ b/cpio/test/CMakeLists.txt @@ -84,25 +84,12 @@ IF(ENABLE_CPIO AND ENABLE_TEST) # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. # GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h - ${CMAKE_CURRENT_LIST_FILE} ${bsdcpio_test_SOURCES}) + ${CMAKE_CURRENT_LIST_FILE} bsdcpio_test ${bsdcpio_test_SOURCES}) SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}) - # list.h has a line DEFINE_TEST(testname) for every - # test. We can use that to define the tests for cmake by - # defining a DEFINE_TEST macro and reading list.h in. - MACRO (DEFINE_TEST _testname) - ADD_TEST( - NAME bsdcpio_${_testname} - COMMAND bsdcpio_test -vv - -p $<TARGET_FILE:bsdcpio> - -r ${CMAKE_CURRENT_SOURCE_DIR} - -s - ${_testname}) - SET_TESTS_PROPERTIES(bsdcpio_${_testname} PROPERTIES SKIP_RETURN_CODE 2) - ENDMACRO (DEFINE_TEST _testname) + DISCOVER_TESTS(bsdcpio ${bsdcpio_test_SOURCES}) - INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/cpio/test) diff --git a/cpio/test/test_extract_cpio_absolute_paths.c b/cpio/test/test_extract_cpio_absolute_paths.c index 51650bc00f5a..e3a72f9ccaf3 100644 --- a/cpio/test/test_extract_cpio_absolute_paths.c +++ b/cpio/test/test_extract_cpio_absolute_paths.c @@ -50,4 +50,5 @@ DEFINE_TEST(test_extract_cpio_absolute_paths) r = systemf("%s -i --insecure < archive.cpio 2> stderr3.txt", testprog); assert(r == 0); assertFileExists(temp_absolute_file_name); + free(temp_absolute_file_name); } diff --git a/cpio/test/test_format_newc.c b/cpio/test/test_format_newc.c index 9d4e4e9fb674..7363fc148f16 100644 --- a/cpio/test/test_format_newc.c +++ b/cpio/test/test_format_newc.c @@ -198,7 +198,7 @@ DEFINE_TEST(test_format_newc) t = from_hex(e + 46, 8); /* mtime */ failure("t=%#08jx now=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now, (intmax_t)now); - assert(t <= now); /* File wasn't created in future. */ + assert(t <= now + 1); /* Allow 1 sec margin for timing variations. */ failure("t=%#08jx now - 2=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now - 2, (intmax_t)now - 2); assert(t >= now - 2); /* File was created w/in last 2 secs. */ diff --git a/doc/RUNNING_TESTS_LINUX.md b/doc/RUNNING_TESTS_LINUX.md new file mode 100644 index 000000000000..62b6d18553e0 --- /dev/null +++ b/doc/RUNNING_TESTS_LINUX.md @@ -0,0 +1,70 @@ +--- +name: libarchive-running-tests-linux +description: Explains how to build and run the libarchive test suite on Linux. +--- + +WIP: This is still being developed. +Of course, we'll need other `RUNNING_TESTS_<platform>.md`, +as well as `BUILDING_<platform>.md` files with more details about various build options and setup. + +# Building and Running Tests on Linux + +The following is a summary of the information in [doc/BUILDING_LINUX.md](BUILDING_LINUX.md). + +### Configuring and Building the Tests + +We recommend using the CMake build system with the Ninja build tool. +A parallel build system based on GNU autoconf is also available. + +To configure with CMake: +```bash +cmake -G Ninja -B _build -S . +``` +(Omit `-G Ninja` to use the platform default build system +-- usually `make` -- instead of Ninja.) + +To build all of libarchive, including the test suites, +using whatever build system you selected during configuration: +```bash +cmake --build _build +``` + +### Testing a component + +There is a single test executable for each major libarchive component. + +To test the libarchive library: +```bash +./_build/bin/libarchive_test +``` + +To test other components: +```bash +./_build/bin/bsdcat_test +./_build/bin/bsdcpio_test +./_build/bin/bsdtar_test +./_build/bin/bsdunzip_test +``` + +Each test executables runs a series of tests on the corresponding component. +Each test runs in its own temporary directory; +if the test fails, the temporary directory is left behind so you can inspect the contents. + +Reference files are loaded from a specific hardcoded path. +This assumes the current working directory is the root of the libarchive source tree. +If you need to run a test executable from a different directory, +use the `-r` option to provide a path to the reference files. + +Use the `-h` (help) option for more details or `-v` (verbose) for more detailed output. + +### Running a single test + +You can run a single test by name +```bash +./_build/bin/libarchive_test test_read_format_zip +``` +or by number +```bash +./_build/bin/libarchive_test 307 +./_build/bin/libarchive_test 446-448 +``` diff --git a/doc/WRITING_TESTS.md b/doc/WRITING_TESTS.md new file mode 100644 index 000000000000..5b179f36d975 --- /dev/null +++ b/doc/WRITING_TESTS.md @@ -0,0 +1,242 @@ +--- +name: libarchive-writing-tests +description: Guide for writing and maintaining libarchive unit tests. +--- + +# Writing Libarchive Unit Tests + +Each libarchive component includes a suite of unit tests. +These are located in the `test` directory underneath the component directory +(`libarchive/test`, `tar/test`, etc). + +The most common reason that we fail to accept patches to libarchive +is because the patch lacks suitable new tests. +Almost all changes should be accompanied with a new or updated test case, +and if the change is non-trivial it will likely require several +tests to verify the full range of new behavior. +A new format or filter may require dozens of new tests. + +The rest of this file explains how to write a new test case and +add it to the existing test suite. +Understanding the structure of tests will also help when updating +or modifying existing tests. +The RUNNING_TESTS documentation corresponding to your platform +describes how to build and run the test suite. + +## Creating a New Test + +A "test" in libarchive is a C function defined with the `DEFINE_TEST(test_name)` macro. +While most test files contain only a single test, it is possible to include multiple tests in a single source file. +Many tests also involve an associated reference or sample input file, which is typically stored in the repository in UUencoded format. + +### 1. Basic Template +```c +#include "test.h" + +/* The test name typically matches the name of the `.c` source file. */ +DEFINE_TEST(test_foo) +{ + /* The file in the repository is named "test_foo.tar.uu". */ + /* The `refname` here omits the `.uu` suffix. */ + /* The base filename should match the test name. */ + const char *refname = "test_foo.tar"; + + struct archive *a; + struct archive_entry *ae; + int r; + + /* Each test runs in a private temporary directory. */ + + /* If you have a binary archive sample, extract it first. */ + extract_reference_file(refname); + + /* Create and configure a suitable archive handle. */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + + /* Open the extracted reference file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + + /* Perform whatever tests are appropriate. */ + + /* For example, when fixing a crash in libarchive, it + * may suffice for a test to simply read all the entries and + * their contents, as shown below. + * If errors are expected, you may need to unroll the following + * in order to perform specific checks for each entry. */ + while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) { + const void *pv; + size_t s; + int64_t o; + + while ((r == archive_read_data_block(a, &pv, &s, &o)) == ARCHIVE_OK) { + /* Verify the data contents if appropriate. */ + } + /* Verify that we exited the loop above on EOF, not on error. */ + assertEqualIntA(a, ARCHIVE_EOF, r); + } + + /* We exited the loop above, verify that it's EOF and not an error. */ + assertEqualIntA(a, ARCHIVE_EOF, r); + + /* Best practice: Close and free separately to get better + * error reporting if close fails. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} +``` + +### 2. Reference Files (Compatibility Tests) +For testing compatibility with existing archives: +1. Place the sample data in the `test` directory alongside the `.c` file. +2. Encode it using `uuencode`: `uuencode test_foo.tar test_foo.tar > test_foo.tar.uu`. +3. Use `extract_reference_file("test_foo.tar")` in your test to decode it into the temporary work directory. + +### 3. File and Function Naming + +The basic naming convention is `test_<functionality>_<format/API>_<detail>.c` where: +- **Functionality:** Indicates general functionality (e.g., `read`, `write`, `archive`, `entry`, `compat`). +- **Format/API:** The specific format or API being exercised (e.g., `format_tar`, `filter_gzip`, `next_header`, `acl`). +- **Detail:** Additional context to clarify the purpose (e.g., `empty`, `large`, `mac_metadata`). + +**Example names from the current suite:** +- `test_read_format_zip_mac_metadata.c` +- `test_write_disk_perms.c` +- `test_archive_read_next_header_empty.c` + +### 4. Registering the Test + +The build system searches uses of `DEFINE_TEST` to locate tests +in the relevant sources. +You only need to add the new files to the build system +to have them built +and run with the rest of the suite. +To add them to the build systems, +you need to update two files: + +1. `Makefile.am` in the root: + - Add `.c` files to `libarchive_test_SOURCES`. + - Add `.uu` reference files to `libarchive_test_EXTRA_DIST`. + - **Note:** Please maintain alphabetical order in these lists. +2. `CMakeLists.txt` in the relevant directory (e.g., `libarchive/test/CMakeLists.txt`): + - Add `.c` files to `libarchive_test_SOURCES`. + - **Note:** `.uu` files do NOT need to be listed in `CMakeLists.txt`. + +--- + +## Assertion Macros + +Always use the specialized assertion macros to ensure failures are actionable. +The full list of available macros is defined in `test_utils/test_common.h`. + +| Macro | Description | +|-------|-------------| +| `assert(expr)` | Standard boolean assertion. | +| `assertEqualInt(v1, v2)` | Asserts two integers are equal. Prints both values on failure. | +| `assertEqualString(s1, s2)` | Asserts two strings are equal. Prints both on failure. | +| `assertEqualMem(p1, p2, n)` | Asserts two memory blocks are equal. Provides a hexdump on failure. | +| `assertA(expr)` | Like `assert`, but also prints `archive_error_string(a)` on failure. | +| `assertEqualIntA(a, v1, v2)` | Like `assertEqualInt`, but includes archive error context. | +| `failure(fmt, ...)` | **Critical:** Use before an assertion to provide context. The message is only shown if the following assertion fails. | + +**Example usage:** +```c +/* Read first entry and verify metadata. */ +assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae)); +if (r != ARCHIVE_OK) { ... end the test ... } + +assertEqualString("test_file.txt", archive_entry_pathname(ae)); +assertEqualInt(1197179003, archive_entry_mtime(ae)); +assertEqualInt(1000, archive_entry_uid(ae)); +assertEqualString("tim", archive_entry_uname(ae)); +assertEqualInt(0100644, archive_entry_mode(ae)); +``` + +--- + +## Working with Files and Data + +Many libarchive tests perform all operations entirely in memory. +However, when testing archive extraction, you must verify the resulting files on disk. +Similarly, when testing archive creation, you may need to create files on disk to be archived. +The harness provides a variety of file utilities expressed as assertions. + +This includes assertions that create or modify files: +- `assertMakeFile(path, mode, contents)` +- `assertMakeDir(path, mode)` +- `assertChmod(pathname, mode)` + +And assertions that verify particular file properties, such as: +- `assertFileExists(path)` +- `assertFileSize(path, expected_size)` +- `assertTextFileContents(expected_text, path)` + +The full set of assertions is listed in `test_utils/test_common.h`. +You can search the existing tests to find examples of their usage. + +--- + +## Platform and Environment Utilities + +Some checks can only be done if the underlying system has certain +capabilities. + +Utilities to check capabilities of the current system include: +- `canSymlink()` +- `canGzip()` +- `canRunCommand("cmd", NULL)`. + +These can be used to circumvent specific individual checks: + +```c +if (canSymlink()) { + skipping("Symlinks not supported on this platform"); + /* ... verify that symlink entries were correctly restored */ +} +``` + +Or to abort an entire test: +```c +if (!canSymlink()) { + skipping("Symlinks not supported on this platform"); + return; +} +``` + +--- + +## General Best Practices + +Some pointers for making more effective tests: + +- **Use assertions liberally:** + Most lines of code in a test use `assert` macros to + verify the expected result. +- **Always Clean Up:** + Call `archive_read_free()` or `archive_write_free()` on every exit + path, including failures and premature exits. +- **Cross-Platform Portability:** + Do not assume POSIX features like `symlink` or `chown`. + Use the `can...()` helpers to verify system support before + performing platform-specific checks. +- **Verify the Fix:** + Run your new test against the code before and after any + other changes to ensure the test reproduces the issue and that + your fix addresses it. +- **Test, then Fix:** + Pull requests should have one or more commits with + new or updated unit tests, followed by commits that + change functionality. +- **Verify Error Details:** + When an API returns `ARCHIVE_WARN` or `ARCHIVE_FATAL`, + verify the specific error code from `archive_errno()`. + However, you should not always check the result of `archive_error_string()`, + as the specific text can evolve over time. + Generally, there should be one test each time a new error path is added + that verifies the error string. +- **Match the Existing Style:** + Changes to existing files should always match the indentation + and style of that file. + New files should follow the "BSD" formatting convention, + with 8-character hard tabs for indentation. diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index 4fb917132ca0..b29663742fd6 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -40,6 +40,7 @@ SET(libarchive_SOURCES archive_entry_xattr.c archive_hmac.c archive_hmac_private.h + archive_integer.h archive_match.c archive_openssl_evp_private.h archive_openssl_hmac_private.h diff --git a/libarchive/archive.h b/libarchive/archive.h index 41a5440cac75..159a3d561a18 100644 --- a/libarchive/archive.h +++ b/libarchive/archive.h @@ -34,7 +34,7 @@ * assert that ARCHIVE_VERSION_NUMBER >= 2012108. */ /* Note: Compiler will complain if this does not match archive_entry.h! */ -#define ARCHIVE_VERSION_NUMBER 3008007 +#define ARCHIVE_VERSION_NUMBER 3008008 #include <sys/stat.h> #include <stddef.h> /* for wchar_t */ @@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.8.7" +#define ARCHIVE_VERSION_ONLY_STRING "3.8.8" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); @@ -210,7 +210,9 @@ __LA_DECL const char * archive_openssl_version(void); __LA_DECL const char * archive_libmd_version(void); __LA_DECL const char * archive_commoncrypto_version(void); __LA_DECL const char * archive_cng_version(void); +#if ARCHIVE_VERSION_NUMBER < 4000000 __LA_DECL const char * archive_wincrypt_version(void); +#endif __LA_DECL const char * archive_librichacl_version(void); __LA_DECL const char * archive_libacl_version(void); __LA_DECL const char * archive_libattr_version(void); @@ -653,7 +655,6 @@ __LA_DECL int archive_read_data_block(struct archive *a, /*- * Some convenience functions that are built on archive_read_data: * 'skip': skips entire entry - * 'into_buffer': writes data into memory buffer that you provide * 'into_fd': writes data to specified filedes */ __LA_DECL int archive_read_data_skip(struct archive *); @@ -1234,7 +1235,7 @@ __LA_DECL int archive_match_exclude_entry(struct archive *, int _flag, struct archive_entry *); /* - * Test if a file is excluded by its uid ,gid, uname or gname. + * Test if a file is excluded by its uid, gid, uname or gname. * The conditions are set by following functions. */ __LA_DECL int archive_match_owner_excluded(struct archive *, diff --git a/libarchive/archive_acl.c b/libarchive/archive_acl.c index ab601833def6..f8d85b4bfabc 100644 --- a/libarchive/archive_acl.c +++ b/libarchive/archive_acl.c @@ -56,9 +56,7 @@ static int archive_acl_add_entry_len_l(struct archive_acl *acl, int type, int permset, int tag, int id, const char *name, size_t len, struct archive_string_conv *sc); static int archive_acl_text_want_type(struct archive_acl *acl, int flags); -static size_t archive_acl_text_len(struct archive_acl *acl, int want_type, - int flags, int wide, struct archive *a, - struct archive_string_conv *sc); +static size_t archive_acl_text_empty(struct archive_acl *acl, int want_type); static int isint_w(const wchar_t *start, const wchar_t *end, int *result); static int ismode_w(const wchar_t *start, const wchar_t *end, int *result); static int is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, @@ -67,9 +65,9 @@ static int is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, int *result); static void next_field_w(const wchar_t **wp, const wchar_t **start, const wchar_t **end, wchar_t *sep); -static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, +static void append_entry_w(struct archive_wstring *ws, const wchar_t *prefix, int type, int tag, int flags, const wchar_t *wname, int perm, int id); -static void append_id_w(wchar_t **wp, int id); +static void append_id_w(struct archive_wstring *ws, int id); static int isint(const char *start, const char *end, int *result); static int ismode(const char *start, const char *end, int *result); static int is_nfs4_flags(const char *start, const char *end, @@ -78,9 +76,9 @@ static int is_nfs4_perms(const char *start, const char *end, int *result); static void next_field(const char **p, size_t *l, const char **start, const char **end, char *sep); -static void append_entry(char **p, const char *prefix, int type, +static void append_entry(struct archive_string *s, const char *prefix, int type, int tag, int flags, const char *name, int perm, int id); -static void append_id(char **p, int id); +static void append_id(struct archive_string *s, int id); static const struct { const int perm; @@ -539,20 +537,12 @@ archive_acl_text_want_type(struct archive_acl *acl, int flags) } /* - * Calculate ACL text string length + * Check if ACL text would be empty */ static size_t -archive_acl_text_len(struct archive_acl *acl, int want_type, int flags, - int wide, struct archive *a, struct archive_string_conv *sc) { +archive_acl_text_empty(struct archive_acl *acl, int want_type) { struct archive_acl_entry *ap; - const char *name; - const wchar_t *wname; - int count, idlen, tmp, r; - size_t length; - size_t len; - count = 0; - length = 0; for (ap = acl->acl_head; ap != NULL; ap = ap->next) { if ((ap->type & want_type) == 0) continue; @@ -565,107 +555,11 @@ archive_acl_text_len(struct archive_acl *acl, int want_type, int flags, || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) continue; - count++; - if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0 - && (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) - length += 8; /* "default:" */ - switch (ap->tag) { - case ARCHIVE_ENTRY_ACL_USER_OBJ: - if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { - length += 6; /* "owner@" */ - break; - } - /* FALLTHROUGH */ - case ARCHIVE_ENTRY_ACL_USER: - case ARCHIVE_ENTRY_ACL_MASK: - length += 4; /* "user", "mask" */ - break; - case ARCHIVE_ENTRY_ACL_GROUP_OBJ: - if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { - length += 6; /* "group@" */ - break; - } - /* FALLTHROUGH */ - case ARCHIVE_ENTRY_ACL_GROUP: - case ARCHIVE_ENTRY_ACL_OTHER: - length += 5; /* "group", "other" */ - break; - case ARCHIVE_ENTRY_ACL_EVERYONE: - length += 9; /* "everyone@" */ - break; - } - length += 1; /* colon after tag */ - if (ap->tag == ARCHIVE_ENTRY_ACL_USER || - ap->tag == ARCHIVE_ENTRY_ACL_GROUP) { - if (wide) { - r = archive_mstring_get_wcs(a, &ap->name, - &wname); - if (r == 0 && wname != NULL) - length += wcslen(wname); - else if (r < 0 && errno == ENOMEM) - return (0); - else - length += sizeof(uid_t) * 3 + 1; - } else { - r = archive_mstring_get_mbs_l(a, &ap->name, &name, - &len, sc); - if (r != 0) - return (0); - if (len > 0 && name != NULL) - length += len; - else - length += sizeof(uid_t) * 3 + 1; - } - length += 1; /* colon after user or group name */ - } else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) - length += 1; /* 2nd colon empty user,group or other */ - - if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) - && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) - && (ap->tag == ARCHIVE_ENTRY_ACL_OTHER - || ap->tag == ARCHIVE_ENTRY_ACL_MASK)) { - /* Solaris has no colon after other: and mask: */ - length = length - 1; - } - - if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { - /* rwxpdDaARWcCos:fdinSFI:deny */ - length += 27; - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0) - length += 1; /* allow, alarm, audit */ - } else - length += 3; /* rwx */ - if ((ap->tag == ARCHIVE_ENTRY_ACL_USER || - ap->tag == ARCHIVE_ENTRY_ACL_GROUP) && - (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) { - length += 1; /* colon */ - /* ID digit count */ - idlen = 1; - tmp = ap->id; - while (tmp > 9) { - tmp = tmp / 10; - idlen++; - } - length += idlen; - } - length ++; /* entry separator */ - } - - /* Add filemode-mapping access entries to the length */ - if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) { - /* "user::rwx\ngroup::rwx\nother:rwx\n" */ - length += 31; - } else { - /* "user::rwx\ngroup::rwx\nother::rwx\n" */ - length += 32; - } - } else if (count == 0) return (0); + } - /* The terminating character is included in count */ - return (length); + return (1); } /* @@ -676,15 +570,12 @@ wchar_t * archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, struct archive *a) { - int count; - size_t length; - size_t len; const wchar_t *wname; const wchar_t *prefix; wchar_t separator; struct archive_acl_entry *ap; + struct archive_wstring ws; int id, r, want_type; - wchar_t *wp, *ws; want_type = archive_acl_text_want_type(acl, flags); @@ -695,9 +586,7 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; - length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL); - - if (length == 0) + if (archive_acl_text_empty(acl, want_type)) return (NULL); if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) @@ -705,28 +594,20 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, else separator = L'\n'; - /* Now, allocate the string and actually populate it. */ - wp = ws = malloc(length * sizeof(*wp)); - if (wp == NULL) { - if (errno == ENOMEM) - __archive_errx(1, "No memory"); - return (NULL); - } - count = 0; + archive_string_init(&ws); if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, acl->mode & 0700, -1); - *wp++ = separator; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + archive_wstrappend_wchar(&ws, separator); + append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, acl->mode & 0070, -1); - *wp++ = separator; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + archive_wstrappend_wchar(&ws, separator); + append_entry_w(&ws, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, acl->mode & 0007, -1); - count += 3; } for (ap = acl->acl_head; ap != NULL; ap = ap->next) { @@ -748,108 +629,95 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, prefix = NULL; r = archive_mstring_get_wcs(a, &ap->name, &wname); if (r == 0) { - if (count > 0) - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) + if (ws.length > 0) + archive_wstrappend_wchar(&ws, separator); + if ((flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) || + wname == NULL) id = ap->id; else id = -1; - append_entry_w(&wp, prefix, ap->type, ap->tag, flags, + append_entry_w(&ws, prefix, ap->type, ap->tag, flags, wname, ap->permset, id); - count++; } else if (r < 0 && errno == ENOMEM) { - free(ws); + archive_wstring_free(&ws); return (NULL); } } - /* Add terminating character */ - *wp++ = L'\0'; - - len = wcslen(ws); - - if (len > length - 1) - __archive_errx(1, "Buffer overrun"); - if (text_len != NULL) - *text_len = len; + *text_len = ws.length; - return (ws); + return (ws.s); } static void -append_id_w(wchar_t **wp, int id) +append_id_w(struct archive_wstring *ws, int id) { if (id < 0) id = 0; if (id > 9) - append_id_w(wp, id / 10); - *(*wp)++ = L"0123456789"[id % 10]; + append_id_w(ws, id / 10); + archive_wstrappend_wchar(ws, L"0123456789"[id % 10]); } static void -append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, +append_entry_w(struct archive_wstring *ws, const wchar_t *prefix, int type, int tag, int flags, const wchar_t *wname, int perm, int id) { int i; - if (prefix != NULL) { - wcscpy(*wp, prefix); - *wp += wcslen(*wp); - } + if (prefix != NULL) + archive_wstrcat(ws, prefix); switch (tag) { case ARCHIVE_ENTRY_ACL_USER_OBJ: wname = NULL; id = -1; if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { - wcscpy(*wp, L"owner@"); + archive_wstrcat(ws, L"owner@"); break; } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_USER: - wcscpy(*wp, L"user"); + archive_wstrcat(ws, L"user"); break; case ARCHIVE_ENTRY_ACL_GROUP_OBJ: wname = NULL; id = -1; if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { - wcscpy(*wp, L"group@"); + archive_wstrcat(ws, L"group@"); break; } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_GROUP: - wcscpy(*wp, L"group"); + archive_wstrcat(ws, L"group"); break; case ARCHIVE_ENTRY_ACL_MASK: - wcscpy(*wp, L"mask"); + archive_wstrcat(ws, L"mask"); wname = NULL; id = -1; break; case ARCHIVE_ENTRY_ACL_OTHER: - wcscpy(*wp, L"other"); + archive_wstrcat(ws, L"other"); wname = NULL; id = -1; break; case ARCHIVE_ENTRY_ACL_EVERYONE: - wcscpy(*wp, L"everyone@"); + archive_wstrcat(ws, L"everyone@"); wname = NULL; id = -1; break; default: - **wp = '\0'; break; } - *wp += wcslen(*wp); - *(*wp)++ = L':'; + archive_wstrappend_wchar(ws, L':'); if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) || tag == ARCHIVE_ENTRY_ACL_USER || tag == ARCHIVE_ENTRY_ACL_GROUP) { if (wname != NULL) { - wcscpy(*wp, wname); - *wp += wcslen(*wp); + archive_wstrcat(ws, wname); } else if (tag == ARCHIVE_ENTRY_ACL_USER || tag == ARCHIVE_ENTRY_ACL_GROUP) { - append_id_w(wp, id); + append_id_w(ws, id); if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) id = -1; } @@ -857,51 +725,49 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) || (tag != ARCHIVE_ENTRY_ACL_OTHER && tag != ARCHIVE_ENTRY_ACL_MASK)) - *(*wp)++ = L':'; + archive_wstrappend_wchar(ws, L':'); } if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { /* POSIX.1e ACL perms */ - *(*wp)++ = (perm & 0444) ? L'r' : L'-'; - *(*wp)++ = (perm & 0222) ? L'w' : L'-'; - *(*wp)++ = (perm & 0111) ? L'x' : L'-'; + archive_wstrappend_wchar(ws, (perm & 0444) ? L'r' : L'-'); + archive_wstrappend_wchar(ws, (perm & 0222) ? L'w' : L'-'); + archive_wstrappend_wchar(ws, (perm & 0111) ? L'x' : L'-'); } else { /* NFSv4 ACL perms */ for (i = 0; i < nfsv4_acl_perm_map_size; i++) { if (perm & nfsv4_acl_perm_map[i].perm) - *(*wp)++ = nfsv4_acl_perm_map[i].wc; + archive_wstrappend_wchar(ws, nfsv4_acl_perm_map[i].wc); else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) - *(*wp)++ = L'-'; + archive_wstrappend_wchar(ws, L'-'); } - *(*wp)++ = L':'; + archive_wstrappend_wchar(ws, L':'); for (i = 0; i < nfsv4_acl_flag_map_size; i++) { if (perm & nfsv4_acl_flag_map[i].perm) - *(*wp)++ = nfsv4_acl_flag_map[i].wc; + archive_wstrappend_wchar(ws, nfsv4_acl_flag_map[i].wc); else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) - *(*wp)++ = L'-'; + archive_wstrappend_wchar(ws, L'-'); } - *(*wp)++ = L':'; + archive_wstrappend_wchar(ws, L':'); switch (type) { case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: - wcscpy(*wp, L"allow"); + archive_wstrcat(ws, L"allow"); break; case ARCHIVE_ENTRY_ACL_TYPE_DENY: - wcscpy(*wp, L"deny"); + archive_wstrcat(ws, L"deny"); break; case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: - wcscpy(*wp, L"audit"); + archive_wstrcat(ws, L"audit"); break; case ARCHIVE_ENTRY_ACL_TYPE_ALARM: - wcscpy(*wp, L"alarm"); + archive_wstrcat(ws, L"alarm"); break; default: - *(*wp) = L'\0'; break; } - *wp += wcslen(*wp); } if (id != -1) { - *(*wp)++ = L':'; - append_id_w(wp, id); + archive_wstrappend_wchar(ws, L':'); + append_id_w(ws, id); } } @@ -913,15 +779,13 @@ char * archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, struct archive_string_conv *sc) { - int count; - size_t length; size_t len; const char *name; const char *prefix; char separator; struct archive_acl_entry *ap; + struct archive_string s; int id, r, want_type; - char *p, *s; want_type = archive_acl_text_want_type(acl, flags); @@ -932,9 +796,7 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; - length = archive_acl_text_len(acl, want_type, flags, 0, NULL, sc); - - if (length == 0) + if (archive_acl_text_empty(acl, want_type)) return (NULL); if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) @@ -942,28 +804,20 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, else separator = '\n'; - /* Now, allocate the string and actually populate it. */ - p = s = malloc(length * sizeof(*p)); - if (p == NULL) { - if (errno == ENOMEM) - __archive_errx(1, "No memory"); - return (NULL); - } - count = 0; + archive_string_init(&s); if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + append_entry(&s, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, acl->mode & 0700, -1); - *p++ = separator; - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + archive_strappend_char(&s, separator); + append_entry(&s, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, acl->mode & 0070, -1); - *p++ = separator; - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + archive_strappend_char(&s, separator); + append_entry(&s, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, acl->mode & 0007, -1); - count += 3; } for (ap = acl->acl_head; ap != NULL; ap = ap->next) { @@ -986,109 +840,95 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, r = archive_mstring_get_mbs_l( NULL, &ap->name, &name, &len, sc); if (r != 0) { - free(s); + archive_string_free(&s); return (NULL); } - if (count > 0) - *p++ = separator; + if (s.length > 0) + archive_strappend_char(&s, separator); if (name == NULL || (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) { id = ap->id; } else { id = -1; } - append_entry(&p, prefix, ap->type, ap->tag, flags, name, + append_entry(&s, prefix, ap->type, ap->tag, flags, name, ap->permset, id); - count++; } - /* Add terminating character */ - *p++ = '\0'; - - len = strlen(s); - - if (len > length - 1) - __archive_errx(1, "Buffer overrun"); - if (text_len != NULL) - *text_len = len; + *text_len = s.length; - return (s); + return (s.s); } static void -append_id(char **p, int id) +append_id(struct archive_string *s, int id) { if (id < 0) id = 0; if (id > 9) - append_id(p, id / 10); - *(*p)++ = "0123456789"[id % 10]; + append_id(s, id / 10); + archive_strappend_char(s, "0123456789"[id % 10]); } static void -append_entry(char **p, const char *prefix, int type, +append_entry(struct archive_string *s, const char *prefix, int type, int tag, int flags, const char *name, int perm, int id) { int i; - if (prefix != NULL) { - strcpy(*p, prefix); - *p += strlen(*p); - } + if (prefix != NULL) + archive_strcat(s, prefix); switch (tag) { case ARCHIVE_ENTRY_ACL_USER_OBJ: name = NULL; id = -1; if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { - strcpy(*p, "owner@"); + archive_strcat(s, "owner@"); break; } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_USER: - strcpy(*p, "user"); + archive_strcat(s, "user"); break; case ARCHIVE_ENTRY_ACL_GROUP_OBJ: name = NULL; id = -1; if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { - strcpy(*p, "group@"); + archive_strcat(s, "group@"); break; } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_GROUP: - strcpy(*p, "group"); + archive_strcat(s, "group"); break; case ARCHIVE_ENTRY_ACL_MASK: - strcpy(*p, "mask"); + archive_strcat(s, "mask"); name = NULL; id = -1; break; case ARCHIVE_ENTRY_ACL_OTHER: - strcpy(*p, "other"); + archive_strcat(s, "other"); name = NULL; id = -1; break; case ARCHIVE_ENTRY_ACL_EVERYONE: - strcpy(*p, "everyone@"); + archive_strcat(s, "everyone@"); name = NULL; id = -1; break; default: - **p = '\0'; break; } - *p += strlen(*p); - *(*p)++ = ':'; + archive_strappend_char(s, ':'); if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) || tag == ARCHIVE_ENTRY_ACL_USER || tag == ARCHIVE_ENTRY_ACL_GROUP) { if (name != NULL) { - strcpy(*p, name); - *p += strlen(*p); + archive_strcat(s, name); } else if (tag == ARCHIVE_ENTRY_ACL_USER || tag == ARCHIVE_ENTRY_ACL_GROUP) { - append_id(p, id); + append_id(s, id); if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) id = -1; } @@ -1096,51 +936,49 @@ append_entry(char **p, const char *prefix, int type, if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) || (tag != ARCHIVE_ENTRY_ACL_OTHER && tag != ARCHIVE_ENTRY_ACL_MASK)) - *(*p)++ = ':'; + archive_strappend_char(s, ':'); } if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { /* POSIX.1e ACL perms */ - *(*p)++ = (perm & 0444) ? 'r' : '-'; - *(*p)++ = (perm & 0222) ? 'w' : '-'; - *(*p)++ = (perm & 0111) ? 'x' : '-'; + archive_strappend_char(s, (perm & 0444) ? 'r' : '-'); + archive_strappend_char(s, (perm & 0222) ? 'w' : '-'); + archive_strappend_char(s, (perm & 0111) ? 'x' : '-'); } else { /* NFSv4 ACL perms */ for (i = 0; i < nfsv4_acl_perm_map_size; i++) { if (perm & nfsv4_acl_perm_map[i].perm) - *(*p)++ = nfsv4_acl_perm_map[i].c; + archive_strappend_char(s, nfsv4_acl_perm_map[i].c); else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) - *(*p)++ = '-'; + archive_strappend_char(s, '-'); } - *(*p)++ = ':'; + archive_strappend_char(s, ':'); for (i = 0; i < nfsv4_acl_flag_map_size; i++) { if (perm & nfsv4_acl_flag_map[i].perm) - *(*p)++ = nfsv4_acl_flag_map[i].c; + archive_strappend_char(s, nfsv4_acl_flag_map[i].c); else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) - *(*p)++ = '-'; + archive_strappend_char(s, '-'); } - *(*p)++ = ':'; + archive_strappend_char(s, ':'); switch (type) { case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: - strcpy(*p, "allow"); + archive_strcat(s, "allow"); break; case ARCHIVE_ENTRY_ACL_TYPE_DENY: - strcpy(*p, "deny"); + archive_strcat(s, "deny"); break; case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: - strcpy(*p, "audit"); + archive_strcat(s, "audit"); break; case ARCHIVE_ENTRY_ACL_TYPE_ALARM: - strcpy(*p, "alarm"); + archive_strcat(s, "alarm"); break; default: - *(*p) = '\0'; break; } - *p += strlen(*p); } if (id != -1) { - *(*p)++ = ':'; - append_id(p, id); + archive_strappend_char(s, ':'); + append_id(s, id); } } @@ -1248,11 +1086,18 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, type = want_type; /* Check for a numeric ID in field n+1 or n+3. */ - isint_w(field[n + 1].start, field[n + 1].end, &id); + if (isint_w(field[n + 1].start, field[n + 1].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } /* Field n+3 is optional. */ - if (id == -1 && fields > n+3) - isint_w(field[n + 3].start, field[n + 3].end, - &id); + if (id == -1 && fields > n+3 && + isint_w(field[n + 3].start, field[n + 3].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } tag = 0; s = field[n].start; @@ -1367,7 +1212,10 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, tag == ARCHIVE_ENTRY_ACL_GROUP) { n = 1; name = field[1]; - isint_w(name.start, name.end, &id); + if (isint_w(name.start, name.end, &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } } else n = 0; @@ -1402,7 +1250,11 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, ret = ARCHIVE_WARN; continue; } - isint_w(field[4 + n].start, field[4 + n].end, &id); + if (isint_w(field[4 + n].start, field[4 + n].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } } /* Add entry to the internal list. */ @@ -1436,8 +1288,8 @@ isint_w(const wchar_t *start, const wchar_t *end, int *result) if (*start < L'0' || *start > L'9') return (0); if (n > (INT_MAX / 10) || - (n == INT_MAX / 10 && (*start - L'0') > INT_MAX % 10)) { - n = INT_MAX; + (n == INT_MAX / 10 && (*start - L'0') >= INT_MAX % 10)) { + return (-1); } else { n *= 10; n += *start - L'0'; @@ -1747,15 +1599,21 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text, type = want_type; /* Check for a numeric ID in field n+1 or n+3. */ - isint(field[n + 1].start, field[n + 1].end, &id); + if (isint(field[n + 1].start, field[n + 1].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } /* Field n+3 is optional. */ - if (id == -1 && fields > (n + 3)) - isint(field[n + 3].start, field[n + 3].end, - &id); + if (id == -1 && fields > (n + 3) && + isint(field[n + 3].start, field[n + 3].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } tag = 0; s = field[n].start; - st = field[n].start + 1; len = field[n].end - field[n].start; if (len == 0) { @@ -1763,6 +1621,8 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text, continue; } + st = s + 1; + switch (*s) { case 'u': if (len == 1 || (len == 4 @@ -1868,7 +1728,10 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text, tag == ARCHIVE_ENTRY_ACL_GROUP) { n = 1; name = field[1]; - isint(name.start, name.end, &id); + if (isint(name.start, name.end, &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } } else n = 0; @@ -1903,8 +1766,11 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text, ret = ARCHIVE_WARN; continue; } - isint(field[4 + n].start, field[4 + n].end, - &id); + if (isint(field[4 + n].start, field[4 + n].end, + &id) < 0) { + ret = ARCHIVE_WARN; + continue; + } } /* Add entry to the internal list. */ @@ -1938,8 +1804,8 @@ isint(const char *start, const char *end, int *result) if (*start < '0' || *start > '9') return (0); if (n > (INT_MAX / 10) || - (n == INT_MAX / 10 && (*start - '0') > INT_MAX % 10)) { - n = INT_MAX; + (n == INT_MAX / 10 && (*start - '0') >= INT_MAX % 10)) { + return (-1); } else { n *= 10; n += *start - '0'; @@ -2121,7 +1987,10 @@ next_field(const char **p, size_t *l, const char **start, (*p)++; (*l)--; } - *sep = **p; + if (*l > 0) + *sep = **p; + else + *sep = '\0'; /* Handle in-field comments */ if (*sep == '#') { @@ -2129,7 +1998,10 @@ next_field(const char **p, size_t *l, const char **start, (*p)++; (*l)--; } - *sep = **p; + if (*l > 0) + *sep = **p; + else + *sep = '\0'; } /* Skip separator. */ diff --git a/libarchive/archive_cmdline.c b/libarchive/archive_cmdline.c index 23bb05d6424a..ffc4f5474947 100644 --- a/libarchive/archive_cmdline.c +++ b/libarchive/archive_cmdline.c @@ -36,7 +36,6 @@ #include "archive_cmdline_private.h" #include "archive_string.h" -static int cmdline_set_path(struct archive_cmdline *, const char *); static int cmdline_add_arg(struct archive_cmdline *, const char *); static ssize_t @@ -98,7 +97,7 @@ get_argument(struct archive_string *as, const char *p) /* * Set up command line arguments. - * Returns ARCHIVE_OK if everything okey. + * Returns ARCHIVE_OK if everything okay. * Returns ARCHIVE_FAILED if there is a lack of the `"' terminator or an * empty command line. * Returns ARCHIVE_FATAL if no memory. @@ -123,9 +122,12 @@ __archive_cmdline_parse(struct archive_cmdline *data, const char *cmd) r = ARCHIVE_FAILED;/* An empty command path. */ goto exit_function; } - r = cmdline_set_path(data, as.s); - if (r != ARCHIVE_OK) + free(data->path); + data->path = strdup(as.s); + if (data->path == NULL) { + r = ARCHIVE_FATAL; goto exit_function; + } p = strrchr(as.s, '/'); if (p == NULL) p = as.s; @@ -158,23 +160,7 @@ exit_function: } /* - * Set the program path. - */ -static int -cmdline_set_path(struct archive_cmdline *data, const char *path) -{ - char *newptr; - - newptr = realloc(data->path, strlen(path) + 1); - if (newptr == NULL) - return (ARCHIVE_FATAL); - data->path = newptr; - strcpy(data->path, path); - return (ARCHIVE_OK); -} - -/* - * Add a argument for the program. + * Add an argument for the program. */ static int cmdline_add_arg(struct archive_cmdline *data, const char *arg) diff --git a/libarchive/archive_crc32.h b/libarchive/archive_crc32.h index d86a507ce78c..cbd25291a975 100644 --- a/libarchive/archive_crc32.h +++ b/libarchive/archive_crc32.h @@ -43,28 +43,65 @@ static unsigned long crc32(unsigned long crc, const void *_p, size_t len) { - unsigned long crc2, b, i; const unsigned char *p = _p; - static volatile int crc_tbl_inited = 0; - static unsigned long crc_tbl[256]; + static const unsigned long crc_tbl[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d + }; if (_p == NULL) return (0); - if (!crc_tbl_inited) { - for (b = 0; b < 256; ++b) { - crc2 = b; - for (i = 8; i > 0; --i) { - if (crc2 & 1) - crc2 = (crc2 >> 1) ^ 0xedb88320UL; - else - crc2 = (crc2 >> 1); - } - crc_tbl[b] = crc2; - } - crc_tbl_inited = 1; - } - crc = crc ^ 0xffffffffUL; /* A use of this loop is about 20% - 30% faster than * no use version in any optimization option of gcc. */ diff --git a/libarchive/archive_cryptor.c b/libarchive/archive_cryptor.c index b6a02fd1e7cb..85b20ac9acc1 100644 --- a/libarchive/archive_cryptor.c +++ b/libarchive/archive_cryptor.c @@ -57,7 +57,7 @@ pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, return 0; } -#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) #ifdef _MSC_VER #pragma comment(lib, "Bcrypt.lib") #endif @@ -197,7 +197,7 @@ aes_ctr_release(archive_crypto_ctx *ctx) return 0; } -#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) static int aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) diff --git a/libarchive/archive_cryptor_private.h b/libarchive/archive_cryptor_private.h index 1f9298ffdc46..069eccd994bf 100644 --- a/libarchive/archive_cryptor_private.h +++ b/libarchive/archive_cryptor_private.h @@ -62,7 +62,7 @@ typedef struct { size_t encr_pos; } archive_crypto_ctx; -#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) #include <bcrypt.h> #define ARCHIVE_CRYPTOR_USE_CNG 1 @@ -148,16 +148,6 @@ typedef struct { #else -#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA512_WIN) -#if defined(_WIN32) && !defined(__CYGWIN__) && !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA) -#define ARCHIVE_CRYPTOR_USE_WINCRYPT 1 -#endif -#endif - #define AES_BLOCK_SIZE 16 #define AES_MAX_KEY_SIZE 32 typedef int archive_crypto_ctx; diff --git a/libarchive/archive_digest.c b/libarchive/archive_digest.c index 45fc36af1145..ab6db12bebe2 100644 --- a/libarchive/archive_digest.c +++ b/libarchive/archive_digest.c @@ -44,16 +44,11 @@ /* * Message digest functions for Windows platform. */ -#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\ - defined(ARCHIVE_CRYPTO_SHA512_WIN) +#if defined(HAVE_BCRYPT_H) /* * Initialize a Message digest. */ -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA static int win_crypto_init(Digest_CTX *ctx, const WCHAR *algo) { @@ -72,30 +67,6 @@ win_crypto_init(Digest_CTX *ctx, const WCHAR *algo) ctx->valid = 1; return (ARCHIVE_OK); } -#else -static int -win_crypto_init(Digest_CTX *ctx, DWORD prov, ALG_ID algId) -{ - - ctx->valid = 0; - if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL, - prov, CRYPT_VERIFYCONTEXT)) { - if (GetLastError() != (DWORD)NTE_BAD_KEYSET) - return (ARCHIVE_FAILED); - if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL, - prov, CRYPT_NEWKEYSET)) - return (ARCHIVE_FAILED); - } - - if (!CryptCreateHash(ctx->cryptProv, algId, 0, 0, &ctx->hash)) { - CryptReleaseContext(ctx->cryptProv, 0); - return (ARCHIVE_FAILED); - } - - ctx->valid = 1; - return (ARCHIVE_OK); -} -#endif /* * Update a Message digest. @@ -107,42 +78,26 @@ win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len) if (!ctx->valid) return (ARCHIVE_FAILED); -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)buf, (ULONG)len, 0); -#else - CryptHashData(ctx->hash, - (unsigned char *)(uintptr_t)buf, - (DWORD)len, 0); -#endif return (ARCHIVE_OK); } static int win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx) { -#if !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA) - DWORD siglen = (DWORD)bufsize; -#endif - if (!ctx->valid) return (ARCHIVE_FAILED); -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA BCryptFinishHash(ctx->hHash, buf, (ULONG)bufsize, 0); BCryptDestroyHash(ctx->hHash); BCryptCloseAlgorithmProvider(ctx->hAlg, 0); -#else - CryptGetHashParam(ctx->hash, HP_HASHVAL, buf, &siglen, 0); - CryptDestroyHash(ctx->hash); - CryptReleaseContext(ctx->cryptProv, 0); -#endif ctx->valid = 0; return (ARCHIVE_OK); } -#endif /* defined(ARCHIVE_CRYPTO_*_WIN) */ +#endif /* defined(HAVE_BCRYPT_H) */ /* MD5 implementations */ @@ -234,11 +189,7 @@ __archive_md5final(archive_md5_ctx *ctx, void *md) static int __archive_md5init(archive_md5_ctx *ctx) { -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM)); -#else - return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5)); -#endif } static int @@ -645,11 +596,7 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md) static int __archive_sha1init(archive_sha1_ctx *ctx) { -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM)); -#else - return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1)); -#endif } static int @@ -925,11 +872,7 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md) static int __archive_sha256init(archive_sha256_ctx *ctx) { -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM)); -#else - return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256)); -#endif } static int @@ -1177,11 +1120,7 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md) static int __archive_sha384init(archive_sha384_ctx *ctx) { -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM)); -#else - return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384)); -#endif } static int @@ -1453,11 +1392,7 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md) static int __archive_sha512init(archive_sha512_ctx *ctx) { -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM)); -#else - return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512)); -#endif } static int diff --git a/libarchive/archive_digest_private.h b/libarchive/archive_digest_private.h index deb134e4f8e8..7db999450e70 100644 --- a/libarchive/archive_digest_private.h +++ b/libarchive/archive_digest_private.h @@ -165,8 +165,7 @@ defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\ defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\ defined(ARCHIVE_CRYPTO_SHA512_WIN) -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA -/* don't use bcrypt when XP needs to be supported */ +#if defined(HAVE_BCRYPT_H) #include <bcrypt.h> #define ARCHIVE_CRYPTO_CNG 1 typedef struct { @@ -174,15 +173,6 @@ typedef struct { BCRYPT_ALG_HANDLE hAlg; BCRYPT_HASH_HANDLE hHash; } Digest_CTX; -#else -#include <windows.h> -#include <wincrypt.h> -#define ARCHIVE_CRYPTO_WINCRYPT 1 -typedef struct { - int valid; - HCRYPTPROV cryptProv; - HCRYPTHASH hash; -} Digest_CTX; #endif #endif diff --git a/libarchive/archive_endian.h b/libarchive/archive_endian.h index 83b2efa531ef..939acc6670ea 100644 --- a/libarchive/archive_endian.h +++ b/libarchive/archive_endian.h @@ -71,6 +71,22 @@ archive_be16dec(const void *pp) } static inline uint32_t +archive_be24dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p2 = p[2]; + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p0 << 16) | (p1 << 8) | p2); +} + + +static inline uint32_t archive_be32dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; @@ -109,6 +125,21 @@ archive_le16dec(const void *pp) } static inline uint32_t +archive_le24dec(const void *pp) +{ + unsigned char const *p = (unsigned char const *)pp; + + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p2 = p[2]; + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p2 << 16) | (p1 << 8) | p0); +} + +static inline uint32_t archive_le32dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; @@ -171,6 +202,16 @@ archive_le16enc(void *pp, uint16_t u) } static inline void +archive_le24enc(void *pp, uint32_t u) +{ + unsigned char *p = (unsigned char *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; + p[2] = (u >> 16) & 0xff; +} + +static inline void archive_le32enc(void *pp, uint32_t u) { unsigned char *p = (unsigned char *)pp; diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c index dc74430f80aa..90cf5cc829ea 100644 --- a/libarchive/archive_entry.c +++ b/libarchive/archive_entry.c @@ -1239,7 +1239,7 @@ _archive_entry_copy_link_l(struct archive_entry *entry, } void -archive_entry_set_mode(struct archive_entry *entry, mode_t m) +archive_entry_set_mode(struct archive_entry *entry, __LA_MODE_T m) { entry->stat_valid = 0; entry->acl.mode = m; @@ -1314,7 +1314,7 @@ _archive_entry_copy_pathname_l(struct archive_entry *entry, } void -archive_entry_set_perm(struct archive_entry *entry, mode_t p) +archive_entry_set_perm(struct archive_entry *entry, __LA_MODE_T p) { entry->stat_valid = 0; entry->acl.mode &= AE_IFMT; diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index 7122a74ed007..aa4f4dfb366f 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -28,7 +28,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3008007 +#define ARCHIVE_VERSION_NUMBER 3008008 /* * Note: archive_entry.h is for use outside of libarchive; the diff --git a/libarchive/archive_entry_link_resolver.c b/libarchive/archive_entry_link_resolver.c index 77fcad61fdea..233c46aa892e 100644 --- a/libarchive/archive_entry_link_resolver.c +++ b/libarchive/archive_entry_link_resolver.c @@ -78,7 +78,7 @@ struct links_entry { struct archive_entry_linkresolver { struct links_entry **buckets; struct links_entry *spare; - unsigned long number_entries; + size_t number_entries; size_t number_buckets; int strategy; }; @@ -158,13 +158,12 @@ archive_entry_linkresolver_set_strategy(struct archive_entry_linkresolver *res, void archive_entry_linkresolver_free(struct archive_entry_linkresolver *res) { - struct links_entry *le; - if (res == NULL) return; - while ((le = next_entry(res, NEXT_ENTRY_ALL)) != NULL) - archive_entry_free(le->entry); + while (next_entry(res, NEXT_ENTRY_ALL) != NULL) { + /* Actual freeing done by next_entry() */ + } free(res->buckets); free(res); } @@ -382,6 +381,10 @@ insert_entry(struct archive_entry_linkresolver *res, if (le == NULL) return (NULL); le->canonical = archive_entry_clone(entry); + if (le->canonical == NULL) { + free(le); + return (NULL); + } /* If the links cache is getting too full, enlarge the hash table. */ if (res->number_entries > res->number_buckets * 2) diff --git a/libarchive/archive_entry_sparse.c b/libarchive/archive_entry_sparse.c index c430896119fb..1e84ff7f8589 100644 --- a/libarchive/archive_entry_sparse.c +++ b/libarchive/archive_entry_sparse.c @@ -127,9 +127,10 @@ archive_entry_sparse_count(struct archive_entry *entry) int archive_entry_sparse_reset(struct archive_entry * entry) { + /* Counting can change sparse_head, so do it first */ + int count = archive_entry_sparse_count(entry); entry->sparse_p = entry->sparse_head; - - return archive_entry_sparse_count(entry); + return (count); } int diff --git a/libarchive/archive_entry_strmode.c b/libarchive/archive_entry_strmode.c index 5faa2faeefa0..22171992dd49 100644 --- a/libarchive/archive_entry_strmode.c +++ b/libarchive/archive_entry_strmode.c @@ -28,9 +28,6 @@ #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif #include "archive_entry.h" #include "archive_entry_private.h" @@ -38,16 +35,10 @@ const char * archive_entry_strmode(struct archive_entry *entry) { - static const mode_t permbits[] = - { 0400, 0200, 0100, 0040, 0020, 0010, 0004, 0002, 0001 }; char *bp = entry->strmode; - mode_t mode; + mode_t mask, mode; int i; - /* Fill in a default string, then selectively override. */ - strcpy(bp, "?rwxrwxrwx "); - - mode = archive_entry_mode(entry); switch (archive_entry_filetype(entry)) { case AE_IFREG: bp[0] = '-'; break; case AE_IFBLK: bp[0] = 'b'; break; @@ -57,30 +48,22 @@ archive_entry_strmode(struct archive_entry *entry) case AE_IFSOCK: bp[0] = 's'; break; case AE_IFIFO: bp[0] = 'p'; break; default: - if (archive_entry_hardlink(entry) != NULL) { - bp[0] = 'h'; - break; - } + bp[0] = (archive_entry_hardlink(entry) != NULL) ? 'h' : '?'; + break; } - for (i = 0; i < 9; i++) - if (!(mode & permbits[i])) - bp[i+1] = '-'; + mode = archive_entry_mode(entry); + for (i = 0, mask = 0400; i < 9; i++, mask >>= 1) + bp[i + 1] = (mode & mask) ? "rwx"[i % 3] : '-'; - if (mode & S_ISUID) { - if (mode & 0100) bp[3] = 's'; - else bp[3] = 'S'; - } - if (mode & S_ISGID) { - if (mode & 0010) bp[6] = 's'; - else bp[6] = 'S'; - } - if (mode & S_ISVTX) { - if (mode & 0001) bp[9] = 't'; - else bp[9] = 'T'; - } - if (archive_entry_acl_types(entry) != 0) - bp[10] = '+'; + if (mode & S_ISUID) + bp[3] = (mode & 0100) ? 's' : 'S'; + if (mode & S_ISGID) + bp[6] = (mode & 0010) ? 's' : 'S'; + if (mode & S_ISVTX) + bp[9] = (mode & 0001) ? 't' : 'T'; + bp[10] = (archive_entry_acl_types(entry) != 0) ? '+' : ' '; + bp[11] = '\0'; return (bp); } diff --git a/libarchive/archive_hmac.c b/libarchive/archive_hmac.c index 458092f41b29..e1e8f05ff0d3 100644 --- a/libarchive/archive_hmac.c +++ b/libarchive/archive_hmac.c @@ -74,7 +74,7 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) memset(ctx, 0, sizeof(*ctx)); } -#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) #ifndef BCRYPT_HASH_REUSABLE_FLAG # define BCRYPT_HASH_REUSABLE_FLAG 0x00000020 diff --git a/libarchive/archive_hmac_private.h b/libarchive/archive_hmac_private.h index 36b8e3320e38..af00beadb588 100644 --- a/libarchive/archive_hmac_private.h +++ b/libarchive/archive_hmac_private.h @@ -52,7 +52,7 @@ int __libarchive_hmac_build_hack(void); typedef CCHmacContext archive_hmac_sha1_ctx; -#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA +#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) #include <bcrypt.h> typedef struct { diff --git a/libarchive/archive_integer.h b/libarchive/archive_integer.h new file mode 100644 index 000000000000..6427c622cd29 --- /dev/null +++ b/libarchive/archive_integer.h @@ -0,0 +1,247 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ARCHIVE_INTEGER_H_INCLUDED +#define ARCHIVE_INTEGER_H_INCLUDED + +#include "archive_platform.h" + +/* Note: This is a purely internal header! */ +/* Do not use this outside of libarchive internal code! */ + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#ifdef HAVE_INTSAFE_H +#define ENABLE_INTSAFE_SIGNED_FUNCTIONS +#include <intsafe.h> +#endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#ifdef HAVE_STDCKDINT_H +#include <stdckdint.h> +#endif +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#ifdef HAVE_STDCKDINT_H +#define USE_STDCKDINT 1 +#elif (__GNUC__ >= 5 && !defined(__INTEL_COMPILER)) +#define USE_BUILTIN 1 +#elif __has_builtin(__builtin_add_overflow) +#define USE_BUILTIN 1 +#elif defined HAVE_INTSAFE_H +#define USE_INTSAFE 1 +#endif + +/* + * Disabling inline keyword for compilers known to choke on it: + * - Watcom C++ in C code. (For any version?) + * - SGI MIPSpro + * - Microsoft Visual C++ 6.0 (supposedly newer versions too) + * - IBM VisualAge 6 (XL v6) + * - Sun WorkShop C (SunPro) before 5.9 + */ +#if defined(__WATCOMC__) || defined(__sgi) || defined(__hpux) || defined(__BORLANDC__) +#define inline +#elif defined(__IBMC__) && __IBMC__ < 700 +#define inline +#elif defined(__SUNPRO_C) && __SUNPRO_C < 0x590 +#define inline +#elif defined(_MSC_VER) || defined(__osf__) +#define inline __inline +#endif + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_add_i64(int64_t *result, int64_t a, int64_t b) +{ +#if USE_STDCKDINT + return ckd_add(result, a, b); +#elif USE_BUILTIN + return __builtin_add_overflow(a, b, result); +#elif USE_INTSAFE + LONGLONG res; + int ret; + + ret = LongLongAdd(a, b, &res); + *result = (int64_t)res; + return ret; +#else + if ((b > 0 && a > INT64_MAX - b) || + (b < 0 && a < INT64_MIN - b)) + return 1; + + *result = a + b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_add_size(size_t *result, size_t a, size_t b) +{ +#if USE_STDCKDINT + return ckd_add(result, a, b); +#elif USE_BUILTIN + return __builtin_add_overflow(a, b, result); +#elif USE_INTSAFE + return SizeTAdd(a, b, result); +#else + if (a > SIZE_MAX - b) + return 1; + *result = a + b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_add_u64(uint64_t *result, uint64_t a, uint64_t b) +{ +#if USE_STDCKDINT + return ckd_add(result, a, b); +#elif USE_BUILTIN + return __builtin_add_overflow(a, b, result); +#elif USE_INTSAFE + ULONGLONG res; + int ret; + + ret = ULongLongAdd(a, b, &res); + *result = (uint64_t)res; + return ret; +#else + if (a > UINT64_MAX - b) + return 1; + *result = a + b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_mul_i64(int64_t *result, int64_t a, int64_t b) +{ +#if USE_STDCKDINT + return ckd_mul(result, a, b); +#elif USE_BUILTIN + return __builtin_mul_overflow(a, b, result); +#elif USE_INTSAFE + LONGLONG res; + int ret; + + ret = LongLongMult(a, b, &res); + *result = (int64_t)res; + return ret; +#else + if ((a > 0 && b > 0 && a > INT64_MAX / b) || + (a < 0 && b > 0 && a < INT64_MIN / b) || + (a > 0 && b < 0 && b < INT64_MIN / a) || + (a < 0 && b < 0 && a < INT64_MAX / b)) + return 1; + + *result = a * b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_mul_size(size_t *result, size_t a, size_t b) +{ +#if USE_STDCKDINT + return ckd_mul(result, a, b); +#elif USE_BUILTIN + return __builtin_mul_overflow(a, b, result); +#elif USE_INTSAFE + return SizeTMult(a, b, result); +#else + if (b != 0 && a > SIZE_MAX / b) + return 1; + *result = a * b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_mul_u64(uint64_t *result, uint64_t a, uint64_t b) +{ +#if USE_STDCKDINT + return ckd_mul(result, a, b); +#elif USE_BUILTIN + return __builtin_mul_overflow(a, b, result); +#elif USE_INTSAFE + ULONGLONG res; + int ret; + + ret = ULongLongMult(a, b, &res); + *result = (uint64_t)res; + return ret; +#else + if (b != 0 && a > UINT64_MAX / b) + return 1; + *result = a * b; + return 0; +#endif +} + +/* Returns 0 on success, a non-zero value otherwise. */ +static inline int +archive_ckd_sub_i64(int64_t *result, int64_t a, int64_t b) +{ +#if USE_STDCKDINT + return ckd_sub(result, a, b); +#elif USE_BUILTIN + return __builtin_sub_overflow(a, b, result); +#elif USE_INTSAFE + LONGLONG res; + int ret; + + ret = LongLongSub(a, b, &res); + *result = (int64_t)res; + return ret; +#else + if ((b > 0 && a < INT64_MIN + b) || + (b < 0 && a > INT64_MAX + b)) + return 1; + + *result = a - b; + return 0; +#endif +} + +#endif diff --git a/libarchive/archive_match.c b/libarchive/archive_match.c index 51a0e3fd5778..ecd470bd15dd 100644 --- a/libarchive/archive_match.c +++ b/libarchive/archive_match.c @@ -40,6 +40,7 @@ #endif #include "archive.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_entry.h" #include "archive_pathmatch.h" @@ -216,6 +217,14 @@ error_nomem(struct archive_match *a) return (ARCHIVE_FATAL); } +static int +error_pattern(struct archive_match *a) +{ + archive_set_error(&(a->archive), EINVAL, "Failed to apply pattern"); + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); +} + /* * Create an ARCHIVE_MATCH object. */ @@ -269,7 +278,7 @@ archive_match_free(struct archive *_a) * * Returns 1 if archive entry is excluded. * Returns 0 if archive entry is not excluded. - * Returns <0 if something error happened. + * Returns <0 if some error happened. */ int archive_match_excluded(struct archive *_a, struct archive_entry *entry) @@ -293,6 +302,8 @@ archive_match_excluded(struct archive *_a, struct archive_entry *entry) #else r = path_excluded(a, 1, archive_entry_pathname(entry)); #endif + if (r < 0) + return (error_pattern(a)); if (r != 0) return (r); } @@ -449,13 +460,14 @@ archive_match_include_pattern_from_file_w(struct archive *_a, * * Returns 1 if archive entry is excluded. * Returns 0 if archive entry is not excluded. - * Returns <0 if something error happened. + * Returns <0 if some error happened. */ int archive_match_path_excluded(struct archive *_a, struct archive_entry *entry) { struct archive_match *a; + int r; archive_check_magic(_a, ARCHIVE_MATCH_MAGIC, ARCHIVE_STATE_NEW, "archive_match_path_excluded"); @@ -471,10 +483,13 @@ archive_match_path_excluded(struct archive *_a, if ((a->setflag & PATTERN_IS_SET) == 0) return (0); #if defined(_WIN32) && !defined(__CYGWIN__) - return (path_excluded(a, 0, archive_entry_pathname_w(entry))); + r = path_excluded(a, 0, archive_entry_pathname_w(entry)); #else - return (path_excluded(a, 1, archive_entry_pathname(entry))); + r = path_excluded(a, 1, archive_entry_pathname(entry)); #endif + if (r < 0) + return (error_pattern(a)); + return (r); } /* @@ -629,11 +644,12 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist, } r = archive_read_next_header(ar, &ae); if (r != ARCHIVE_OK) { - archive_read_free(ar); if (r == ARCHIVE_EOF) { + archive_read_free(ar); return (ARCHIVE_OK); } else { archive_copy_error(&(a->archive), ar); + archive_read_free(ar); return (r); } } @@ -1007,7 +1023,7 @@ archive_match_exclude_entry(struct archive *_a, int flag, * * Returns 1 if archive entry is excluded. * Returns 0 if archive entry is not excluded. - * Returns <0 if something error happened. + * Returns <0 if some error happened. */ int archive_match_time_excluded(struct archive *_a, @@ -1653,7 +1669,7 @@ archive_match_include_gname_w(struct archive *_a, const wchar_t *gname) * * Returns 1 if archive entry is excluded. * Returns 0 if archive entry is not excluded. - * Returns <0 if something error happened. + * Returns <0 if some error happened. */ int archive_match_owner_excluded(struct archive *_a, @@ -1684,15 +1700,22 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id) if (ids->count + 1 >= ids->size) { void *p; + size_t alloc_size, new_size; if (ids->size == 0) - ids->size = 8; - else - ids->size *= 2; - p = realloc(ids->ids, sizeof(*ids->ids) * ids->size); + new_size = 8; + else { + if (archive_ckd_mul_size(&new_size, ids->size, 2)) + return (error_nomem(a)); + } + if (archive_ckd_mul_size(&alloc_size, + new_size, sizeof(*ids->ids))) + return (error_nomem(a)); + p = realloc(ids->ids, alloc_size); if (p == NULL) return (error_nomem(a)); ids->ids = (int64_t *)p; + ids->size = new_size; } /* Find an insert point. */ diff --git a/libarchive/archive_options.c b/libarchive/archive_options.c index 66491bd4183b..6190bb8ef7ee 100644 --- a/libarchive/archive_options.c +++ b/libarchive/archive_options.c @@ -31,9 +31,9 @@ #include "archive_options_private.h" -static const char * -parse_option(const char **str, - const char **mod, const char **opt, const char **val); +static char * +parse_option(char **str, + char **mod, char **opt, char **val); int _archive_set_option(struct archive *a, @@ -103,7 +103,7 @@ _archive_set_options(struct archive *a, const char *options, { int allok = 1, anyok = 0, ignore_mod_err = 0, r; char *data; - const char *s, *mod, *opt, *val; + char *s, *mod, *opt, *val; archive_check_magic(a, magic, ARCHIVE_STATE_NEW, fn); @@ -115,7 +115,7 @@ _archive_set_options(struct archive *a, const char *options, ENOMEM, "Out of memory adding file to list"); return (ARCHIVE_FATAL); } - s = (const char *)data; + s = data; do { mod = opt = val = NULL; @@ -167,10 +167,10 @@ _archive_set_options(struct archive *a, const char *options, return allok ? ARCHIVE_OK : anyok ? ARCHIVE_WARN : ARCHIVE_FAILED; } -static const char * -parse_option(const char **s, const char **m, const char **o, const char **v) +static char * +parse_option(char **s, char **m, char **o, char **v) { - const char *end, *mod, *opt, *val; + char *end, *mod, *opt, *val; char *p; end = NULL; @@ -182,7 +182,7 @@ parse_option(const char **s, const char **m, const char **o, const char **v) if (p != NULL) { *p = '\0'; - end = ((const char *)p) + 1; + end = p + 1; } if (0 == strlen(opt)) { diff --git a/libarchive/archive_pack_dev.c b/libarchive/archive_pack_dev.c index 3c6209b98405..e29351292895 100644 --- a/libarchive/archive_pack_dev.c +++ b/libarchive/archive_pack_dev.c @@ -319,7 +319,7 @@ compare_format(const void *key, const void *element) pack_t * pack_find(const char *name) { - struct format *format; + const struct format *format; format = bsearch(name, formats, sizeof(formats)/sizeof(formats[0]), diff --git a/libarchive/archive_parse_date.c b/libarchive/archive_parse_date.c index d9e968387d34..c1b0f1831165 100644 --- a/libarchive/archive_parse_date.c +++ b/libarchive/archive_parse_date.c @@ -36,6 +36,7 @@ #include <time.h> #include "archive.h" +#include "archive_integer.h" /* Basic time units. */ #define EPOCH 1970 @@ -49,7 +50,7 @@ enum DSTMODE { DSTon, DSToff, DSTmaybe }; enum { tAM, tPM }; /* Token types returned by nexttoken() */ enum { tAGO = 260, tDAY, tDAYZONE, tAMPM, tMONTH, tMONTH_UNIT, tSEC_UNIT, - tUNUMBER, tZONE, tDST }; + tUNUMBER, tZONE, tDST, tERROR }; struct token { int token; time_t value; }; /* @@ -818,20 +819,33 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth) } /* - * Parses and consumes an unsigned number. - * Returns 1 if any number is parsed. Otherwise, *value is unchanged. + * Parses and consumes an unsigned 64-bit number. + * Returns UINT64_MAX if the number overflows. */ -static char -consume_unsigned_number(const char **in, time_t *value) -{ - char c; - if (isdigit((unsigned char)(c = **in))) { - for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); ) - *value = 10 * *value + c - '0'; - (*in)--; - return 1; +static uint64_t +consume_unsigned_number(const char **in) { + uint64_t value = 0; + unsigned char c; + + /* Get the first character, abort if it's not a digit */ + c = (unsigned char)(**in); + if (c < '0' || c > '9') { + return UINT64_MAX; } - return 0; + + /* Fold digits into the value, abort on overflow */ + while (c >= '0' && c <= '9') { + unsigned char digit = c - '0'; + + /* Return error if the result would overflow UINT64_MAX */ + if (archive_ckd_mul_u64(&value, value, 10) || + archive_ckd_add_u64(&value, value, digit)) { + return UINT64_MAX; + } + (*in)++; + c = (unsigned char)(**in); + } + return value; } /* @@ -906,12 +920,19 @@ nexttoken(const char **in, time_t *value) } /* - * Not in the word table, maybe it's a number. Note: - * Because '-' and '+' have other special meanings, I - * don't deal with signed numbers here. + * Not in the word table. If it starts with a digit, + * it must be a number. Note: Because '-' and '+' have + * other special meanings, I don't deal with signed + * numbers here. */ - if (consume_unsigned_number(in, value)) { - return (tUNUMBER); + if (isdigit((unsigned char)(**in))) { + uint64_t val = consume_unsigned_number(in); + if (val > 9999) { + return (tERROR); + } else { + *value = val; + return (tUNUMBER); + } } return *(*in)++; @@ -949,6 +970,7 @@ difftm (struct tm *a, struct tm *b) static time_t parse_unix_epoch(const char *p) { + uint64_t val; time_t epoch; /* may begin with + */ @@ -957,12 +979,18 @@ parse_unix_epoch(const char *p) } /* followed by some number */ - if (!consume_unsigned_number(&p, &epoch)) + val = consume_unsigned_number(&p); + /* Truncate to time_t */ + epoch = (time_t)val; + /* If truncated value is different, then + * the value is too large for `time_t`. */ + if (epoch < 0 || (uint64_t)epoch != val) { return (time_t)-1; - - /* ...and nothing else */ - if (*p != '\0') + } + /* If there's any more characters, fail. */ + if (*p != '\0') { return (time_t)-1; + } return epoch; } diff --git a/libarchive/archive_pathmatch.c b/libarchive/archive_pathmatch.c index db0d2b791adf..4b69ae1e4afb 100644 --- a/libarchive/archive_pathmatch.c +++ b/libarchive/archive_pathmatch.c @@ -35,6 +35,8 @@ #include "archive_pathmatch.h" +#define MAX_RECURSION 100 + /* * Check whether a character 'c' is matched by a list specification [...]: * * Leading '!' or '^' negates the class. @@ -167,9 +169,13 @@ pm_slashskip_w(const wchar_t *s) { } static int -pm(const char *p, const char *s, int flags) +pm(const char *p, const char *s, int flags, int depth) { const char *end; + int r; + + if (depth > MAX_RECURSION) + return (-1); /* * Ignore leading './', './/', '././', etc. @@ -202,8 +208,9 @@ pm(const char *p, const char *s, int flags) if (*p == '\0') return (1); while (*s) { - if (pm(p, s, flags)) - return (1); + r = pm(p, s, flags, depth + 1); + if (r) + return (r); ++s; } return (0); @@ -220,7 +227,7 @@ pm(const char *p, const char *s, int flags) } if (*end == ']') { /* We found [...], try to match it. */ - if (!pm_list(p + 1, end, *s, flags)) + if (*s == '\0' || !pm_list(p + 1, end, *s, flags)) return (0); p = end; /* Jump to trailing ']' char. */ break; @@ -272,9 +279,13 @@ pm(const char *p, const char *s, int flags) } static int -pm_w(const wchar_t *p, const wchar_t *s, int flags) +pm_w(const wchar_t *p, const wchar_t *s, int flags, int depth) { const wchar_t *end; + int r; + + if (depth > MAX_RECURSION) + return (-1); /* * Ignore leading './', './/', '././', etc. @@ -307,8 +318,9 @@ pm_w(const wchar_t *p, const wchar_t *s, int flags) if (*p == L'\0') return (1); while (*s) { - if (pm_w(p, s, flags)) - return (1); + r = pm_w(p, s, flags, depth + 1); + if (r) + return (r); ++s; } return (0); @@ -387,7 +399,7 @@ __archive_pathmatch(const char *p, const char *s, int flags) return (0); /* Leading '^' anchors the start of the pattern. */ - if (*p == '^') { + if ((flags & PATHMATCH_NO_ANCHOR_START) && *p == '^') { ++p; flags &= ~PATHMATCH_NO_ANCHOR_START; } @@ -401,22 +413,25 @@ __archive_pathmatch(const char *p, const char *s, int flags) ++p; while (*s == '/') ++s; - return (pm(p, s, flags)); + return (pm(p, s, flags, 0)); } /* If start is unanchored, try to match start of each path element. */ if (flags & PATHMATCH_NO_ANCHOR_START) { for ( ; s != NULL; s = strchr(s, '/')) { + int r; + if (*s == '/') s++; - if (pm(p, s, flags)) - return (1); + r = pm(p, s, flags, 0); + if (r) + return (r); } return (0); } /* Default: Match from beginning. */ - return (pm(p, s, flags)); + return (pm(p, s, flags, 0)); } int @@ -429,7 +444,7 @@ __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags) return (0); /* Leading '^' anchors the start of the pattern. */ - if (*p == L'^') { + if ((flags & PATHMATCH_NO_ANCHOR_START) && *p == L'^') { ++p; flags &= ~PATHMATCH_NO_ANCHOR_START; } @@ -443,20 +458,23 @@ __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags) ++p; while (*s == L'/') ++s; - return (pm_w(p, s, flags)); + return (pm_w(p, s, flags, 0)); } /* If start is unanchored, try to match start of each path element. */ if (flags & PATHMATCH_NO_ANCHOR_START) { for ( ; s != NULL; s = wcschr(s, L'/')) { + int r; + if (*s == L'/') s++; - if (pm_w(p, s, flags)) - return (1); + r = pm_w(p, s, flags, 0); + if (r) + return (r); } return (0); } /* Default: Match from beginning. */ - return (pm_w(p, s, flags)); + return (pm_w(p, s, flags, 0)); } diff --git a/libarchive/archive_random.c b/libarchive/archive_random.c index 8c48d2d3b5a9..28cba00bd3cd 100644 --- a/libarchive/archive_random.c +++ b/libarchive/archive_random.c @@ -58,18 +58,12 @@ static void la_arc4random_buf(void *, size_t); #include "archive_random_private.h" #if defined(_WIN32) && !defined(__CYGWIN__) -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA -/* don't use bcrypt when XP needs to be supported */ #include <bcrypt.h> /* Common in other bcrypt implementations, but missing from VS2008. */ #ifndef BCRYPT_SUCCESS #define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS) #endif - -#elif defined(HAVE_WINCRYPT_H) -#include <wincrypt.h> -#endif #endif #ifndef O_CLOEXEC @@ -85,7 +79,6 @@ int archive_random(void *buf, size_t nbytes) { #if defined(_WIN32) && !defined(__CYGWIN__) -# if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA NTSTATUS status; BCRYPT_ALG_HANDLE hAlg; @@ -98,25 +91,6 @@ archive_random(void *buf, size_t nbytes) return ARCHIVE_FAILED; return ARCHIVE_OK; -# else - HCRYPTPROV hProv; - BOOL success; - - success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT); - if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) { - success = CryptAcquireContext(&hProv, NULL, NULL, - PROV_RSA_FULL, CRYPT_NEWKEYSET); - } - if (success) { - success = CryptGenRandom(hProv, (DWORD)nbytes, (BYTE*)buf); - CryptReleaseContext(hProv, 0); - if (success) - return ARCHIVE_OK; - } - /* TODO: Does this case really happen? */ - return ARCHIVE_FAILED; -# endif #elif !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__)) la_arc4random_buf(buf, nbytes); return ARCHIVE_OK; diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c index e5f89bdc8772..b23d99dd7b27 100644 --- a/libarchive/archive_read.c +++ b/libarchive/archive_read.c @@ -36,6 +36,9 @@ #ifdef HAVE_ERRNO_H #include <errno.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #include <stdio.h> #ifdef HAVE_STDLIB_H #include <stdlib.h> @@ -49,6 +52,7 @@ #include "archive.h" #include "archive_entry.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" @@ -253,41 +257,38 @@ client_close_proxy(struct archive_read_filter *self) } static int -client_open_proxy(struct archive_read_filter *self) -{ - int r = ARCHIVE_OK; - if (self->archive->client.opener != NULL) - r = (self->archive->client.opener)( - (struct archive *)self->archive, self->data); - return (r); -} - -static int client_switch_proxy(struct archive_read_filter *self, unsigned int iindex) { - int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK; - void *data2 = NULL; + struct archive_read *a; + int r1 = ARCHIVE_OK, r2 = ARCHIVE_OK; + void *data2; + + while (self->upstream != NULL) + self = self->upstream; + a = self->archive; /* Don't do anything if already in the specified data node */ - if (self->archive->client.cursor == iindex) + if (a->client.cursor == iindex) return (ARCHIVE_OK); - self->archive->client.cursor = iindex; - data2 = self->archive->client.dataset[self->archive->client.cursor].data; - if (self->archive->client.switcher != NULL) + a->client.cursor = iindex; + data2 = a->client.dataset[a->client.cursor].data; + if (a->client.switcher != NULL) { - r1 = r2 = (self->archive->client.switcher) - ((struct archive *)self->archive, self->data, data2); + r1 = r2 = (a->client.switcher) + ((struct archive *)a, self->data, data2); self->data = data2; } else { /* Attempt to call close and open instead */ - if (self->archive->client.closer != NULL) - r1 = (self->archive->client.closer) - ((struct archive *)self->archive, self->data); + if (a->client.closer != NULL) + r1 = (a->client.closer) + ((struct archive *)a, self->data); self->data = data2; - r2 = client_open_proxy(self); + if (a->client.opener != NULL) + r2 = (a->client.opener) + ((struct archive *)a, self->data); } return (r1 < r2) ? r1 : r2; } @@ -403,7 +404,9 @@ archive_read_add_callback_data(struct archive *_a, void *client_data, { struct archive_read *a = (struct archive_read *)_a; void *p; + size_t alloc_size; unsigned int i; + unsigned int nodes; archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_add_callback_data"); @@ -412,14 +415,26 @@ archive_read_add_callback_data(struct archive *_a, void *client_data, "Invalid index specified"); return ARCHIVE_FATAL; } - p = realloc(a->client.dataset, sizeof(*a->client.dataset) - * (++(a->client.nodes))); + + if (a->client.nodes == UINT_MAX || + archive_ckd_mul_size(&alloc_size, + (size_t)a->client.nodes + 1, sizeof(*a->client.dataset))) { + archive_set_error(&a->archive, ENOMEM, + "No memory"); + return ARCHIVE_FATAL; + } + + nodes = a->client.nodes + 1; + p = realloc(a->client.dataset, alloc_size); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "No memory"); return ARCHIVE_FATAL; } + a->client.dataset = (struct archive_read_data_node *)p; + a->client.nodes = nodes; + for (i = a->client.nodes - 1; i > iindex; i--) { a->client.dataset[i].data = a->client.dataset[i-1].data; a->client.dataset[i].begin_position = -1; @@ -934,7 +949,10 @@ archive_read_data_skip(struct archive *_a) if (r == ARCHIVE_EOF) r = ARCHIVE_OK; - a->archive.state = ARCHIVE_STATE_HEADER; + if (r == ARCHIVE_FATAL) + a->archive.state = ARCHIVE_STATE_FATAL; + else + a->archive.state = ARCHIVE_STATE_HEADER; return (r); } @@ -942,6 +960,8 @@ la_int64_t archive_seek_data(struct archive *_a, int64_t offset, int whence) { struct archive_read *a = (struct archive_read *)_a; + la_int64_t r; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_seek_data_block"); @@ -949,10 +969,14 @@ archive_seek_data(struct archive *_a, int64_t offset, int whence) archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, "Internal error: " "No format_seek_data_block function registered"); + a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } - return (a->format->seek_data)(a, offset, whence); + r = (a->format->seek_data)(a, offset, whence); + if (r == ARCHIVE_FATAL) + a->archive.state = ARCHIVE_STATE_FATAL; + return (r); } /* @@ -968,6 +992,8 @@ _archive_read_data_block(struct archive *_a, const void **buff, size_t *size, int64_t *offset) { struct archive_read *a = (struct archive_read *)_a; + int r; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_read_data_block"); @@ -975,10 +1001,14 @@ _archive_read_data_block(struct archive *_a, archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, "Internal error: " "No format->read_data function registered"); + a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } - return (a->format->read_data)(a, buff, size, offset); + r = (a->format->read_data)(a, buff, size, offset); + if (r == ARCHIVE_FATAL) + a->archive.state = ARCHIVE_STATE_FATAL; + return (r); } static int @@ -1366,7 +1396,7 @@ __archive_read_filter_ahead(struct archive_read_filter *filter, /* Move data forward in copy buffer if necessary. */ if (filter->next > filter->buffer && - filter->next + min > filter->buffer + filter->buffer_size) { + min > filter->buffer_size - (filter->next - filter->buffer)) { if (filter->avail > 0) memmove(filter->buffer, filter->next, filter->avail); diff --git a/libarchive/archive_read_append_filter.c b/libarchive/archive_read_append_filter.c index d578b06fe714..04c362741360 100644 --- a/libarchive/archive_read_append_filter.c +++ b/libarchive/archive_read_append_filter.c @@ -37,7 +37,7 @@ int archive_read_append_filter(struct archive *_a, int code) { int r1, r2, number_bidders, i; - char str[20]; + const char *str; struct archive_read_filter_bidder *bidder; struct archive_read_filter *filter; struct archive_read *a = (struct archive_read *)_a; @@ -53,15 +53,15 @@ archive_read_append_filter(struct archive *_a, int code) r1 = (ARCHIVE_OK); break; case ARCHIVE_FILTER_GZIP: - strcpy(str, "gzip"); + str = "gzip"; r1 = archive_read_support_filter_gzip(_a); break; case ARCHIVE_FILTER_BZIP2: - strcpy(str, "bzip2"); + str = "bzip2"; r1 = archive_read_support_filter_bzip2(_a); break; case ARCHIVE_FILTER_COMPRESS: - strcpy(str, "compress (.Z)"); + str = "compress (.Z)"; r1 = archive_read_support_filter_compress(_a); break; case ARCHIVE_FILTER_PROGRAM: @@ -69,43 +69,43 @@ archive_read_append_filter(struct archive *_a, int code) "Cannot append program filter using archive_read_append_filter"); return (ARCHIVE_FATAL); case ARCHIVE_FILTER_LZMA: - strcpy(str, "lzma"); + str = "lzma"; r1 = archive_read_support_filter_lzma(_a); break; case ARCHIVE_FILTER_XZ: - strcpy(str, "xz"); + str = "xz"; r1 = archive_read_support_filter_xz(_a); break; case ARCHIVE_FILTER_UU: - strcpy(str, "uu"); + str = "uu"; r1 = archive_read_support_filter_uu(_a); break; case ARCHIVE_FILTER_RPM: - strcpy(str, "rpm"); + str = "rpm"; r1 = archive_read_support_filter_rpm(_a); break; case ARCHIVE_FILTER_LZ4: - strcpy(str, "lz4"); + str = "lz4"; r1 = archive_read_support_filter_lz4(_a); break; case ARCHIVE_FILTER_ZSTD: - strcpy(str, "zstd"); + str = "zstd"; r1 = archive_read_support_filter_zstd(_a); break; case ARCHIVE_FILTER_LZIP: - strcpy(str, "lzip"); + str = "lzip"; r1 = archive_read_support_filter_lzip(_a); break; case ARCHIVE_FILTER_LZOP: - strcpy(str, "lzop"); + str = "lzop"; r1 = archive_read_support_filter_lzop(_a); break; case ARCHIVE_FILTER_LRZIP: - strcpy(str, "lrzip"); + str = "lrzip"; r1 = archive_read_support_filter_lrzip(_a); break; case ARCHIVE_FILTER_GRZIP: - strcpy(str, "grzip"); + str = "grzip"; r1 = archive_read_support_filter_grzip(_a); break; default: diff --git a/libarchive/archive_read_data_into_fd.c b/libarchive/archive_read_data_into_fd.c index 8fd5e12442bc..38de5b4b4dff 100644 --- a/libarchive/archive_read_data_into_fd.c +++ b/libarchive/archive_read_data_into_fd.c @@ -46,9 +46,9 @@ */ static int pad_to(struct archive *a, int fd, int can_lseek, - size_t nulls_size, const char *nulls, - int64_t target_offset, int64_t actual_offset) + char **nulls, int64_t target_offset, int64_t actual_offset) { + const size_t nulls_size = 16384; size_t to_write; ssize_t bytes_written; @@ -56,16 +56,26 @@ pad_to(struct archive *a, int fd, int can_lseek, actual_offset = lseek(fd, target_offset - actual_offset, SEEK_CUR); if (actual_offset != target_offset) { - archive_set_error(a, errno, "Seek error"); + archive_set_error(a, + actual_offset == -1 ? errno : ARCHIVE_ERRNO_MISC, + "Seek error"); return (ARCHIVE_FATAL); } return (ARCHIVE_OK); } + if (*nulls == NULL) { + *nulls = calloc(1, nulls_size); + if (*nulls == NULL) { + archive_set_error(a, errno, "Out of memory"); + return (ARCHIVE_FATAL); + } + } + while (target_offset > actual_offset) { to_write = nulls_size; if (target_offset < actual_offset + (int64_t)nulls_size) to_write = (size_t)(target_offset - actual_offset); - bytes_written = write(fd, nulls, to_write); + bytes_written = write(fd, *nulls, to_write); if (bytes_written < 0) { archive_set_error(a, errno, "Write error"); return (ARCHIVE_FATAL); @@ -84,29 +94,27 @@ archive_read_data_into_fd(struct archive *a, int fd) const void *buff; size_t size, bytes_to_write; ssize_t bytes_written; + int64_t fd_offset; int64_t target_offset; int64_t actual_offset = 0; int can_lseek; char *nulls = NULL; - size_t nulls_size = 16384; archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA, "archive_read_data_into_fd"); can_lseek = (fstat(fd, &st) == 0) && S_ISREG(st.st_mode); - if (!can_lseek) { - nulls = calloc(1, nulls_size); - if (!nulls) { - r = ARCHIVE_FATAL; - goto cleanup; - } + if (can_lseek) { + fd_offset = lseek(fd, 0, SEEK_CUR); + if (fd_offset == -1) + can_lseek = 0; } while ((r = archive_read_data_block(a, &buff, &size, &target_offset)) == ARCHIVE_OK) { const char *p = buff; if (target_offset > actual_offset) { - r = pad_to(a, fd, can_lseek, nulls_size, nulls, + r = pad_to(a, fd, can_lseek, &nulls, target_offset, actual_offset); if (r != ARCHIVE_OK) break; @@ -129,7 +137,7 @@ archive_read_data_into_fd(struct archive *a, int fd) } if (r == ARCHIVE_EOF && target_offset > actual_offset) { - r2 = pad_to(a, fd, can_lseek, nulls_size, nulls, + r2 = pad_to(a, fd, can_lseek, &nulls, target_offset, actual_offset); if (r2 != ARCHIVE_OK) r = r2; @@ -139,5 +147,15 @@ cleanup: free(nulls); if (r != ARCHIVE_EOF) return (r); - return (ARCHIVE_OK); + r = ARCHIVE_OK; + if (can_lseek) { + int64_t offset = lseek(fd, 0, SEEK_CUR); + if (offset - fd_offset != actual_offset) { + archive_set_error(a, + offset == -1 ? errno : ARCHIVE_ERRNO_MISC, + "Seek error"); + r = ARCHIVE_FATAL; + } + } + return (r); } diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c index 6e6bae6a4e06..c4ad595fa4d8 100644 --- a/libarchive/archive_read_disk_entry_from_file.c +++ b/libarchive/archive_read_disk_entry_from_file.c @@ -256,6 +256,11 @@ archive_read_disk_entry_from_file(struct archive *_a, char *linkbuffer; ssize_t lnklen; + if (st->st_size >= SSIZE_MAX) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't read link data"); + return (ARCHIVE_FAILED); + } linkbuffer = malloc(linkbuffer_len + 1); if (linkbuffer == NULL) { archive_set_error(&a->archive, ENOMEM, @@ -894,7 +899,7 @@ setup_sparse_fiemap(struct archive_read_disk *a, r = ioctl(*fd, FS_IOC_FIEMAP, fm); if (r < 0) { - /* When something error happens, it is better we + /* When some error happens, it is better we * should return ARCHIVE_OK because an earlier * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */ goto exit_setup_sparse_fiemap; diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index a7176bdd939d..47c1d3343640 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -920,7 +920,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, if (a->matching) { r = archive_match_path_excluded(a->matching, entry); if (r < 0) { - archive_set_error(&(a->archive), errno, + archive_set_error(&(a->archive), archive_errno(a->matching), "%s", archive_error_string(a->matching)); return (r); } @@ -1034,7 +1034,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, if (a->matching) { r = archive_match_time_excluded(a->matching, entry); if (r < 0) { - archive_set_error(&(a->archive), errno, + archive_set_error(&(a->archive), archive_errno(a->matching), "%s", archive_error_string(a->matching)); return (r); } @@ -1060,7 +1060,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, if (a->matching) { r = archive_match_owner_excluded(a->matching, entry); if (r < 0) { - archive_set_error(&(a->archive), errno, + archive_set_error(&(a->archive), archive_errno(a->matching), "%s", archive_error_string(a->matching)); return (r); } @@ -1413,18 +1413,18 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) /* * This is the new filesystem which we have to generate a new ID for. */ - fid = t->max_filesystem_id++; - if (fid > MAX_FILESYSTEM_ID) { + fid = t->max_filesystem_id; + if (fid >= MAX_FILESYSTEM_ID) { archive_set_error(&a->archive, ENOMEM, "Too many filesystems"); return (ARCHIVE_FATAL); } - if (t->max_filesystem_id > t->allocated_filesystem) { + if (fid + 1 > t->allocated_filesystem) { int s; void *p; - s = t->max_filesystem_id * 2; + s = (fid + 1) * 2; p = realloc(t->filesystem_table, - s * sizeof(*t->filesystem_table)); + s * sizeof(*t->filesystem_table)); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate tar data"); @@ -1433,6 +1433,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) t->filesystem_table = (struct filesystem *)p; t->allocated_filesystem = s; } + t->max_filesystem_id = fid + 1; t->current_filesystem_id = fid; t->current_filesystem = &(t->filesystem_table[fid]); t->current_filesystem->dev = dev; diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c index 0e890497a443..d5f7ce77cbc9 100644 --- a/libarchive/archive_read_disk_windows.c +++ b/libarchive/archive_read_disk_windows.c @@ -358,6 +358,8 @@ la_linkname_from_handle(HANDLE h, wchar_t **linkname, int *linktype) } indata = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); + if (indata == NULL) + return (-1); ret = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, indata, 1024, &inbytes, NULL); if (ret == 0) { @@ -946,7 +948,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, if (a->matching) { r = archive_match_path_excluded(a->matching, entry); if (r < 0) { - archive_set_error(&(a->archive), errno, + archive_set_error(&(a->archive), archive_errno(a->matching), "%s", archive_error_string(a->matching)); return (r); } @@ -1018,7 +1020,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, if (a->matching) { r = archive_match_time_excluded(a->matching, entry); if (r < 0) { - archive_set_error(&(a->archive), errno, + archive_set_error(&(a->archive), archive_errno(a->matching), "%s", archive_error_string(a->matching)); return (r); } @@ -1044,7 +1046,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, if (a->matching) { r = archive_match_owner_excluded(a->matching, entry); if (r < 0) { - archive_set_error(&(a->archive), errno, + archive_set_error(&(a->archive), archive_errno(a->matching), "%s", archive_error_string(a->matching)); return (r); } @@ -1450,18 +1452,18 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) /* * There is a new filesystem, we generate a new ID for. */ - fid = t->max_filesystem_id++; - if (fid > MAX_FILESYSTEM_ID) { + fid = t->max_filesystem_id; + if (fid >= MAX_FILESYSTEM_ID) { archive_set_error(&a->archive, ENOMEM, "Too many filesystems"); return (ARCHIVE_FATAL); } - if (t->max_filesystem_id > t->allocated_filesystem) { + if (fid + 1 > t->allocated_filesystem) { int s; void *p; - s = t->max_filesystem_id * 2; + s = (fid + 1) * 2; p = realloc(t->filesystem_table, - s * sizeof(*t->filesystem_table)); + s * sizeof(*t->filesystem_table)); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate tar data"); @@ -1470,6 +1472,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) t->filesystem_table = (struct filesystem *)p; t->allocated_filesystem = s; } + t->max_filesystem_id = fid + 1; t->current_filesystem_id = fid; t->current_filesystem = &(t->filesystem_table[fid]); t->current_filesystem->dev = dev; @@ -1632,6 +1635,8 @@ tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path, struct tree_entry *te; te = calloc(1, sizeof(*te)); + if (te == NULL) + return; te->next = t->stack; te->parent = t->current; if (te->parent) @@ -1704,6 +1709,8 @@ tree_open(const wchar_t *path, int symlink_mode, int restore_time) struct tree *t; t = calloc(1, sizeof(*t)); + if (t == NULL) + return (NULL); archive_string_init(&(t->full_path)); archive_string_init(&t->path); if (archive_wstring_ensure(&t->path, 15) == NULL) { diff --git a/libarchive/archive_read_filter.3 b/libarchive/archive_read_filter.3 index 72ff240fd393..05513ececda6 100644 --- a/libarchive/archive_read_filter.3 +++ b/libarchive/archive_read_filter.3 @@ -142,7 +142,9 @@ These functions return .Cm ARCHIVE_OK if the compression is fully supported, .Cm ARCHIVE_WARN -if the compression is supported only through an external program. +if the compression is supported only through an external program, or +.Cm ARCHIVE_FATAL +on error. .Pp .Fn archive_read_support_filter_none always succeeds. @@ -158,5 +160,4 @@ functions. .Xr archive_read 3 , .Xr archive_read_data 3 , .Xr archive_read_format 3 , -.Xr archive_read_format 3 , .Xr libarchive 3 diff --git a/libarchive/archive_read_open.3 b/libarchive/archive_read_open.3 index 081b7114bea6..0e85d16f0d2f 100644 --- a/libarchive/archive_read_open.3 +++ b/libarchive/archive_read_open.3 @@ -31,6 +31,7 @@ .Nm archive_read_open_fd , .Nm archive_read_open_FILE , .Nm archive_read_open_filename , +.Nm archive_read_open_filenames , .Nm archive_read_open_memory .Nd functions for reading streaming archives .Sh LIBRARY @@ -65,6 +66,12 @@ Streaming Archive Library (libarchive, -larchive) .Fa "size_t block_size" .Fc .Ft int +.Fo archive_read_open_filenames +.Fa "struct archive *" +.Fa "const char **filenames" +.Fa "size_t block_size" +.Fc +.Ft int .Fn archive_read_open_memory "struct archive *" "const void *buff" "size_t size" .Sh DESCRIPTION .Bl -tag -compact -width indent @@ -111,6 +118,15 @@ Like except that it accepts a simple filename and a block size. A NULL filename represents standard input. This function is safe for use with tape drives or other blocked devices. +.It Fn archive_read_open_filenames +Like +.Fn archive_read_open , +except that it accepts a NULL-terminated array of filenames to open in +sequence (as would be created by the +.Xr split 1 +command) and a block size. +A NULL filename at the beginning of the array represents standard input. +This function is safe for use with tape drives or other blocked devices. .It Fn archive_read_open_memory Like .Fn archive_read_open , diff --git a/libarchive/archive_read_open_filename.c b/libarchive/archive_read_open_filename.c index 9ec1e6c0e808..91f64b694a0c 100644 --- a/libarchive/archive_read_open_filename.c +++ b/libarchive/archive_read_open_filename.c @@ -40,6 +40,9 @@ #ifdef HAVE_IO_H #include <io.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif @@ -181,7 +184,7 @@ archive_read_open_filenames_w(struct archive *a, const wchar_t **wfilenames, if (wfilename == NULL) wfilename = L""; mine = calloc(1, - sizeof(*mine) + wcslen(wfilename) * sizeof(wchar_t)); + sizeof(*mine) + wcslen(wfilename) * MB_LEN_MAX); if (mine == NULL) goto no_memory; mine->block_size = block_size; @@ -315,7 +318,7 @@ file_open(struct archive *a, void *client_data) } #else archive_set_error(a, ARCHIVE_ERRNO_MISC, - "Unexpedted operation in archive_read_open_filename"); + "Unexpected operation in archive_read_open_filename"); goto fail; #endif } diff --git a/libarchive/archive_read_support_filter_all.c b/libarchive/archive_read_support_filter_all.c index cb46d120d102..f08677301fb3 100644 --- a/libarchive/archive_read_support_filter_all.c +++ b/libarchive/archive_read_support_filter_all.c @@ -43,34 +43,34 @@ archive_read_support_filter_all(struct archive *a) archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_filter_all"); - /* Bzip falls back to "bunzip2" command-line */ + /* Bzip falls back to "bzip2 -d" command-line */ archive_read_support_filter_bzip2(a); /* The decompress code doesn't use an outside library. */ archive_read_support_filter_compress(a); /* Gzip decompress falls back to "gzip -d" command-line. */ archive_read_support_filter_gzip(a); - /* Lzip falls back to "unlzip" command-line program. */ + /* Lzip falls back to "lzip -d -q" command-line. */ archive_read_support_filter_lzip(a); /* The LZMA file format has a very weak signature, so it * may not be feasible to keep this here, but we'll try. * This will come back out if there are problems. */ - /* Lzma falls back to "unlzma" command-line program. */ + /* Lzma falls back to "lzma -d -qq" command-line. */ archive_read_support_filter_lzma(a); - /* Xz falls back to "unxz" command-line program. */ + /* Xz falls back to "xz -d -qq" command-line. */ archive_read_support_filter_xz(a); /* The decode code doesn't use an outside library. */ archive_read_support_filter_uu(a); /* The decode code doesn't use an outside library. */ archive_read_support_filter_rpm(a); - /* The decode code always uses "lrzip -q -d" command-line. */ + /* The decode code always uses "lrzip -d -q" command-line. */ archive_read_support_filter_lrzip(a); /* Lzop decompress falls back to "lzop -d" command-line. */ archive_read_support_filter_lzop(a); /* The decode code always uses "grzip -d" command-line. */ archive_read_support_filter_grzip(a); - /* Lz4 falls back to "lz4 -d" command-line program. */ + /* Lz4 falls back to "lz4 -d -q" command-line. */ archive_read_support_filter_lz4(a); - /* Zstd falls back to "zstd -d" command-line program. */ + /* Zstd falls back to "zstd -d -qq" command-line. */ archive_read_support_filter_zstd(a); /* Note: We always return ARCHIVE_OK here, even if some of the diff --git a/libarchive/archive_read_support_filter_bzip2.c b/libarchive/archive_read_support_filter_bzip2.c index 479237c27792..26d550e2c45a 100644 --- a/libarchive/archive_read_support_filter_bzip2.c +++ b/libarchive/archive_read_support_filter_bzip2.c @@ -28,6 +28,9 @@ #ifdef HAVE_ERRNO_H #include <errno.h> #endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif #include <stdio.h> #ifdef HAVE_STDLIB_H #include <stdlib.h> @@ -63,8 +66,7 @@ static int bzip2_filter_close(struct archive_read_filter *); /* * Note that we can detect bzip2 archives even if we can't decompress * them. (In fact, we like detecting them because we can give better - * error messages.) So the bid framework here gets compiled even - * if bzlib is unavailable. + * error messages.) */ static int bzip2_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); static int bzip2_reader_init(struct archive_read_filter *); @@ -113,13 +115,12 @@ static int bzip2_reader_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *buffer; - ssize_t avail; int bits_checked; (void)self; /* UNUSED */ /* Minimal bzip2 archive is 14 bytes. */ - buffer = __archive_read_filter_ahead(filter, 14, &avail); + buffer = __archive_read_filter_ahead(filter, 14, NULL); if (buffer == NULL) return (0); @@ -150,9 +151,9 @@ bzip2_reader_bid(struct archive_read_filter_bidder *self, struct archive_read_fi #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) /* - * If we don't have the library on this system, we can't actually do the - * decompression. We can, however, still detect compressed archives - * and emit a useful message. + * If we don't have the library on this system, we can't do the + * decompression directly. We can, however, try to run "bzip2 -d" + * in case that's available. */ static int bzip2_reader_init(struct archive_read_filter *self) @@ -232,6 +233,8 @@ bzip2_filter_read(struct archive_read_filter *self, const void **p) /* Try to fill the output buffer. */ for (;;) { + ssize_t max_in; + if (!state->valid) { if (bzip2_reader_bid(self->bidder, self->upstream) == 0) { state->eof = 1; @@ -286,15 +289,13 @@ bzip2_filter_read(struct archive_read_filter *self, const void **p) return (ARCHIVE_FATAL); } state->stream.next_in = (char *)(uintptr_t)read_buf; + if (UINT_MAX >= SSIZE_MAX) + max_in = SSIZE_MAX; + else + max_in = UINT_MAX; + if (ret > max_in) + ret = max_in; state->stream.avail_in = (uint32_t)ret; - /* There is no more data, return whatever we have. */ - if (ret == 0) { - state->eof = 1; - *p = state->out_block; - decompressed = state->stream.next_out - - state->out_block; - return (decompressed); - } /* Decompress as much as we can in one pass. */ ret = BZ2_bzDecompress(&(state->stream)); diff --git a/libarchive/archive_read_support_filter_compress.c b/libarchive/archive_read_support_filter_compress.c index b89eaabe5259..54a99818655d 100644 --- a/libarchive/archive_read_support_filter_compress.c +++ b/libarchive/archive_read_support_filter_compress.c @@ -104,6 +104,7 @@ struct private_data { void *out_block; /* Decompression status variables. */ + int initialized; int use_reset_code; int end_of_stream; /* EOF status. */ int maxcode; /* Largest code. */ @@ -172,13 +173,12 @@ compress_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *buffer; - ssize_t avail; int bits_checked; (void)self; /* UNUSED */ /* Shortest valid compress file is 3 bytes. */ - buffer = __archive_read_filter_ahead(filter, 3, &avail); + buffer = __archive_read_filter_ahead(filter, 3, NULL); if (buffer == NULL) return (0); @@ -212,7 +212,6 @@ compress_bidder_init(struct archive_read_filter *self) struct private_data *state; static const size_t out_block_size = 64 * 1024; void *out_block; - int code; self->code = ARCHIVE_FILTER_COMPRESS; self->name = "compress (.Z)"; @@ -233,14 +232,23 @@ compress_bidder_init(struct archive_read_filter *self) state->out_block = out_block; self->vtable = &compress_reader_vtable; - /* XXX MOVE THE FOLLOWING OUT OF INIT() XXX */ + return (ARCHIVE_OK); +} + +static int +compress_filter_init(struct archive_read_filter *self) +{ + struct private_data *state = (struct private_data *)self->data; + int code; + + state->initialized = 1; (void)getbits(self, 8); /* Skip first signature byte. */ (void)getbits(self, 8); /* Skip second signature byte. */ /* Get compression parameters. */ code = getbits(self, 8); - if ((code & 0x1f) > 16) { + if (code < 0 || (code & 0x1f) > 16) { archive_set_error(&self->archive->archive, -1, "Invalid compressed data"); return (ARCHIVE_FATAL); @@ -278,6 +286,11 @@ compress_filter_read(struct archive_read_filter *self, const void **pblock) int ret; state = (struct private_data *)self->data; + if (!state->initialized) { + ret = compress_filter_init(self); + if (ret != ARCHIVE_OK) + return (ret); + } if (state->end_of_stream) { *pblock = NULL; return (0); @@ -325,18 +338,11 @@ next_code(struct archive_read_filter *self) struct private_data *state = (struct private_data *)self->data; int code, newcode; - static int debug_buff[1024]; - static unsigned debug_index; - again: code = newcode = getbits(self, state->bits); if (code < 0) return (code); - debug_buff[debug_index++] = code; - if (debug_index >= sizeof(debug_buff)/sizeof(debug_buff[0])) - debug_index = 0; - /* If it's a reset code, reset the dictionary. */ if ((code == 256) && state->use_reset_code) { /* @@ -434,7 +440,7 @@ getbits(struct archive_read_filter *self, int n) 1, &ret); if (ret == 0) return (-1); - if (ret < 0 || state->next_in == NULL) + if (state->next_in == NULL) return (ARCHIVE_FATAL); state->consume_unnotified = state->avail_in = ret; } diff --git a/libarchive/archive_read_support_filter_grzip.c b/libarchive/archive_read_support_filter_grzip.c index 8ec5d1f855cb..2bbb2e016e71 100644 --- a/libarchive/archive_read_support_filter_grzip.c +++ b/libarchive/archive_read_support_filter_grzip.c @@ -80,12 +80,11 @@ grzip_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *p; - ssize_t avail; (void)self; /* UNUSED */ - p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), &avail); - if (p == NULL || avail == 0) + p = __archive_read_filter_ahead(filter, sizeof(grzip_magic), NULL); + if (p == NULL) return (0); if (memcmp(p, grzip_magic, sizeof(grzip_magic))) diff --git a/libarchive/archive_read_support_filter_gzip.c b/libarchive/archive_read_support_filter_gzip.c index 726385e328a0..a312065c63e6 100644 --- a/libarchive/archive_read_support_filter_gzip.c +++ b/libarchive/archive_read_support_filter_gzip.c @@ -56,7 +56,6 @@ struct private_data { char in_stream; unsigned char *out_block; size_t out_block_size; - int64_t total_out; unsigned long crc; uint32_t mtime; char *name; @@ -71,12 +70,7 @@ static int gzip_filter_close(struct archive_read_filter *); /* * Note that we can detect gzip archives even if we can't decompress * them. (In fact, we like detecting them because we can give better - * error messages.) So the bid framework here gets compiled even - * if zlib is unavailable. - * - * TODO: If zlib is unavailable, gzip_bidder_init() should - * use the compress_program framework to try to fire up an external - * gzip program. + * error messages.) */ static int gzip_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); @@ -146,7 +140,7 @@ peek_at_header(struct archive_read_filter *filter, int *pbits, * is all fixed layout. */ len = 10; p = __archive_read_filter_ahead(filter, len, &avail); - if (p == NULL || avail == 0) + if (p == NULL) return (0); /* We only support deflation- third byte must be 0x08. */ if (memcmp(p, "\x1F\x8B\x08", 3) != 0) @@ -171,7 +165,7 @@ peek_at_header(struct archive_read_filter *filter, int *pbits, p = __archive_read_filter_ahead(filter, len + 2, &avail); if (p == NULL) return (0); - len += ((int)p[len + 1] << 8) | (int)p[len]; + len += archive_le16dec(p + len); len += 2; } @@ -284,7 +278,7 @@ gzip_read_header(struct archive_read_filter *self, struct archive_entry *entry) state = (struct private_data *)self->data; - /* A mtime of 0 is considered invalid/missing. */ + /* An mtime of 0 is considered invalid/missing. */ if (state->mtime != 0) archive_entry_set_mtime(entry, state->mtime, 0); @@ -341,7 +335,7 @@ static int consume_header(struct archive_read_filter *self) { struct private_data *state; - ssize_t avail; + ssize_t avail, max_in; size_t len; int ret; @@ -359,6 +353,18 @@ consume_header(struct archive_read_filter *self) /* Initialize compression library. */ state->stream.next_in = (unsigned char *)(uintptr_t) __archive_read_filter_ahead(self->upstream, 1, &avail); + if (avail < 0) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Failed to read gzip input"); + return (ARCHIVE_FATAL); + } + if (UINT_MAX >= SSIZE_MAX) + max_in = SSIZE_MAX; + else + max_in = UINT_MAX; + if (avail > max_in) + avail = max_in; state->stream.avail_in = (uInt)avail; ret = inflateInit2(&(state->stream), -15 /* Don't check for zlib header */); @@ -400,7 +406,6 @@ consume_trailer(struct archive_read_filter *self) { struct private_data *state; const unsigned char *p; - ssize_t avail; state = (struct private_data *)self->data; @@ -416,8 +421,8 @@ consume_trailer(struct archive_read_filter *self) } /* GZip trailer is a fixed 8 byte structure. */ - p = __archive_read_filter_ahead(self->upstream, 8, &avail); - if (p == NULL || avail == 0) + p = __archive_read_filter_ahead(self->upstream, 8, NULL); + if (p == NULL) return (ARCHIVE_FATAL); /* XXX TODO: Verify the length and CRC. */ @@ -502,7 +507,6 @@ gzip_filter_read(struct archive_read_filter *self, const void **p) /* We've read as much as we can. */ decompressed = state->stream.next_out - state->out_block; - state->total_out += decompressed; if (decompressed == 0) *p = NULL; else diff --git a/libarchive/archive_read_support_filter_lrzip.c b/libarchive/archive_read_support_filter_lrzip.c index a562d538ed81..9d51837753e3 100644 --- a/libarchive/archive_read_support_filter_lrzip.c +++ b/libarchive/archive_read_support_filter_lrzip.c @@ -79,15 +79,15 @@ lrzip_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *p; - ssize_t avail, len; + ssize_t len; int i; (void)self; /* UNUSED */ /* Start by looking at the first six bytes of the header, which * is all fixed layout. */ len = 6; - p = __archive_read_filter_ahead(filter, len, &avail); - if (p == NULL || avail == 0) + p = __archive_read_filter_ahead(filter, len, NULL); + if (p == NULL) return (0); if (memcmp(p, LRZIP_HEADER_MAGIC, LRZIP_HEADER_MAGIC_LEN)) diff --git a/libarchive/archive_read_support_filter_lz4.c b/libarchive/archive_read_support_filter_lz4.c index acd7f5157997..2e5f634b1aa3 100644 --- a/libarchive/archive_read_support_filter_lz4.c +++ b/libarchive/archive_read_support_filter_lz4.c @@ -44,6 +44,7 @@ #include "archive.h" #include "archive_endian.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" #include "archive_xxhash.h" @@ -95,8 +96,7 @@ static int lz4_filter_close(struct archive_read_filter *); /* * Note that we can detect lz4 archives even if we can't decompress * them. (In fact, we like detecting them because we can give better - * error messages.) So the bid framework here gets compiled even - * if liblz4 is unavailable. + * error messages.) */ static int lz4_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); static int lz4_reader_init(struct archive_read_filter *); @@ -145,52 +145,75 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, const unsigned char *buffer; ssize_t avail; int bits_checked = 0; - ssize_t min_lz4_archive_size = 11; + const size_t min_lz4_archive_size = 11; - // LZ4 skippable frames contain a 4 byte magic number followed by - // a 4 byte frame data size, then that number of bytes of data. Regular - // frames contain a 4 byte magic number followed by a 2-14 byte frame - // header, some data, and a 3 byte end marker. - ssize_t min_lz4_frame_size = 8; + /* + * LZ4 skippable frames contain a 4 byte magic number followed by + * a 4 byte frame data size, then that number of bytes of data. + * Regular frames contain a 4 byte magic number followed by a 2-14 + * byte frame header, some data, and a 3 byte end marker. + */ + const size_t min_lz4_frame_size = 8; - ssize_t offset_in_buffer = 0; - ssize_t max_lookahead = 64 * 1024; + size_t offset_in_buffer = 0; + const size_t max_lookahead = 64 * 1024; + uint32_t magic_number; - (void)self; // UNUSED + (void)self; /* UNUSED */ - // Zstd and LZ4 skippable frame magic numbers are identical. To - // differentiate these two, we need to look for a non-skippable - // frame. + /* + * Zstd and LZ4 skippable frame magic numbers are identical. To + * differentiate these two, we need to look for a non-skippable + * frame. + */ - // Minimal lz4 archive is 11 bytes. - buffer = __archive_read_filter_ahead(filter, min_lz4_archive_size, &avail); + /* Minimal lz4 archive is 11 bytes. */ + buffer = __archive_read_filter_ahead(filter, min_lz4_archive_size, + &avail); if (buffer == NULL) return (0); - uint32_t magic_number = archive_le32dec(buffer); + magic_number = archive_le32dec(buffer); while ((magic_number & LZ4_SKIPPABLE_MASK) == LZ4_SKIPPABLE_START) { + size_t min; + uint32_t frame_data_size; - offset_in_buffer += 4; // Skip over the magic number + /* Skip over the magic number */ + offset_in_buffer += 4; - // Ensure that we can read another 4 bytes. - if (offset_in_buffer + 4 > avail) { - buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail); + /* Ensure that we can read another 4 bytes. */ + if (offset_in_buffer + 4 > (size_t)avail) { + buffer = __archive_read_filter_ahead(filter, + offset_in_buffer + 4, &avail); if (buffer == NULL) return (0); } - uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer); + frame_data_size = archive_le32dec(buffer + offset_in_buffer); - // Skip over the 4 frame data size bytes, plus the value stored there. - offset_in_buffer += 4 + frame_data_size; + /* Skip over the 4 frame data size bytes */ + offset_in_buffer += 4; - // There should be at least one more frame if this is LZ4 data. - if (offset_in_buffer + min_lz4_frame_size > avail) { // TODO: should this be >= ? - if (offset_in_buffer + min_lz4_frame_size > max_lookahead) + /* Skip over the value stored there. */ + if (archive_ckd_add_size(&offset_in_buffer, + offset_in_buffer, frame_data_size)) + return (0); + + /* + * There should be at least one more frame + * if this is LZ4 data. + */ + if (archive_ckd_add_size(&min, + offset_in_buffer, min_lz4_frame_size)) + return (0); + /* TODO: should this be >= ? */ + if (min > (size_t)avail) { + if (min > max_lookahead) return (0); - buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_lz4_frame_size, &avail); + buffer = __archive_read_filter_ahead(filter, + min, &avail); if (buffer == NULL) return (0); } @@ -198,8 +221,10 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, magic_number = archive_le32dec(buffer + offset_in_buffer); } - // We have skipped over any skippable frames. Either a regular LZ4 frame - // follows, or this isn't LZ4 data. + /* + * We have skipped over any skippable frames. Either a regular LZ4 frame + * follows, or this isn't LZ4 data. + */ bits_checked = offset_in_buffer; buffer = buffer + offset_in_buffer; @@ -241,9 +266,9 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, #if !defined(HAVE_LIBLZ4) /* - * If we don't have the library on this system, we can't actually do the - * decompression. We can, however, still detect compressed archives - * and emit a useful message. + * If we don't have the library on this system, we can't do the + * decompression directly. We can, however, try to run "lz4 -d -q" + * in case that's available. */ static int lz4_reader_init(struct archive_read_filter *self) @@ -304,13 +329,15 @@ lz4_allocate_out_block(struct archive_read_filter *self) out_block_size += 64 * 1024; if (state->out_block_size < out_block_size) { free(state->out_block); + state->out_block = NULL; out_block = malloc(out_block_size); - state->out_block_size = out_block_size; if (out_block == NULL) { + state->out_block_size = 0; archive_set_error(&self->archive->archive, ENOMEM, "Can't allocate data for lz4 decompression"); return (ARCHIVE_FATAL); } + state->out_block_size = out_block_size; state->out_block = out_block; } if (!state->flags.block_independence) @@ -327,13 +354,15 @@ lz4_allocate_out_block_for_legacy(struct archive_read_filter *self) if (state->out_block_size < out_block_size) { free(state->out_block); + state->out_block = NULL; out_block = malloc(out_block_size); - state->out_block_size = out_block_size; if (out_block == NULL) { + state->out_block_size = 0; archive_set_error(&self->archive->archive, ENOMEM, "Can't allocate data for lz4 decompression"); return (ARCHIVE_FATAL); } + state->out_block_size = out_block_size; state->out_block = out_block; } return (ARCHIVE_OK); @@ -361,7 +390,7 @@ lz4_filter_read(struct archive_read_filter *self, const void **p) break; case READ_DEFAULT_STREAM: case READ_LEGACY_STREAM: - /* Reading a lz4 stream already failed. */ + /* Reading an lz4 stream already failed. */ archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "Invalid sequence"); return (ARCHIVE_FATAL); @@ -408,9 +437,15 @@ lz4_filter_read(struct archive_read_filter *self, const void **p) "Malformed lz4 data"); return (ARCHIVE_FATAL); } - uint32_t skip_bytes = archive_le32dec(read_buf); - __archive_read_filter_consume(self->upstream, - 4 + skip_bytes); + int64_t skip_bytes = archive_le32dec(read_buf); + if (__archive_read_filter_consume(self->upstream, + 4 + skip_bytes) < 0) { + archive_set_error( + &self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Malformed lz4 data"); + return (ARCHIVE_FATAL); + } } else { /* Ignore following unrecognized data. */ state->eof = 1; @@ -512,8 +547,11 @@ lz4_filter_read_descriptor(struct archive_read_filter *self) /* Make sure we have a large enough buffer for uncompressed data. */ if (lz4_allocate_out_block(self) != ARCHIVE_OK) return (ARCHIVE_FATAL); - if (state->flags.stream_checksum) + if (state->flags.stream_checksum) { state->xxh32_state = __archive_xxhash.XXH32_init(0); + if (state->xxh32_state == NULL) + return (ARCHIVE_FATAL); + } state->decoded_size = 0; /* Success */ @@ -530,7 +568,6 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) struct private_data *state = (struct private_data *)self->data; ssize_t compressed_size; const char *read_buf; - ssize_t bytes_remaining; int checksum_size; ssize_t uncompressed_size; size_t prefix64k; @@ -538,8 +575,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) *p = NULL; /* Make sure we have 4 bytes for a block size. */ - read_buf = __archive_read_filter_ahead(self->upstream, 4, - &bytes_remaining); + read_buf = __archive_read_filter_ahead(self->upstream, 4, NULL); if (read_buf == NULL) goto truncated_error; compressed_size = archive_le32dec(read_buf); @@ -565,7 +601,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) a huge buffer used for decoded data. */ read_buf = __archive_read_filter_ahead(self->upstream, - 4 + compressed_size + checksum_size, &bytes_remaining); + 4 + compressed_size + checksum_size, NULL); if (read_buf == NULL) goto truncated_error; @@ -673,7 +709,6 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p) { struct private_data *state = (struct private_data *)self->data; const char *read_buf; - ssize_t bytes_remaining; ssize_t ret; if (state->stage == SELECT_STREAM) { @@ -697,7 +732,7 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p) unsigned int checksum; unsigned int checksum_stream; read_buf = __archive_read_filter_ahead(self->upstream, - 4, &bytes_remaining); + 4, NULL); if (read_buf == NULL) { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, "truncated lz4 input"); diff --git a/libarchive/archive_read_support_filter_lzop.c b/libarchive/archive_read_support_filter_lzop.c index 12ed78c578cd..40c4575882e0 100644 --- a/libarchive/archive_read_support_filter_lzop.c +++ b/libarchive/archive_read_support_filter_lzop.c @@ -71,7 +71,6 @@ struct read_lzop { unsigned char *out_block; size_t out_block_size; - int64_t total_out; int flags; uint32_t compressed_cksum; uint32_t uncompressed_cksum; @@ -118,7 +117,6 @@ archive_read_support_filter_lzop(struct archive *_a) #if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) return (ARCHIVE_OK); #else - /* Return ARCHIVE_WARN since this always uses an external program. */ archive_set_error(_a, ARCHIVE_ERRNO_MISC, "Using external lzop program for lzop decompression"); return (ARCHIVE_WARN); @@ -133,12 +131,11 @@ lzop_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *p; - ssize_t avail; (void)self; /* UNUSED */ - p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail); - if (p == NULL || avail == 0) + p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, NULL); + if (p == NULL) return (0); if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) @@ -429,12 +426,11 @@ lzop_filter_read(struct archive_read_filter *self, const void **p) } /* - * If the both uncompressed size and compressed size are the same, + * If both uncompressed size and compressed size are the same, * we do not decompress this block. */ if (state->uncompressed_size == state->compressed_size) { *p = b; - state->total_out += state->compressed_size; state->unconsumed_bytes = state->compressed_size; return ((ssize_t)state->uncompressed_size); } @@ -478,7 +474,6 @@ lzop_filter_read(struct archive_read_filter *self, const void **p) __archive_read_filter_consume(self->upstream, state->compressed_size); *p = state->out_block; - state->total_out += out_size; return ((ssize_t)out_size); } diff --git a/libarchive/archive_read_support_filter_rpm.c b/libarchive/archive_read_support_filter_rpm.c index 25ace4a25bc9..1213df6c9b17 100644 --- a/libarchive/archive_read_support_filter_rpm.c +++ b/libarchive/archive_read_support_filter_rpm.c @@ -38,20 +38,7 @@ #include "archive_read_private.h" struct rpm { - int64_t total_in; - uint64_t hpos; - uint64_t hlen; - unsigned char header[16]; - enum { - ST_LEAD, /* Skipping 'Lead' section. */ - ST_HEADER, /* Reading 'Header' section; - * first 16 bytes. */ - ST_HEADER_DATA, /* Skipping 'Header' section. */ - ST_PADDING, /* Skipping padding data after the - * 'Header' section. */ - ST_ARCHIVE /* Reading 'Archive' section. */ - } state; - int first_header; + int data_reached; }; #define RPM_LEAD_SIZE 96 /* Size of 'Lead' section. */ #define RPM_MIN_HEAD_SIZE 16 /* Minimum size of 'Head'. */ @@ -64,8 +51,6 @@ static ssize_t rpm_filter_read(struct archive_read_filter *, const void **); static int rpm_filter_close(struct archive_read_filter *); -static inline size_t rpm_limit_bytes(uint64_t, size_t); - #if ARCHIVE_VERSION_NUMBER < 4000000 /* Deprecated; remove in libarchive 4.0 */ int @@ -95,12 +80,11 @@ rpm_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *b; - ssize_t avail; int bits_checked; (void)self; /* UNUSED */ - b = __archive_read_filter_ahead(filter, 8, &avail); + b = __archive_read_filter_ahead(filter, 8, NULL); if (b == NULL) return (0); @@ -152,133 +136,107 @@ rpm_bidder_init(struct archive_read_filter *self) } self->data = rpm; - rpm->state = ST_LEAD; + rpm->data_reached = 0; self->vtable = &rpm_reader_vtable; return (ARCHIVE_OK); } -static inline size_t -rpm_limit_bytes(uint64_t bytes, size_t max) +static ssize_t +skip_padding(struct archive_read_filter *self) { - return (bytes > max ? max : (size_t)bytes); + const unsigned char *h; + ssize_t avail, count, r; + + do { + h = __archive_read_filter_ahead(self->upstream, 1, &avail); + if (h == NULL) + return (ARCHIVE_FATAL); + for (count = 0; count < avail && *h++ == '\0'; count++) + ; + r = __archive_read_filter_consume(self->upstream, count); + if (r < 0) + return (r); + } while (count == avail); + + return (ARCHIVE_OK); } static ssize_t -rpm_filter_read(struct archive_read_filter *self, const void **buff) +skip_prologue(struct archive_read_filter *self) { - struct rpm *rpm; - const unsigned char *b; - ssize_t avail_in, total, used; - size_t n; - uint64_t section; - uint64_t bytes; + const unsigned char *h; + ssize_t r; + int header, seen_header = 0; + + /* Skip lead size. */ + r = __archive_read_filter_consume(self->upstream, RPM_LEAD_SIZE); + if (r < 0) + return (r); - rpm = (struct rpm *)self->data; - *buff = NULL; - total = avail_in = 0; - b = NULL; - used = 0; do { - if (b == NULL) { - b = __archive_read_filter_ahead(self->upstream, 1, - &avail_in); - if (b == NULL) { - if (avail_in < 0) - return (ARCHIVE_FATAL); - else - break; - } - } + /* Read header intro. */ + h = __archive_read_filter_ahead(self->upstream, + RPM_MIN_HEAD_SIZE, NULL); + if (h == NULL) + return (ARCHIVE_FATAL); - switch (rpm->state) { - case ST_LEAD: - if (rpm->total_in + avail_in < RPM_LEAD_SIZE) - used += avail_in; - else { - n = (size_t)(RPM_LEAD_SIZE - rpm->total_in); - used += n; - b += n; - rpm->state = ST_HEADER; - rpm->hpos = 0; - rpm->hlen = 0; - rpm->first_header = 1; - } - break; - case ST_HEADER: - n = rpm_limit_bytes(RPM_MIN_HEAD_SIZE - rpm->hpos, - avail_in - used); - memcpy(rpm->header+rpm->hpos, b, n); - b += n; - used += n; - rpm->hpos += n; + header = (memcmp(h, "\x8E\xAD\xE8\x01", 4) == 0); + if (header) { + int64_t bytes, length, section; - if (rpm->hpos == RPM_MIN_HEAD_SIZE) { - if (rpm->header[0] != 0x8e || - rpm->header[1] != 0xad || - rpm->header[2] != 0xe8 || - rpm->header[3] != 0x01) { - if (rpm->first_header) { - archive_set_error( - &self->archive->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "Unrecognized rpm header"); - return (ARCHIVE_FATAL); - } - rpm->state = ST_ARCHIVE; - *buff = rpm->header; - total = RPM_MIN_HEAD_SIZE; - break; - } - /* Calculate 'Header' length. */ - section = archive_be32dec(rpm->header+8); - bytes = archive_be32dec(rpm->header+12); - rpm->hlen = rpm->hpos + section * 16 + bytes; - rpm->state = ST_HEADER_DATA; - rpm->first_header = 0; - } - break; - case ST_HEADER_DATA: - n = rpm_limit_bytes(rpm->hlen - rpm->hpos, - avail_in - used); - b += n; - used += n; - rpm->hpos += n; - if (rpm->hpos == rpm->hlen) - rpm->state = ST_PADDING; - break; - case ST_PADDING: - while (used < avail_in) { - if (*b != 0) { - /* Read next header. */ - rpm->state = ST_HEADER; - rpm->hpos = 0; - rpm->hlen = 0; - break; - } - b++; - used++; - } - break; - case ST_ARCHIVE: - *buff = b; - total = avail_in; - used = avail_in; - break; - } - if (used == avail_in) { - rpm->total_in += used; - __archive_read_filter_consume(self->upstream, used); - b = NULL; - used = 0; + seen_header = 1; + + /* Calculate header length. */ + section = archive_be32dec(h + 8); + bytes = archive_be32dec(h + 12); + length = RPM_MIN_HEAD_SIZE + section * 16 + bytes; + + /* Skip header. */ + r = __archive_read_filter_consume(self->upstream, + length); + if (r < 0) + return (r); + + /* Skip padding. */ + r = skip_padding(self); + if (r != ARCHIVE_OK) + return (r); } - } while (total == 0 && avail_in > 0); + } while (header); - if (used > 0 && b != NULL) { - rpm->total_in += used; - __archive_read_filter_consume(self->upstream, used); + /* At least one header must have been encountered. */ + if (!seen_header) { + archive_set_error( + &self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unrecognized rpm header"); + return (ARCHIVE_FATAL); } - return (total); + + return (ARCHIVE_OK); +} + +static ssize_t +rpm_filter_read(struct archive_read_filter *self, const void **buff) +{ + struct rpm *rpm; + ssize_t r; + + rpm = (struct rpm *)self->data; + + if (!rpm->data_reached) { + r = skip_prologue(self); + if (r != ARCHIVE_OK) + return (r); + rpm->data_reached = 1; + } + + *buff = __archive_read_filter_ahead(self->upstream, 1, &r); + if (r > 0) + __archive_read_filter_consume(self->upstream, r); + + return r; } static int diff --git a/libarchive/archive_read_support_filter_uu.c b/libarchive/archive_read_support_filter_uu.c index acb8feb79b2d..714c7e836170 100644 --- a/libarchive/archive_read_support_filter_uu.c +++ b/libarchive/archive_read_support_filter_uu.c @@ -43,8 +43,6 @@ /* Maximum lookahead during bid phase */ #define UUENCODE_BID_MAX_READ 128*1024 /* in bytes */ -#define UUENCODE_MAX_LINE_LENGTH 34*1024 /* in bytes */ - struct uudecode { int64_t total; unsigned char *in_buff; @@ -224,7 +222,7 @@ bid_get_line(struct archive_read_filter *filter, len = get_line(*b, *avail, nl); /* - * Read bytes more while it does not reach the end of line. + * Read more bytes while it does not reach the end of line. */ while (*nl == 0 && len == *avail && !quit && *nbytes_read < UUENCODE_BID_MAX_READ) { @@ -423,7 +421,6 @@ ensure_in_buff_size(struct archive_read_filter *self, /* Allocate the new buffer. */ ptr = malloc(newsize); if (ptr == NULL) { - free(ptr); archive_set_error(&self->archive->archive, ENOMEM, "Can't allocate data for uudecode"); @@ -480,13 +477,15 @@ read_more: used = 0; total = 0; out = uudecode->out_buff; + if (avail_in > 2 * UUENCODE_BID_MAX_READ) + avail_in = 2 * UUENCODE_BID_MAX_READ; ravail = avail_in; if (uudecode->state == ST_IGNORE) { used = avail_in; goto finish; } if (uudecode->in_cnt) { - if (uudecode->in_cnt > UUENCODE_MAX_LINE_LENGTH) { + if (uudecode->in_cnt > UUENCODE_BID_MAX_READ) { archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid format data"); @@ -523,6 +522,12 @@ read_more: "Insufficient compressed data"); return (ARCHIVE_FATAL); } + if (len > UUENCODE_BID_MAX_READ) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid format data"); + return (ARCHIVE_FATAL); + } llen = len; if ((nl == 0) && (uudecode->state != ST_UUEND)) { if (total == 0 && ravail <= 0) { @@ -544,7 +549,7 @@ read_more: uudecode->in_cnt = len; if (total == 0) { /* Do not return 0; it means end-of-file. - * We should try to read bytes more. */ + * We should try to read more bytes. */ __archive_read_filter_consume( self->upstream, ravail); goto read_more; @@ -586,11 +591,11 @@ read_more: if (uudecode->name != NULL) free(uudecode->name); uudecode->name = malloc(namelen + 1); - if (uudecode->name == NULL) { - archive_set_error( - &self->archive->archive, - ENOMEM, - "Can't allocate data for uudecode"); + if (uudecode->name == NULL) { + archive_set_error( + &self->archive->archive, + ENOMEM, + "Can't allocate data for uudecode"); return (ARCHIVE_FATAL); } strncpy(uudecode->name, diff --git a/libarchive/archive_read_support_filter_xz.c b/libarchive/archive_read_support_filter_xz.c index dcbf734ecacb..22cbb26cd091 100644 --- a/libarchive/archive_read_support_filter_xz.c +++ b/libarchive/archive_read_support_filter_xz.c @@ -54,7 +54,6 @@ struct private_data { lzma_stream stream; unsigned char *out_block; size_t out_block_size; - int64_t total_out; char eof; /* True = found end of compressed data. */ char in_stream; @@ -83,8 +82,7 @@ static int xz_lzma_bidder_init(struct archive_read_filter *); /* * Note that we can detect xz and lzma compressed files even if we * can't decompress them. (In fact, we like detecting them because we - * can give better error messages.) So the bid framework here gets - * compiled even if no lzma library is available. + * can give better error messages.) */ static int xz_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); @@ -203,11 +201,10 @@ xz_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *buffer; - ssize_t avail; (void)self; /* UNUSED */ - buffer = __archive_read_filter_ahead(filter, 6, &avail); + buffer = __archive_read_filter_ahead(filter, 6, NULL); if (buffer == NULL) return (0); @@ -237,14 +234,13 @@ lzma_bidder_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) { const unsigned char *buffer; - ssize_t avail; uint32_t dicsize; uint64_t uncompressed_size; int bits_checked; (void)self; /* UNUSED */ - buffer = __archive_read_filter_ahead(filter, 14, &avail); + buffer = __archive_read_filter_ahead(filter, 14, NULL); if (buffer == NULL) return (0); @@ -343,11 +339,10 @@ static int lzip_has_member(struct archive_read_filter *filter) { const unsigned char *buffer; - ssize_t avail; int bits_checked; int log2dic; - buffer = __archive_read_filter_ahead(filter, 6, &avail); + buffer = __archive_read_filter_ahead(filter, 6, NULL); if (buffer == NULL) return (0); @@ -526,6 +521,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self) free(state->out_block); free(state); self->data = NULL; + self->vtable = NULL; return (ARCHIVE_FATAL); } @@ -536,12 +532,11 @@ lzip_init(struct archive_read_filter *self) const unsigned char *h; lzma_filter filters[2]; unsigned char props[5]; - ssize_t avail_in; uint32_t dicsize; int log2dic, ret; state = (struct private_data *)self->data; - h = __archive_read_filter_ahead(self->upstream, 6, &avail_in); + h = __archive_read_filter_ahead(self->upstream, 6, NULL); if (h == NULL) return (ARCHIVE_FATAL); @@ -706,7 +701,6 @@ xz_filter_read(struct archive_read_filter *self, const void **p) } decompressed = state->stream.next_out - state->out_block; - state->total_out += decompressed; state->member_out += decompressed; if (decompressed == 0) { if (member_in != state->member_in && diff --git a/libarchive/archive_read_support_filter_zstd.c b/libarchive/archive_read_support_filter_zstd.c index da7c540dbcd9..100c2c10ddb1 100644 --- a/libarchive/archive_read_support_filter_zstd.c +++ b/libarchive/archive_read_support_filter_zstd.c @@ -48,6 +48,7 @@ #include "archive.h" #include "archive_endian.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" @@ -57,7 +58,6 @@ struct private_data { ZSTD_DStream *dstream; unsigned char *out_block; size_t out_block_size; - int64_t total_out; char in_frame; /* True = in the middle of a zstd frame. */ char eof; /* True = found end of compressed data. */ }; @@ -70,8 +70,7 @@ static int zstd_filter_close(struct archive_read_filter *); /* * Note that we can detect zstd compressed files even if we can't decompress * them. (In fact, we like detecting them because we can give better error - * messages.) So the bid framework here gets compiled even if no zstd library - * is available. + * messages.) */ static int zstd_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); @@ -110,55 +109,77 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self, { const unsigned char *buffer; ssize_t avail; + /* + * Zstandard skippable frames contain a 4 byte magic number followed + * by a 4 byte frame data size, then that number of bytes of data. + * Regular frames contain a 4 byte magic number followed by a 2-14 + * byte frame header, some data, and a 3 byte end marker. + */ + const size_t min_zstd_frame_size = 8; - // Zstandard skippable frames contain a 4 byte magic number followed by - // a 4 byte frame data size, then that number of bytes of data. Regular - // frames contain a 4 byte magic number followed by a 2-14 byte frame - // header, some data, and a 3 byte end marker. - ssize_t min_zstd_frame_size = 8; + size_t offset_in_buffer = 0; + const size_t max_lookahead = 64 * 1024; + uint32_t magic_number; - ssize_t offset_in_buffer = 0; - ssize_t max_lookahead = 64 * 1024; + /* Zstd regular frame magic number. */ + const uint32_t zstd_magic = 0xFD2FB528U; - // Zstd regular frame magic number. - uint32_t zstd_magic = 0xFD2FB528U; + /* + * Note: Zstd and LZ4 skippable frame magic numbers are identical. + * To differentiate these two, we need to look for a non-skippable + * frame. + */ + const uint32_t zstd_magic_skippable_start = 0x184D2A50; + const uint32_t zstd_magic_skippable_mask = 0xFFFFFFF0; - // Note: Zstd and LZ4 skippable frame magic numbers are identical. - // To differentiate these two, we need to look for a non-skippable - // frame. - uint32_t zstd_magic_skippable_start = 0x184D2A50; - uint32_t zstd_magic_skippable_mask = 0xFFFFFFF0; + (void) self; /* UNUSED */ - (void) self; // UNUSED - - buffer = __archive_read_filter_ahead(filter, min_zstd_frame_size, &avail); + buffer = __archive_read_filter_ahead(filter, min_zstd_frame_size, + &avail); if (buffer == NULL) return (0); - uint32_t magic_number = archive_le32dec(buffer); + magic_number = archive_le32dec(buffer); - while ((magic_number & zstd_magic_skippable_mask) == zstd_magic_skippable_start) { + while ((magic_number & zstd_magic_skippable_mask) == + zstd_magic_skippable_start) { + size_t min; + uint32_t frame_data_size; - offset_in_buffer += 4; // Skip over the magic number + /* Skip over the magic number */ + offset_in_buffer += 4; - // Ensure that we can read another 4 bytes. - if (offset_in_buffer + 4 > avail) { - buffer = __archive_read_filter_ahead(filter, offset_in_buffer + 4, &avail); + /* Ensure that we can read another 4 bytes. */ + if (offset_in_buffer + 4 > (size_t)avail) { + buffer = __archive_read_filter_ahead(filter, + offset_in_buffer + 4, &avail); if (buffer == NULL) return (0); } - uint32_t frame_data_size = archive_le32dec(buffer + offset_in_buffer); + frame_data_size = archive_le32dec(buffer + offset_in_buffer); + + /* Skip over the 4 frame data size bytes */ + offset_in_buffer += 4; - // Skip over the 4 frame data size bytes, plus the value stored there. - offset_in_buffer += 4 + frame_data_size; + /* Skip over the value stored there. */ + if (archive_ckd_add_size(&offset_in_buffer, + offset_in_buffer, frame_data_size)) + return (0); - // There should be at least one more frame if this is zstd data. - if (offset_in_buffer + min_zstd_frame_size > avail) { - if (offset_in_buffer + min_zstd_frame_size > max_lookahead) + /* + * There should be at least one more frame + * if this is zstd data. + */ + if (archive_ckd_add_size(&min, + offset_in_buffer, min_zstd_frame_size)) + return (0); + if (min > (size_t)avail) { + if (min > max_lookahead) return (0); - buffer = __archive_read_filter_ahead(filter, offset_in_buffer + min_zstd_frame_size, &avail); + buffer = __archive_read_filter_ahead(filter, + min, &avail); if (buffer == NULL) return (0); } @@ -166,8 +187,10 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self, magic_number = archive_le32dec(buffer + offset_in_buffer); } - // We have skipped over any skippable frames. Either a regular zstd frame - // follows, or this isn't zstd data. + /* + * We have skipped over any skippable frames. Either a regular zstd + * frame follows, or this isn't zstd data. + */ if (magic_number == zstd_magic) return (offset_in_buffer + 4); @@ -179,7 +202,7 @@ zstd_bidder_bid(struct archive_read_filter_bidder *self, /* * If we don't have the library on this system, we can't do the - * decompression directly. We can, however, try to run "zstd -d" + * decompression directly. We can, however, try to run "zstd -d -qq" * in case that's available. */ static int @@ -310,7 +333,6 @@ zstd_filter_read(struct archive_read_filter *self, const void **p) } decompressed = out.pos; - state->total_out += decompressed; if (decompressed == 0) *p = NULL; else diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c index 8926ac50a1ed..0b476edd6691 100644 --- a/libarchive/archive_read_support_format_7zip.c +++ b/libarchive/archive_read_support_format_7zip.c @@ -67,6 +67,7 @@ #define SFX_MIN_ADDR 0x27000 #define SFX_MAX_ADDR 0x60000 #define SFX_MAX_OFFSET (SFX_MAX_ADDR - SFX_MIN_ADDR) +#define SFX_MAX_SEEK 0x800000 /* * PE format @@ -174,7 +175,7 @@ struct _7z_digests { struct _7z_folder { uint64_t numCoders; struct _7z_coder { - unsigned long codec; + uint64_t codec; uint64_t numInStreams; uint64_t numOutStreams; uint64_t propertiesSize; @@ -334,7 +335,7 @@ struct _7zip { int stream_valid; #endif /* Decoding Zstandard data. */ -#if HAVE_ZSTD_H +#if HAVE_ZSTD_H && HAVE_LIBZSTD ZSTD_DStream *zstd_dstream; int zstdstream_valid; #endif @@ -345,12 +346,10 @@ struct _7zip { IByteIn bytein; struct { const unsigned char *next_in; - int64_t avail_in; - int64_t total_in; - int64_t stream_in; + size_t avail_in; + size_t stream_in; unsigned char *next_out; - int64_t avail_out; - int64_t total_out; + size_t avail_out; int overconsumed; } ppstream; int ppmd7_valid; @@ -398,6 +397,27 @@ struct _7zip { * the files. */ #define UMAX_ENTRY ARCHIVE_LITERAL_ULL(100000000) +/* + * Files without unpack streams must be described by the EmptyStream bitmap, + * which consumes one bit for every file entry in FilesInfo. + */ +static int +files_info_numfiles_is_sane(const struct _7zip *zip) +{ + uint64_t empty_stream_map_bytes; + + if (zip->numFiles > UMAX_ENTRY) + return (0); + if (zip->numFiles > SIZE_MAX / sizeof(*zip->entries)) + return (0); + + if (zip->numFiles <= zip->si.ss.unpack_streams) + return (1); + + empty_stream_map_bytes = (zip->numFiles + 7) / 8; + return (empty_stream_map_bytes <= zip->header_bytes_remaining); +} + static int archive_read_format_7zip_has_encrypted_entries(struct archive_read *); static int archive_read_support_format_7zip_capabilities(struct archive_read *a); static int archive_read_format_7zip_bid(struct archive_read *, int); @@ -407,8 +427,8 @@ static int archive_read_format_7zip_read_data(struct archive_read *, static int archive_read_format_7zip_read_data_skip(struct archive_read *); static int archive_read_format_7zip_read_header(struct archive_read *, struct archive_entry *); -static int check_7zip_header_in_sfx(const char *); -static unsigned long decode_codec_id(const unsigned char *, size_t); +static int check_7zip_header_in_sfx(const unsigned char *); +static int decode_codec_id(const unsigned char *, size_t, uint64_t *); static int decode_encoded_header_info(struct archive_read *, struct _7z_stream_info *); static int decompress(struct archive_read *, struct _7zip *, @@ -449,9 +469,9 @@ static ssize_t read_stream(struct archive_read *, const void **, size_t, size_t); static int seek_pack(struct archive_read *); static int64_t skip_stream(struct archive_read *, size_t); -static int skip_sfx(struct archive_read *, const ssize_t); -static ssize_t find_pe_overlay(struct archive_read *); -static ssize_t find_elf_data_sec(struct archive_read *); +static int get_data_offset(struct archive_read *, int64_t *, int); +static int get_pe_sfx_offset(struct archive_read *, int64_t *); +static int get_elf_sfx_offset(struct archive_read *, int64_t *, int); static int slurp_central_directory(struct archive_read *, struct _7zip *, struct _7z_header_info *); static int setup_decode_folder(struct archive_read *, struct _7z_folder *, @@ -464,6 +484,7 @@ static size_t arm64_Convert(struct _7zip *, uint8_t *, size_t); static ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t); static size_t sparc_Convert(struct _7zip *, uint8_t *, size_t); static size_t powerpc_Convert(struct _7zip *, uint8_t *, size_t); +static int64_t seek_compat(struct archive_read *, int64_t, int, int); int @@ -530,64 +551,92 @@ archive_read_format_7zip_has_encrypted_entries(struct archive_read *_a) } static int -archive_read_format_7zip_bid(struct archive_read *a, int best_bid) +get_data_offset(struct archive_read *a, int64_t *data_offset, int compat) { - const char *p; - - /* If someone has already bid more than 32, then avoid - trashing the look-ahead buffers with a seek. */ - if (best_bid > 32) - return (-1); + const unsigned char *p; + int64_t offset, sfx_offset; + int r, window; - if ((p = __archive_read_ahead(a, 6, NULL)) == NULL) - return (0); + if ((p = __archive_read_ahead(a, 6, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } /* If first six bytes are the 7-Zip signature, - * return the bid right now. */ - if (memcmp(p, _7ZIP_SIGNATURE, 6) == 0) - return (48); + * return the offset right now. */ + if (memcmp(p, _7ZIP_SIGNATURE, 6) == 0) { + *data_offset = 0; + return (ARCHIVE_OK); + } /* - * It may a 7-Zip SFX archive file. If first two bytes are - * 'M' and 'Z' available on Windows or first four bytes are - * "\x7F\x45LF" available on posix like system, seek the 7-Zip - * signature. While find_pe_overlay can be performed without - * performing a seek, find_elf_data_sec requires one, + * It may be a 7-Zip SFX archive file. If first two bytes are + * 'M' and 'Z' (PE, Windows) or first four bytes are + * "\x7F\x45LF" (ELF, Posix-like systems), seek the 7-Zip + * signature. While get_pe_sfx_offset can be performed without + * performing a seek, get_elf_sfx_offset requires one, * thus a performance difference between the two is expected. */ - if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) { - const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) : - find_elf_data_sec(a); - ssize_t offset = min_addr; - ssize_t window = 4096; + if ((p[0] == 'M' && p[1] == 'Z')) + r = get_pe_sfx_offset(a, &sfx_offset); + else if (memcmp(p, "\x7F\x45LF", 4) == 0) + r = get_elf_sfx_offset(a, &sfx_offset, compat); + else + r = ARCHIVE_FATAL; + if (r < ARCHIVE_WARN || sfx_offset > SFX_MAX_SEEK) + goto fail; + + offset = sfx_offset; + window = 4096; + while (offset + window <= (sfx_offset + SFX_MAX_OFFSET)) { ssize_t bytes_avail; - while (offset + window <= (min_addr + SFX_MAX_OFFSET)) { - const char *buff = __archive_read_ahead(a, - offset + window, &bytes_avail); - if (buff == NULL) { - /* Remaining bytes are less than window. */ - window >>= 1; - if (window < 0x40) - return (0); - continue; - } - p = buff + offset; - while (p + 32 < buff + bytes_avail) { - int step = check_7zip_header_in_sfx(p); - if (step == 0) - return (48); - p += step; + const unsigned char *buff = __archive_read_ahead(a, + offset + window, &bytes_avail); + if (buff == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 0x40) + goto fail; + continue; + } + p = buff + offset; + while (p + 32 < buff + bytes_avail) { + int step = check_7zip_header_in_sfx(p); + if (step == 0) { + *data_offset = p - buff; + return (ARCHIVE_OK); } - offset = p - buff; + p += step; } + offset = p - buff; } - return (0); +fail: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out 7-Zip header"); + return (ARCHIVE_FATAL); } static int -check_7zip_header_in_sfx(const char *p) +archive_read_format_7zip_bid(struct archive_read *a, int best_bid) { - switch ((unsigned char)p[5]) { + int64_t data_offset; + + /* If someone has already bid more than 32, then avoid + trashing the look-ahead buffers with a seek. */ + if (best_bid > 32) + return (-1); + + if (get_data_offset(a, &data_offset, 0) < 0) + return (0); + + return (48); +} + +static int +check_7zip_header_in_sfx(const unsigned char *p) +{ + switch (p[5]) { case 0x1C: if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0) return (6); @@ -596,8 +645,7 @@ check_7zip_header_in_sfx(const char *p) * Magic Code, so we should do this in order not to * make a mis-detection. */ - if (crc32(0, (const unsigned char *)p + 12, 20) - != archive_le32dec(p + 8)) + if (crc32(0, p + 12, 20) != archive_le32dec(p + 8)) return (6); /* Hit the header! */ return (0); @@ -611,79 +659,33 @@ check_7zip_header_in_sfx(const char *p) } static int -skip_sfx(struct archive_read *a, const ssize_t min_addr) -{ - const void *h; - const char *p, *q; - size_t skip, offset; - ssize_t bytes, window; - - if (__archive_read_seek(a, min_addr, SEEK_SET) < 0) - return (ARCHIVE_FATAL); - - offset = 0; - window = 1; - while (offset + window <= SFX_MAX_ADDR - SFX_MIN_ADDR) { - h = __archive_read_ahead(a, window, &bytes); - if (h == NULL) { - /* Remaining bytes are less than window. */ - window >>= 1; - if (window < 0x40) - goto fatal; - continue; - } - if (bytes < 6) { - /* This case might happen when window == 1. */ - window = 4096; - continue; - } - p = (const char *)h; - q = p + bytes; - - /* - * Scan ahead until we find something that looks - * like the 7-Zip header. - */ - while (p + 32 < q) { - int step = check_7zip_header_in_sfx(p); - if (step == 0) { - struct _7zip *zip = - (struct _7zip *)a->format->data; - skip = p - (const char *)h; - __archive_read_consume(a, skip); - zip->seek_base = min_addr + offset + skip; - return (ARCHIVE_OK); - } - p += step; - } - skip = p - (const char *)h; - __archive_read_consume(a, skip); - offset += skip; - if (window == 1) - window = 4096; - } -fatal: - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Couldn't find out 7-Zip header"); - return (ARCHIVE_FATAL); -} - -static ssize_t -find_pe_overlay(struct archive_read *a) +get_pe_sfx_offset(struct archive_read *a, int64_t *sfx_offset) { const char *h; - ssize_t bytes, max_offset, offset, sec_end; - ssize_t opt_hdr_sz, sec_cnt; + int64_t max_offset, offset; + ssize_t bytes; + uint16_t opt_hdr_sz, sec_cnt; + + /* + * If encounter any weirdness, revert to old brute-force style search + */ + *sfx_offset = SFX_MIN_ADDR; for (;;) { /* * Read Dos header to find e_lfanew */ h = __archive_read_ahead(a, PE_DOS_HDR_LEN, &bytes); - if (h == NULL || h[0] != 'M' || h[1] != 'Z') { + if (h == NULL) { + return (ARCHIVE_FATAL); + } + if (h[0] != 'M' || h[1] != 'Z') { break; } offset = archive_le32dec(h + PE_DOS_HDR_ELFANEW_OFFSET); + if (offset > SFX_MAX_SEEK) { + return (ARCHIVE_FATAL); + } /* * Read COFF header to find opt header size and sec cnt @@ -691,8 +693,10 @@ find_pe_overlay(struct archive_read *a) if (bytes < offset + PE_COFF_HDR_LEN) { h = __archive_read_ahead(a, offset + PE_COFF_HDR_LEN, &bytes); - if (h == NULL || h[offset] != 'P' || - h[offset + 1] != 'E') { + if (h == NULL) { + return (ARCHIVE_FATAL); + } + if (h[offset] != 'P' || h[offset + 1] != 'E') { break; } } @@ -710,6 +714,10 @@ find_pe_overlay(struct archive_read *a) break; } + if (offset + sec_cnt * PE_SEC_HDR_LEN > SFX_MAX_SEEK) { + return (ARCHIVE_FATAL); + } + /* * Traverse sec table to find max raw offset (i.e., overlay) */ @@ -717,12 +725,14 @@ find_pe_overlay(struct archive_read *a) h = __archive_read_ahead(a, offset + sec_cnt * PE_SEC_HDR_LEN, NULL); if (h == NULL) { - break; + return (ARCHIVE_FATAL); } } max_offset = offset; while (sec_cnt > 0) { - sec_end = archive_le32dec( + int64_t sec_end; + + sec_end = (int64_t)archive_le32dec( h + offset + PE_SEC_HDR_RAW_SZ_OFFSET) + archive_le32dec( h + offset + PE_SEC_HDR_RAW_ADDR_OFFSET); @@ -732,34 +742,40 @@ find_pe_overlay(struct archive_read *a) offset += PE_SEC_HDR_LEN; sec_cnt--; } - return (max_offset); + *sfx_offset = max_offset; + break; } - /* - * If encounter any weirdness, revert to old brute-force style search - */ - return (SFX_MIN_ADDR); + return (ARCHIVE_OK); } -static ssize_t -find_elf_data_sec(struct archive_read *a) +static int +get_elf_sfx_offset(struct archive_read *a, int64_t *sfx_offset, int compat) { + int64_t r; const char *h; char big_endian, format_64; - ssize_t bytes, min_addr = SFX_MIN_ADDR; - ssize_t request; + size_t request; uint64_t e_shoff, strtab_offset, strtab_size; uint16_t e_shentsize, e_shnum, e_shstrndx; uint16_t (*dec16)(const void *); uint32_t (*dec32)(const void *); uint64_t (*dec64)(const void *); + /* + * If encounter any weirdness, revert to old brute-force style search + */ + *sfx_offset = SFX_MIN_ADDR; + for (;;) { /* * Read Elf header to find bitness & endianness */ - h = __archive_read_ahead(a, ELF_HDR_MIN_LEN, &bytes); - if (h == NULL || memcmp(h, "\x7F\x45LF", 4) != 0) { + h = __archive_read_ahead(a, ELF_HDR_MIN_LEN, NULL); + if (h == NULL) { + return (ARCHIVE_FATAL); + } + if (memcmp(h, "\x7F\x45LF", 4) != 0) { break; } format_64 = h[ELF_HDR_EI_CLASS_OFFSET] == 0x2; @@ -794,20 +810,28 @@ find_elf_data_sec(struct archive_read *a) break; } + if ((int64_t)e_shoff < 0) { + return (ARCHIVE_FATAL); + } + /* * Reading the section table to find strtab section */ - if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) { - break; + if (seek_compat(a, e_shoff, SEEK_SET, compat) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); + return (ARCHIVE_FATAL); } if (format_64) { - request = (size_t)e_shnum * (size_t)e_shentsize + 0x28; + request = (size_t)e_shnum * e_shentsize + 0x28; } else { - request = (size_t)e_shnum * (size_t)e_shentsize + 0x18; + request = (size_t)e_shnum * e_shentsize + 0x18; } - h = __archive_read_ahead(a, request, &bytes); + if (request > SFX_MAX_SEEK) { + return (ARCHIVE_FATAL); + } + h = __archive_read_ahead(a, request, NULL); if (h == NULL) { - break; + return (ARCHIVE_FATAL); } if (format_64) { strtab_offset = (*dec64)( @@ -820,45 +844,50 @@ find_elf_data_sec(struct archive_read *a) strtab_size = (*dec32)( h + e_shstrndx * e_shentsize + 0x14); } - if (strtab_size < 6 || strtab_size > SIZE_MAX) - break; + if ((int64_t)strtab_offset < 0 || strtab_size < 6 || + strtab_size > SFX_MAX_SEEK) + return (ARCHIVE_FATAL); /* * Read the STRTAB section to find the .data offset */ - if (__archive_read_seek(a, strtab_offset, SEEK_SET) < 0) { - break; + if (seek_compat(a, strtab_offset, SEEK_SET, compat) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); + return (ARCHIVE_FATAL); } h = __archive_read_ahead(a, strtab_size, NULL); if (h == NULL) { - break; + return (ARCHIVE_FATAL); } - ssize_t data_sym_offset = -1; + size_t data_sym_offset = strtab_size; for (size_t offset = 0; offset < strtab_size - 6; offset++) { if (memcmp(h + offset, ".data\00", 6) == 0) { data_sym_offset = offset; break; } } - if (data_sym_offset == -1) { + if (data_sym_offset == strtab_size) { break; } /* * Find the section with the .data name */ - if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) { - break; + if (seek_compat(a, e_shoff, SEEK_SET, compat) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); + return (ARCHIVE_FATAL); } - h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL); + h = __archive_read_ahead(a, (size_t)e_shnum * e_shentsize, NULL); if (h == NULL) { - break; + return (ARCHIVE_FATAL); } - ssize_t sec_tbl_offset = 0, name_offset; + size_t sec_tbl_offset = 0; while (e_shnum > 0) { + uint32_t name_offset; + name_offset = (*dec32)(h + sec_tbl_offset); if (name_offset == data_sym_offset) { - uint64_t sel_offset; + int64_t sel_offset; if (format_64) { sel_offset = (*dec64)( @@ -867,9 +896,8 @@ find_elf_data_sec(struct archive_read *a) sel_offset = (*dec32)( h + sec_tbl_offset + 0x10); } - if (sel_offset > SSIZE_MAX) - break; - min_addr = (ssize_t)sel_offset; + if (sel_offset >= 0) + *sfx_offset = sel_offset; break; } sec_tbl_offset += e_shentsize; @@ -878,8 +906,10 @@ find_elf_data_sec(struct archive_read *a) break; } - __archive_read_seek(a, 0, SEEK_SET); - return (min_addr); + r = seek_compat(a, 0, SEEK_SET, compat); + if (r < 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); + return (int)r; } static int @@ -1004,29 +1034,19 @@ archive_read_format_7zip_read_header(struct archive_read *a, const int supported_attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM; if (zip_entry->attr & supported_attrs) { - char *fflags_text, *ptr; - /* allocate for ",rdonly,hidden,system" */ - fflags_text = malloc(22 * sizeof(*fflags_text)); - if (fflags_text != NULL) { - ptr = fflags_text; - if (zip_entry->attr & FILE_ATTRIBUTE_READONLY) { - strcpy(ptr, ",rdonly"); - ptr = ptr + 7; - } - if (zip_entry->attr & FILE_ATTRIBUTE_HIDDEN) { - strcpy(ptr, ",hidden"); - ptr = ptr + 7; - } - if (zip_entry->attr & FILE_ATTRIBUTE_SYSTEM) { - strcpy(ptr, ",system"); - ptr = ptr + 7; - } - if (ptr > fflags_text) { - archive_entry_copy_fflags_text(entry, - fflags_text + 1); - } - free(fflags_text); - } + char buf[sizeof(",rdonly,hidden,system")]; + char *fflags[3] = { "", "", "" }; + char **flag = fflags; + + if (zip_entry->attr & FILE_ATTRIBUTE_READONLY) + *flag++ = ",rdonly"; + if (zip_entry->attr & FILE_ATTRIBUTE_HIDDEN) + *flag++ = ",hidden"; + if (zip_entry->attr & FILE_ATTRIBUTE_SYSTEM) + *flag++ = ",system"; + + snprintf(buf, sizeof(buf), "%s%s%s", fflags[0], fflags[1], fflags[2]); + archive_entry_copy_fflags_text(entry, buf + 1); } /* If there's no body, force read_data() to return EOF immediately. */ @@ -1037,6 +1057,13 @@ archive_read_format_7zip_read_header(struct archive_read *a, unsigned char *symname = NULL; size_t symsize = 0; + if (zip->entry_bytes_remaining > 1024 * 1024) { + archive_set_error(&a->archive, ENOMEM, + "Rejecting malformed 7zip archive: " + "symlink contents exceed 1 megabyte"); + return (ARCHIVE_FATAL); + } + /* * Symbolic-name is recorded as its contents. We have to * read the contents at this time. @@ -1189,7 +1216,7 @@ archive_read_format_7zip_read_data_skip(struct archive_read *a) */ bytes_skipped = skip_stream(a, (size_t)zip->entry_bytes_remaining); if (bytes_skipped < 0) - return (ARCHIVE_FATAL); + return ((int)bytes_skipped); zip->entry_bytes_remaining = 0; /* This entry is finished and done. */ @@ -1281,17 +1308,20 @@ set_error(struct archive_read *a, int ret) #endif -static unsigned long -decode_codec_id(const unsigned char *codecId, size_t id_size) +static int +decode_codec_id(const unsigned char *codecId, size_t id_size, uint64_t *id) { unsigned i; - unsigned long id = 0; + uint64_t v = 0; for (i = 0; i < id_size; i++) { - id <<= 8; - id += codecId[i]; + if (v > (uint64_t)INT64_MAX / 256) + return (-1); + v <<= 8; + v += codecId[i]; } - return (id); + *id = v; + return (0); } static Byte @@ -1301,29 +1331,26 @@ ppmd_read(void *p) struct _7zip *zip = (struct _7zip *)(a->format->data); Byte b; - if (zip->ppstream.avail_in <= 0) { + if (zip->ppstream.avail_in == 0) { /* * Ppmd7_DecodeSymbol might require reading multiple bytes * and we are on boundary; * last resort to read using __archive_read_ahead. */ - ssize_t bytes_avail = 0; const uint8_t* data = __archive_read_ahead(a, - (size_t)zip->ppstream.stream_in+1, &bytes_avail); - if(data == NULL || bytes_avail < zip->ppstream.stream_in+1) { + zip->ppstream.stream_in + 1, NULL); + if (data == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated 7z file data"); zip->ppstream.overconsumed = 1; return (0); } - zip->ppstream.next_in++; b = data[zip->ppstream.stream_in]; } else { b = *zip->ppstream.next_in++; + zip->ppstream.avail_in--; } - zip->ppstream.avail_in--; - zip->ppstream.total_in++; zip->ppstream.stream_in++; return (b); } @@ -1352,8 +1379,9 @@ init_decompression(struct archive_read *a, struct _7zip *zip, coder2->codec != _7Z_SPARC) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Unsupported filter %lx for %lx", - coder2->codec, coder1->codec); + "Unsupported filter %jx for %jx", + (uintmax_t)coder2->codec, + (uintmax_t)coder1->codec); return (ARCHIVE_FAILED); } zip->codec2 = coder2->codec; @@ -1558,7 +1586,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip, #endif case _7Z_ZSTD: { -#if defined(HAVE_ZSTD_H) +#if HAVE_ZSTD_H && HAVE_LIBZSTD if (zip->zstdstream_valid) { ZSTD_freeDStream(zip->zstd_dstream); zip->zstdstream_valid = 0; @@ -1632,8 +1660,6 @@ init_decompression(struct archive_read *a, struct _7zip *zip, zip->ppmd7_valid = 1; zip->ppmd7_stat = 0; zip->ppstream.overconsumed = 0; - zip->ppstream.total_in = 0; - zip->ppstream.total_out = 0; break; } case _7Z_X86: @@ -1840,7 +1866,7 @@ decompress(struct archive_read *a, struct _7zip *zip, t_avail_out = zip->stream.avail_out; break; #endif -#ifdef HAVE_ZSTD_H +#if HAVE_ZSTD_H && HAVE_LIBZSTD case _7Z_ZSTD: { ZSTD_inBuffer input = { t_next_in, t_avail_in, 0 }; // src, size, pos @@ -1916,14 +1942,13 @@ decompress(struct archive_read *a, struct _7zip *zip, } *zip->ppstream.next_out++ = (unsigned char)sym; zip->ppstream.avail_out--; - zip->ppstream.total_out++; if (flush_bytes) flush_bytes--; } while (zip->ppstream.avail_out && (zip->ppstream.avail_in || flush_bytes)); - t_avail_in = (size_t)zip->ppstream.avail_in; - t_avail_out = (size_t)zip->ppstream.avail_out; + t_avail_in = zip->ppstream.avail_in; + t_avail_out = zip->ppstream.avail_out; break; } default: @@ -2027,7 +2052,7 @@ free_decompression(struct archive_read *a, struct _7zip *zip) zip->stream_valid = 0; } #endif -#ifdef HAVE_ZSTD_H +#if HAVE_ZSTD_H && HAVE_LIBZSTD if (zip->zstdstream_valid) ZSTD_freeDStream(zip->zstd_dstream); #endif @@ -2279,7 +2304,8 @@ read_Folder(struct archive_read *a, struct _7z_folder *f) if ((p = header_bytes(a, codec_size)) == NULL) return (-1); - f->coders[i].codec = decode_codec_id(p, codec_size); + if (decode_codec_id(p, codec_size, &f->coders[i].codec) < 0) + return (-1); if (simple) { f->coders[i].numInStreams = 1; @@ -2543,9 +2569,8 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss, for (i = 0; i < numFolders; i++) { if (parse_7zip_uint64(a, &(f[i].numUnpackStreams)) < 0) return (-1); - if (UMAX_ENTRY < f[i].numUnpackStreams) - return (-1); - if (unpack_streams > SIZE_MAX - UMAX_ENTRY) { + if (f[i].numUnpackStreams > + UMAX_ENTRY - unpack_streams) { return (-1); } unpack_streams += (size_t)f[i].numUnpackStreams; @@ -2556,6 +2581,13 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss, } else unpack_streams = numFolders; + if (type != kSize) { + for (i = 0; i < numFolders; i++) { + if (f[i].numUnpackStreams > 1) + return (-1); + } + } + ss->unpack_streams = unpack_streams; if (unpack_streams) { ss->unpackSizes = calloc(unpack_streams, @@ -2599,11 +2631,6 @@ read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss, type = *p; } - for (i = 0; i < unpack_streams; i++) { - ss->digestsDefined[i] = 0; - ss->digests[i] = 0; - } - numDigests = 0; for (i = 0; i < numFolders; i++) { if (f[i].numUnpackStreams != 1 || !f[i].digest_defined) @@ -2806,7 +2833,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if (parse_7zip_uint64(a, &(zip->numFiles)) < 0) return (-1); - if (UMAX_ENTRY < zip->numFiles) + if (!files_info_numfiles_is_sane(zip)) return (-1); zip->entries = calloc((size_t)zip->numFiles, sizeof(*zip->entries)); @@ -2828,7 +2855,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if (parse_7zip_uint64(a, &size) < 0) return (-1); - if (zip->header_bytes_remaining < size) + if (zip->header_bytes_remaining < size || size > SIZE_MAX / 4) return (-1); ll = (size_t)size; @@ -3235,22 +3262,22 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, uint64_t next_header_size; uint32_t next_header_crc; ssize_t bytes_avail; + int64_t data_offset; int check_header_crc, r; - if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) + if (get_data_offset(a, &data_offset, 1) < 0) + return (ARCHIVE_FATAL); + if (__archive_read_consume(a, data_offset) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); return (ARCHIVE_FATAL); - - if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) { - /* This is an executable ? Must be self-extracting... */ - const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) : - find_elf_data_sec(a); - r = skip_sfx(a, min_addr); - if (r < ARCHIVE_WARN) - return (r); - if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) - return (ARCHIVE_FATAL); } - zip->seek_base += 32; + if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file header"); + return (ARCHIVE_FATAL); + } + + zip->seek_base = (uint64_t)data_offset + 32; if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0) { archive_set_error(&a->archive, -1, "Not 7-Zip archive file"); @@ -3258,7 +3285,7 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, } /* CRC check. */ - if (crc32(0, (const unsigned char *)p + 12, 20) + if (crc32(0, p + 12, 20) != archive_le32dec(p + 8)) { #ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, -1, "Header CRC error"); @@ -3282,9 +3309,11 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip, if (next_header_offset != 0) { if (bytes_avail >= (ssize_t)next_header_offset) __archive_read_consume(a, next_header_offset); - else if (__archive_read_seek(a, - next_header_offset + zip->seek_base, SEEK_SET) < 0) + else if (seek_compat(a, + next_header_offset + zip->seek_base, SEEK_SET, 1) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); return (ARCHIVE_FATAL); + } } zip->stream_offset = next_header_offset; zip->header_offset = next_header_offset; @@ -3620,9 +3649,11 @@ seek_pack(struct archive_read *a) zip->si.pi.sizes[zip->pack_stream_index]; pack_offset = zip->si.pi.positions[zip->pack_stream_index]; if (zip->stream_offset != pack_offset) { - if (0 > __archive_read_seek(a, pack_offset + zip->seek_base, - SEEK_SET)) + if (0 > seek_compat(a, pack_offset + zip->seek_base, + SEEK_SET, 1)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek error"); return (ARCHIVE_FATAL); + } zip->stream_offset = pack_offset; } zip->pack_stream_index++; @@ -3688,7 +3719,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size, r = setup_decode_folder(a, &(zip->si.ci.folders[zip->folder_index]), 0); if (r != ARCHIVE_OK) - return (ARCHIVE_FATAL); + return (r); zip->folder_index++; } @@ -3763,15 +3794,9 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, } /* - * Initialize a stream reader. - */ - zip->pack_stream_remaining = (unsigned)folder->numPackedStreams; - zip->pack_stream_index = (unsigned)folder->packIndex; - zip->folder_outbytes_remaining = folder_uncompressed_size(folder); - zip->uncompressed_buffer_bytes_remaining = 0; - - /* - * Check coder types. + * Check coder types before modifying any stream-reader state, so that + * an early return leaves zip unchanged (avoids partially-initialized + * state that callers would have to reason about). */ for (i = 0; i < folder->numCoders; i++) { switch(folder->coders[i].codec) { @@ -3789,7 +3814,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, ARCHIVE_ERRNO_MISC, "The %s is encrypted, " "but currently not supported", cname); - return (ARCHIVE_FATAL); + return (header ? ARCHIVE_FATAL : ARCHIVE_FAILED); } case _7Z_X86_BCJ2: { found_bcj2++; @@ -3809,8 +3834,16 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, ARCHIVE_ERRNO_MISC, "The %s is encoded with many filters, " "but currently not supported", cname); - return (ARCHIVE_FATAL); + return (header ? ARCHIVE_FATAL : ARCHIVE_FAILED); } + + /* + * Initialize a stream reader. + */ + zip->pack_stream_remaining = (unsigned)folder->numPackedStreams; + zip->pack_stream_index = (unsigned)folder->packIndex; + zip->folder_outbytes_remaining = folder_uncompressed_size(folder); + zip->uncompressed_buffer_bytes_remaining = 0; coder1 = &(folder->coders[0]); if (folder->numCoders == 2) coder2 = &(folder->coders[1]); @@ -3831,6 +3864,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, ssize_t bytes; unsigned char *b[3] = {NULL, NULL, NULL}; uint64_t sunpack[3] ={-1, -1, -1}; + uint64_t remaining; size_t s[3] = {0, 0, 0}; int idx[3] = {0, 1, 2}; @@ -3885,12 +3919,14 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, coder2 = &(fc[3]); zip->main_stream_bytes_remaining = (size_t)folder->unPackSize[2]; + remaining = folder->unPackSize[2]; } else if (coder2 != NULL && coder2->codec == _7Z_X86_BCJ2 && zip->pack_stream_remaining == 4 && folder->numInStreams == 5 && folder->numOutStreams == 2) { /* Source type 0 made by 7z */ zip->main_stream_bytes_remaining = (size_t)folder->unPackSize[0]; + remaining = folder->unPackSize[0]; } else { /* We got an unexpected form. */ archive_set_error(&(a->archive), @@ -3898,6 +3934,15 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, "Unsupported form of BCJ2 streams"); return (ARCHIVE_FATAL); } + if (remaining > SIZE_MAX) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "7-Zip sub-stream size exceeds " + "platform maximum"); + return (ARCHIVE_FATAL); + } + zip->main_stream_bytes_remaining = remaining; + /* Skip the main stream at this time. */ if ((r = seek_pack(a)) < 0) @@ -3929,6 +3974,14 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, /* Allocate memory for the decoded data of a sub * stream. */ + if (zip->folder_outbytes_remaining > SIZE_MAX) { + free(b[0]); free(b[1]); free(b[2]); + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "7-Zip sub-stream size exceeds " + "platform maximum"); + return (ARCHIVE_FATAL); + } b[i] = malloc((size_t)zip->folder_outbytes_remaining); if (b[i] == NULL) { free(b[0]); free(b[1]); free(b[2]); @@ -4101,9 +4154,7 @@ x86_Convert(struct _7zip *zip, uint8_t *data, size_t size) prevPosT = bufferPos; if (Test86MSByte(p[4])) { - uint32_t src = ((uint32_t)p[4] << 24) | - ((uint32_t)p[3] << 16) | ((uint32_t)p[2] << 8) | - ((uint32_t)p[1]); + uint32_t src = archive_le32dec(p + 1); uint32_t dest; for (;;) { uint8_t b; @@ -4163,16 +4214,13 @@ arm_Convert(struct _7zip *zip, uint8_t *buf, size_t size) for (i = 0; i + 4 <= size; i += 4) { if (buf[i + 3] == 0xEB) { // Calculate the transformed addr. - addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8) - | ((uint32_t)buf[i + 2] << 16); + addr = archive_le24dec(buf + i); addr <<= 2; addr -= zip->bcj_ip + (uint32_t)i; addr >>= 2; // Store the transformed addr in buf. - buf[i] = (uint8_t)addr; - buf[i + 1] = (uint8_t)(addr >> 8); - buf[i + 2] = (uint8_t)(addr >> 16); + archive_le24enc(buf + i, addr); } } @@ -4203,20 +4251,14 @@ arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size) uint32_t addr; for (i = 0; i + 4 <= size; i += 4) { - instr = (uint32_t)buf[i] - | ((uint32_t)buf[i+1] << 8) - | ((uint32_t)buf[i+2] << 16) - | ((uint32_t)buf[i+3] << 24); + instr = archive_le32dec(buf + i); if ((instr >> 26) == 0x25) { /* BL instruction */ addr = instr - ((zip->bcj_ip + (uint32_t)i) >> 2); instr = 0x94000000 | (addr & 0x03FFFFFF); - buf[i] = (uint8_t)instr; - buf[i+1] = (uint8_t)(instr >> 8); - buf[i+2] = (uint8_t)(instr >> 16); - buf[i+3] = (uint8_t)(instr >> 24); + archive_le32enc(buf + i, instr); } else if ((instr & 0x9F000000) == 0x90000000) { /* ADRP instruction */ addr = ((instr >> 29) & 3) | ((instr >> 3) & 0x1FFFFC); @@ -4232,10 +4274,7 @@ arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size) instr |= (addr & 0x03FFFC) << 3; instr |= (0U - (addr & 0x020000)) & 0xE00000; - buf[i] = (uint8_t)instr; - buf[i+1] = (uint8_t)(instr >> 8); - buf[i+2] = (uint8_t)(instr >> 16); - buf[i+3] = (uint8_t)(instr >> 24); + archive_le32enc(buf + i, instr); } } @@ -4278,10 +4317,7 @@ sparc_Convert(struct _7zip *zip, uint8_t *buf, size_t size) size &= ~(size_t)3; for (i = 0; i < size; i += 4) { - instr = (uint32_t)(buf[i] << 24) - | ((uint32_t)buf[i+1] << 16) - | ((uint32_t)buf[i+2] << 8) - | (uint32_t)buf[i+3]; + instr = archive_be32dec(buf + i); if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) { instr <<= 2; @@ -4290,10 +4326,7 @@ sparc_Convert(struct _7zip *zip, uint8_t *buf, size_t size) instr = ((uint32_t)0x40000000 - (instr & 0x400000)) | 0x40000000 | (instr & 0x3FFFFF); - buf[i] = (uint8_t)(instr >> 24); - buf[i+1] = (uint8_t)(instr >> 16); - buf[i+2] = (uint8_t)(instr >> 8); - buf[i+3] = (uint8_t)instr; + archive_be32enc(buf + i, instr); } } @@ -4504,15 +4537,10 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize) buf2 += 4; size2 -= 4; } - dest = (((uint32_t)v[0] << 24) | - ((uint32_t)v[1] << 16) | - ((uint32_t)v[2] << 8) | - ((uint32_t)v[3])) - + dest = archive_be32dec(v) - ((uint32_t)zip->bcj2_outPos + (uint32_t)outPos + 4); - out[0] = (uint8_t)dest; - out[1] = (uint8_t)(dest >> 8); - out[2] = (uint8_t)(dest >> 16); - out[3] = zip->bcj2_prevByte = (uint8_t)(dest >> 24); + archive_le32enc(out, dest); + zip->bcj2_prevByte = out[3]; for (i = 0; i < 4 && outPos < outSize; i++) outBuf[outPos++] = out[i]; @@ -4538,3 +4566,34 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize) return ((ssize_t)outPos); } + +/* + * Perform a seek to given position. If seeking is not supported, + * target position is in front of current position, and compat is requested, + * try to consume bytes until position is reached. + */ +int64_t +seek_compat(struct archive_read *a, int64_t offset, int whence, int compat) +{ + int64_t ret = ARCHIVE_FAILED; + + if (a->filter->can_seek) + ret = __archive_read_seek(a, offset, whence); + else if (compat) { + switch (whence) { + case SEEK_CUR: + ret = __archive_read_consume(a, offset); + break; + case SEEK_SET: + if (a->filter->position > offset) + break; + ret = __archive_read_consume(a, + offset - a->filter->position); + break; + default: + break; + } + } + + return (ret); +} diff --git a/libarchive/archive_read_support_format_ar.c b/libarchive/archive_read_support_format_ar.c index 6dfe2939d090..5633594405fa 100644 --- a/libarchive/archive_read_support_format_ar.c +++ b/libarchive/archive_read_support_format_ar.c @@ -45,6 +45,7 @@ #include "archive.h" #include "archive_entry.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" @@ -588,24 +589,22 @@ bad_string_table: static uint64_t ar_atol8(const char *p, unsigned char_cnt) { - uint64_t l, limit, last_digit_limit; + uint64_t l; unsigned int digit, base; base = 8; - limit = UINT64_MAX / base; - last_digit_limit = UINT64_MAX % base; while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) p++; l = 0; digit = *p - '0'; - while (*p >= '0' && digit < base && char_cnt-- > 0) { - if (l>limit || (l == limit && digit > last_digit_limit)) { + while (*p >= '0' && digit < base && char_cnt-- > 0) { + if (archive_ckd_mul_u64(&l, l, base) || + archive_ckd_add_u64(&l, l, digit)) { l = UINT64_MAX; /* Truncate on overflow. */ break; } - l = (l * base) + digit; digit = *++p - '0'; } return (l); @@ -614,23 +613,21 @@ ar_atol8(const char *p, unsigned char_cnt) static uint64_t ar_atol10(const char *p, unsigned char_cnt) { - uint64_t l, limit, last_digit_limit; + uint64_t l; unsigned int base, digit; base = 10; - limit = UINT64_MAX / base; - last_digit_limit = UINT64_MAX % base; while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) p++; l = 0; digit = *p - '0'; while (*p >= '0' && digit < base && char_cnt-- > 0) { - if (l > limit || (l == limit && digit > last_digit_limit)) { + if (archive_ckd_mul_u64(&l, l, base) || + archive_ckd_add_u64(&l, l, digit)) { l = UINT64_MAX; /* Truncate on overflow. */ break; } - l = (l * base) + digit; digit = *++p - '0'; } return (l); diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c index bf8ac6b1ca77..bd82b44accc5 100644 --- a/libarchive/archive_read_support_format_cab.c +++ b/libarchive/archive_read_support_format_cab.c @@ -112,8 +112,8 @@ struct lzx_dec { unsigned char *bitlen; /* - * Use a index table. It's faster than searching a huffman - * coding tree, which is a binary tree. But a use of a large + * Use an index table. It's faster than searching a huffman + * coding tree, which is a binary tree. But usage of a large * index table causes L1 cache read miss many times. */ int max_bits; @@ -264,7 +264,7 @@ struct cfheader { }; struct cab { - /* entry_bytes_remaining is the number of bytes we expect. */ + /* entry_bytes_remaining is the number of bytes we expect. */ int64_t entry_offset; int64_t entry_bytes_remaining; int64_t entry_unconsumed; @@ -279,7 +279,7 @@ struct cab { struct cfheader cfheader; struct archive_wstring ws; - /* Flag to mark progress that an archive was read their first header.*/ + /* Flag to mark progress that first header of an archive was read.*/ char found_header; char end_of_archive; char end_of_entry; @@ -433,7 +433,7 @@ archive_read_format_cab_bid(struct archive_read *a, int best_bid) /* * Attempt to handle self-extracting archives * by noting a PE header and searching forward - * up to 128k for a 'MSCF' marker. + * up to 128k for an 'MSCF' marker. */ if (p[0] == 'M' && p[1] == 'Z') { offset = 0; @@ -501,7 +501,7 @@ cab_skip_sfx(struct archive_read *a) for (;;) { const char *h = __archive_read_ahead(a, window, &bytes); if (h == NULL) { - /* Remaining size are less than window. */ + /* Remaining size is less than window. */ window >>= 1; if (window < 128) { archive_set_error(&a->archive, @@ -554,19 +554,18 @@ cab_strnlen(const unsigned char *p, size_t maxlen) return ((ssize_t)i); } -/* Read bytes as much as remaining. */ +/* Read up to max remaining bytes. */ static const void * -cab_read_ahead_remaining(struct archive_read *a, size_t min, ssize_t *avail) +cab_read_ahead_remaining(struct archive_read *a, size_t max, ssize_t *avail) { - const void *p; + const void *p = __archive_read_ahead(a, max, avail); - while (min > 0) { - p = __archive_read_ahead(a, min, avail); - if (p != NULL) - return (p); - min--; - } - return (NULL); + if (p == NULL && *avail > 0) + p = __archive_read_ahead(a, *avail, avail); + if (p != NULL && (size_t)*avail > max) + *avail = max; + + return (p); } /* Convert a path separator '\' -> '/' */ @@ -627,7 +626,7 @@ cab_read_header(struct archive_read *a) struct cab *cab; struct cfheader *hd; size_t bytes, used; - ssize_t len; + ssize_t avail, len; int64_t skip; int err, i; int cur_folder, prev_folder; @@ -691,29 +690,34 @@ cab_read_header(struct archive_read *a) hd->cffolder = 0;/* Avoid compiling warning. */ if (hd->flags & PREV_CABINET) { /* How many bytes are used for szCabinetPrev. */ - if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + if ((p = cab_read_ahead_remaining(a, used + 256, + &avail)) == NULL || (size_t)avail <= used) return (truncated_error(a)); - if ((len = cab_strnlen(p + used, 255)) <= 0) + if ((len = cab_strnlen(p + used, avail - used - 1)) <= 0) { goto invalid; + } used += len + 1; /* How many bytes are used for szDiskPrev. */ - if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + if ((p = cab_read_ahead_remaining(a, used + 256, + &avail)) == NULL || (size_t)avail <= used) return (truncated_error(a)); - if ((len = cab_strnlen(p + used, 255)) <= 0) + if ((len = cab_strnlen(p + used, avail - used - 1)) < 0) goto invalid; used += len + 1; } if (hd->flags & NEXT_CABINET) { /* How many bytes are used for szCabinetNext. */ - if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + if ((p = cab_read_ahead_remaining(a, used + 256, + &avail)) == NULL || (size_t)avail <= used) return (truncated_error(a)); - if ((len = cab_strnlen(p + used, 255)) <= 0) + if ((len = cab_strnlen(p + used, avail - used - 1)) <= 0) goto invalid; used += len + 1; /* How many bytes are used for szDiskNext. */ - if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + if ((p = cab_read_ahead_remaining(a, used + 256, + &avail)) == NULL || (size_t)avail <= used) return (truncated_error(a)); - if ((len = cab_strnlen(p + used, 255)) <= 0) + if ((len = cab_strnlen(p + used, avail - used - 1)) < 0) goto invalid; used += len + 1; } @@ -776,7 +780,7 @@ cab_read_header(struct archive_read *a) */ /* Seek read pointer to the offset of CFFILE if needed. */ skip = (int64_t)hd->files_offset - cab->cab_offset; - if (skip < 0) { + if (skip < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid offset of CFFILE %jd < %jd", (intmax_t)hd->files_offset, (intmax_t)cab->cab_offset); @@ -795,7 +799,6 @@ cab_read_header(struct archive_read *a) prev_folder = -1; for (i = 0; i < hd->file_count; i++) { struct cffile *file = &(hd->file_array[i]); - ssize_t avail; if ((p = __archive_read_ahead(a, 16, NULL)) == NULL) return (truncated_error(a)); @@ -1336,6 +1339,10 @@ cab_next_cfdata(struct archive_read *a) } return (ARCHIVE_OK); invalid: + cfdata->compressed_size = 0; + cfdata->compressed_bytes_remaining = 0; + cfdata->uncompressed_size = 0; + cfdata->uncompressed_bytes_remaining = 0; archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA"); return (ARCHIVE_FATAL); @@ -1478,6 +1485,14 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) cab->uncompressed_buffer + cab->stream.total_out; cab->stream.avail_out = cfdata->uncompressed_size - cab->stream.total_out; + if ((size_t)cfdata->uncompressed_size > + cab->uncompressed_buffer_size) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid CFDATA uncompressed size"); + *avail = ARCHIVE_FATAL; + return (NULL); + } d = __archive_read_ahead(a, 1, &bytes_avail); if (bytes_avail <= 0) { @@ -1565,11 +1580,9 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) * correctly compute the sum of CFDATA accordingly. */ if (cfdata->compressed_bytes_remaining > 0) { - ssize_t bytes_avail; - d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining, - &bytes_avail); - if (bytes_avail <= 0) { + NULL); + if (d == NULL) { *avail = truncated_error(a); return (NULL); } @@ -1737,11 +1750,9 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail) * Make sure a read pointer advances to next CFDATA. */ if (cfdata->compressed_bytes_remaining > 0) { - ssize_t bytes_avail; - d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining, - &bytes_avail); - if (bytes_avail <= 0) { + NULL); + if (d == NULL) { *avail = truncated_error(a); return (NULL); } @@ -3211,6 +3222,10 @@ lzx_make_huffman_table(struct huffman *hf) bitlen = hf->bitlen; len_avail = hf->len_size; hf->tree_used = 0; + /* Initialize table to invalid values */ + for (i = 0; i < tbl_size; i++) { + tbl[i] = (uint16_t)hf->len_size; + } for (i = 0; i < len_avail; i++) { uint16_t *p; int len, cnt; diff --git a/libarchive/archive_read_support_format_cpio.c b/libarchive/archive_read_support_format_cpio.c index 43169f61806d..86d2bc95d53b 100644 --- a/libarchive/archive_read_support_format_cpio.c +++ b/libarchive/archive_read_support_format_cpio.c @@ -38,6 +38,7 @@ #endif #include "archive.h" +#include "archive_endian.h" #include "archive_entry.h" #include "archive_entry_locale.h" #include "archive_private.h" @@ -160,6 +161,8 @@ #define afiol_filesize_c_offset 115 /* ':' */ #define afiol_header_size 116 +/* CPIO name fields store a full pathname, including the terminating NUL. */ +#define CPIO_PATHNAME_MAX (1024 * 1024) struct links_entry { struct links_entry *next; @@ -200,7 +203,7 @@ static int archive_read_format_cpio_read_data(struct archive_read *, static int archive_read_format_cpio_read_header(struct archive_read *, struct archive_entry *); static int archive_read_format_cpio_skip(struct archive_read *); -static int64_t be4(const unsigned char *); +static int64_t be32dec(const unsigned char *); static int find_odc_header(struct archive_read *); static int find_newc_header(struct archive_read *); static int header_bin_be(struct archive_read *, struct cpio *, @@ -215,7 +218,7 @@ static int header_afiol(struct archive_read *, struct cpio *, struct archive_entry *, size_t *, size_t *); static int is_octal(const char *, size_t); static int is_hex(const char *, size_t); -static int64_t le4(const unsigned char *); +static int64_t le32dec(const unsigned char *); static int record_hardlink(struct archive_read *a, struct cpio *cpio, struct archive_entry *entry); @@ -303,12 +306,12 @@ archive_read_format_cpio_bid(struct archive_read *a, int best_bid) * XXX TODO: More verification; Could check that only hex * digits appear in appropriate header locations. XXX */ - } else if (p[0] * 256 + p[1] == 070707) { + } else if (archive_be16dec(p) == 070707) { /* big-endian binary cpio archives */ cpio->read_header = header_bin_be; bid += 16; /* Is more verification possible here? */ - } else if (p[0] + p[1] * 256 == 070707) { + } else if (archive_le16dec(p) == 070707) { /* little-endian binary cpio archives */ cpio->read_header = header_bin_le; bid += 16; @@ -385,8 +388,15 @@ archive_read_format_cpio_read_header(struct archive_read *a, if (r < ARCHIVE_WARN) return (r); + if (namelength > CPIO_PATHNAME_MAX) { + archive_set_error(&a->archive, ENOMEM, + "Rejecting malformed cpio archive: " + "pathname exceeds 1 megabyte"); + return (ARCHIVE_FATAL); + } + /* Read name from buffer. */ - h = __archive_read_ahead(a, namelength + name_pad, NULL); + h = __archive_read_ahead(a, namelength, NULL); if (h == NULL) return (ARCHIVE_FATAL); if (archive_entry_copy_pathname_l(entry, @@ -403,7 +413,8 @@ archive_read_format_cpio_read_header(struct archive_read *a, } cpio->entry_offset = 0; - __archive_read_consume(a, namelength + name_pad); + __archive_read_consume(a, namelength); + __archive_read_consume(a, name_pad); /* If this is a symlink, read the link contents. */ if (archive_entry_filetype(entry) == AE_IFLNK) { @@ -703,13 +714,24 @@ find_odc_header(struct archive_read *a) { const void *h; const char *p, *q; - size_t skip, skipped = 0; + int64_t skip; + uintmax_t skipped = 0; ssize_t bytes; for (;;) { - h = __archive_read_ahead(a, odc_header_size, &bytes); - if (h == NULL) - return (ARCHIVE_FATAL); + size_t header_size; + + header_size = afiol_header_size; + h = __archive_read_ahead(a, afiol_header_size, &bytes); + if (h == NULL) { + if (bytes >= odc_header_size) { + header_size = odc_header_size; + h = __archive_read_ahead(a, odc_header_size, + &bytes); + } + if (h == NULL) + return (ARCHIVE_FATAL); + } p = h; q = p + bytes; @@ -725,7 +747,7 @@ find_odc_header(struct archive_read *a) * Scan ahead until we find something that looks * like an odc header. */ - while (p + odc_header_size <= q) { + while (p + header_size <= q) { switch (p[5]) { case '7': if ((memcmp("070707", p, 6) == 0 @@ -741,9 +763,9 @@ find_odc_header(struct archive_read *a) if (skipped > 0) { archive_set_error(&a->archive, 0, - "Skipped %d bytes before " + "Skipped %ju bytes before " "finding valid header", - (int)skipped); + skipped); return (ARCHIVE_WARN); } return (ARCHIVE_OK); @@ -828,7 +850,7 @@ header_odc(struct archive_read *a, struct cpio *cpio, * NOTE: if a filename suffix is ".z", it is a file gzipped by afio. * it would be nice if we could show uncompressed file size and * uncompress file contents automatically, unfortunately we have nothing - * to get a uncompressed file size while reading each header. It means + * to get an uncompressed file size while reading each header. It means * we also cannot uncompress file contents under our framework. */ static int @@ -873,7 +895,8 @@ header_afiol(struct archive_read *a, struct cpio *cpio, t = atol16(header + afiol_filesize_offset, afiol_filesize_size); if (t < 0) { - archive_set_error(&a->archive, 0, "Nonsensical file size"); + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Nonsensical file size"); return (ARCHIVE_FATAL); } cpio->entry_bytes_remaining = t; @@ -897,7 +920,7 @@ header_bin_le(struct archive_read *a, struct cpio *cpio, /* Read fixed-size portion of header. */ h = __archive_read_ahead(a, bin_header_size, NULL); if (h == NULL) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "End of file trying to read next cpio header"); return (ARCHIVE_FATAL); } @@ -905,24 +928,24 @@ header_bin_le(struct archive_read *a, struct cpio *cpio, /* Parse out binary fields. */ header = (const unsigned char *)h; - archive_entry_set_dev(entry, header[bin_dev_offset] + header[bin_dev_offset + 1] * 256); - archive_entry_set_ino(entry, header[bin_ino_offset] + header[bin_ino_offset + 1] * 256); - archive_entry_set_mode(entry, header[bin_mode_offset] + header[bin_mode_offset + 1] * 256); + archive_entry_set_dev(entry, archive_le16dec(header + bin_dev_offset)); + archive_entry_set_ino(entry, archive_le16dec(header + bin_ino_offset)); + archive_entry_set_mode(entry, archive_le16dec(header + bin_mode_offset)); if (cpio->option_pwb) { /* turn off random bits left over from V6 inode */ archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777); if ((archive_entry_mode(entry) & AE_IFMT) == 0) archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG); } - archive_entry_set_uid(entry, header[bin_uid_offset] + header[bin_uid_offset + 1] * 256); - archive_entry_set_gid(entry, header[bin_gid_offset] + header[bin_gid_offset + 1] * 256); - archive_entry_set_nlink(entry, header[bin_nlink_offset] + header[bin_nlink_offset + 1] * 256); - archive_entry_set_rdev(entry, header[bin_rdev_offset] + header[bin_rdev_offset + 1] * 256); - archive_entry_set_mtime(entry, le4(header + bin_mtime_offset), 0); - *namelength = header[bin_namesize_offset] + header[bin_namesize_offset + 1] * 256; + archive_entry_set_uid(entry, archive_le16dec(header + bin_uid_offset)); + archive_entry_set_gid(entry, archive_le16dec(header + bin_gid_offset)); + archive_entry_set_nlink(entry, archive_le16dec(header + bin_nlink_offset)); + archive_entry_set_rdev(entry, archive_le16dec(header + bin_rdev_offset)); + archive_entry_set_mtime(entry, le32dec(header + bin_mtime_offset), 0); + *namelength = archive_le16dec(header + bin_namesize_offset); *name_pad = *namelength & 1; /* Pad to even. */ - cpio->entry_bytes_remaining = le4(header + bin_filesize_offset); + cpio->entry_bytes_remaining = le32dec(header + bin_filesize_offset); archive_entry_set_size(entry, cpio->entry_bytes_remaining); cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ __archive_read_consume(a, bin_header_size); @@ -942,7 +965,7 @@ header_bin_be(struct archive_read *a, struct cpio *cpio, /* Read fixed-size portion of header. */ h = __archive_read_ahead(a, bin_header_size, NULL); if (h == NULL) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "End of file trying to read next cpio header"); return (ARCHIVE_FATAL); } @@ -950,24 +973,24 @@ header_bin_be(struct archive_read *a, struct cpio *cpio, /* Parse out binary fields. */ header = (const unsigned char *)h; - archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]); - archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]); - archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]); + archive_entry_set_dev(entry, archive_be16dec(header + bin_dev_offset)); + archive_entry_set_ino(entry, archive_be16dec(header + bin_ino_offset)); + archive_entry_set_mode(entry, archive_be16dec(header + bin_mode_offset)); if (cpio->option_pwb) { /* turn off random bits left over from V6 inode */ archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777); if ((archive_entry_mode(entry) & AE_IFMT) == 0) archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG); } - archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]); - archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]); - archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]); - archive_entry_set_rdev(entry, header[bin_rdev_offset] * 256 + header[bin_rdev_offset + 1]); - archive_entry_set_mtime(entry, be4(header + bin_mtime_offset), 0); - *namelength = header[bin_namesize_offset] * 256 + header[bin_namesize_offset + 1]; + archive_entry_set_uid(entry, archive_be16dec(header + bin_uid_offset)); + archive_entry_set_gid(entry, archive_be16dec(header + bin_gid_offset)); + archive_entry_set_nlink(entry, archive_be16dec(header + bin_nlink_offset)); + archive_entry_set_rdev(entry, archive_be16dec(header + bin_rdev_offset)); + archive_entry_set_mtime(entry, be32dec(header + bin_mtime_offset), 0); + *namelength = archive_be16dec(header + bin_namesize_offset); *name_pad = *namelength & 1; /* Pad to even. */ - cpio->entry_bytes_remaining = be4(header + bin_filesize_offset); + cpio->entry_bytes_remaining = be32dec(header + bin_filesize_offset); archive_entry_set_size(entry, cpio->entry_bytes_remaining); cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */ __archive_read_consume(a, bin_header_size); @@ -994,16 +1017,15 @@ archive_read_format_cpio_cleanup(struct archive_read *a) } static int64_t -le4(const unsigned char *p) +le32dec(const unsigned char *p) { - return ((p[0] << 16) | (((int64_t)p[1]) << 24) | (p[2] << 0) | (p[3] << 8)); + return ((int64_t)archive_le16dec(p) << 16) | archive_le16dec(p + 2); } - static int64_t -be4(const unsigned char *p) +be32dec(const unsigned char *p) { - return ((((int64_t)p[0]) << 24) | (p[1] << 16) | (p[2] << 8) | (p[3])); + return ((int64_t)archive_be16dec(p) << 16) | archive_be16dec(p + 2); } /* @@ -1051,7 +1073,7 @@ atol16u(const char *p, unsigned char_cnt) else if (*p >= '0' && *p <= '9') digit = *p - '0'; else - return ((int64_t)l); + return (l); p++; l <<= 4; l |= digit; @@ -1102,20 +1124,32 @@ record_hardlink(struct archive_read *a, ENOMEM, "Out of memory adding file to list"); return (ARCHIVE_FATAL); } - if (cpio->links_head != NULL) - cpio->links_head->previous = le; - le->next = cpio->links_head; - le->previous = NULL; - cpio->links_head = le; + + const char *pathname = archive_entry_pathname(entry); + if (pathname == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid hardlink entry with no pathname"); + free(le); + return (ARCHIVE_FATAL); + } + le->dev = dev; le->ino = ino; le->links = archive_entry_nlink(entry) - 1; - le->name = strdup(archive_entry_pathname(entry)); + le->name = strdup(pathname); if (le->name == NULL) { archive_set_error(&a->archive, ENOMEM, "Out of memory adding file to list"); + free(le); return (ARCHIVE_FATAL); } + if (cpio->links_head != NULL) + cpio->links_head->previous = le; + le->next = cpio->links_head; + le->previous = NULL; + cpio->links_head = le; + return (ARCHIVE_OK); } diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c index c69fcd272bcd..e1df6273fe63 100644 --- a/libarchive/archive_read_support_format_iso9660.c +++ b/libarchive/archive_read_support_format_iso9660.c @@ -268,6 +268,7 @@ struct file_info { uint64_t size; /* File size in bytes. */ uint32_t ce_offset; /* Offset of CE. */ uint32_t ce_size; /* Size of CE. */ + uint64_t ce_processed_end;/* End offset of processed CE. */ char rr_moved; /* Flag to rr_moved. */ char rr_moved_has_re_only; char re; /* Having RRIP "RE" extension. */ @@ -436,7 +437,6 @@ static void parse_rockridge_ZF1(struct file_info *, const unsigned char *, int); static void register_file(struct iso9660 *, struct file_info *); static void release_files(struct iso9660 *); -static unsigned toi(const void *p, int n); static inline void re_add_entry(struct iso9660 *, struct file_info *); static inline struct file_info * re_get_entry(struct iso9660 *); static inline int rede_add_entry(struct file_info *); @@ -1865,7 +1865,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, } name_len = (size_t)isodirrec[DR_name_len_offset]; location = archive_le32dec(isodirrec + DR_extent_offset); - fsize = toi(isodirrec + DR_size_offset, DR_size_size); + fsize = archive_le32dec(isodirrec + DR_size_offset); /* Sanity check that name_len doesn't exceed dr_len. */ if (dr_len - 33 < name_len || name_len == 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -2162,7 +2162,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, fprintf(stderr, "\n ** Unrecognized flag: "); dump_isodirrec(stderr, isodirrec); fprintf(stderr, "\n"); - } else if (toi(isodirrec + DR_volume_sequence_number_offset, 2) != 1) { + } else if (archive_le16dec(isodirrec + DR_volume_sequence_number_offset) != 1) { fprintf(stderr, "\n ** Unrecognized sequence number: "); dump_isodirrec(stderr, isodirrec); fprintf(stderr, "\n"); @@ -2255,9 +2255,10 @@ parse_rockridge(struct archive_read *a, struct file_info *file, */ if (p[1] == 'N') { if (version == 1 && data_length == 16) { - file->rdev = toi(data,4); + file->rdev = archive_le32dec(data); file->rdev <<= 32; - file->rdev |= toi(data + 8, 4); + file->rdev |= + archive_le32dec(data + 8); iso9660->seenRockridge = 1; } } @@ -2272,20 +2273,20 @@ parse_rockridge(struct archive_read *a, struct file_info *file, */ if (version == 1) { if (data_length >= 8) - file->mode - = (__LA_MODE_T)toi(data, 4); + file->mode = (__LA_MODE_T) + archive_le32dec(data); if (data_length >= 16) - file->nlinks - = toi(data + 8, 4); + file->nlinks = + archive_le32dec(data + 8); if (data_length >= 24) - file->uid - = toi(data + 16, 4); + file->uid = + archive_le32dec(data + 16); if (data_length >= 32) - file->gid - = toi(data + 24, 4); + file->gid = + archive_le32dec(data + 24); if (data_length >= 40) - file->number - = toi(data + 32, 4); + file->number = + archive_le32dec(data + 32); iso9660->seenRockridge = 1; } } @@ -2483,6 +2484,7 @@ read_CE(struct archive_read *a, struct iso9660 *iso9660) const unsigned char *b, *p, *end; struct file_info *file; size_t step; + uint64_t ce_start, ce_end; int r; /* Read data which RRIP "CE" extension points. */ @@ -2506,8 +2508,16 @@ read_CE(struct archive_read *a, struct iso9660 *iso9660) "Malformed CE information"); return (ARCHIVE_FATAL); } + ce_start = heap->reqs[0].offset + file->ce_offset; + ce_end = ce_start + file->ce_size; + if (ce_start < file->ce_processed_end) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid parameter in SUSP \"CE\" extension"); + return (ARCHIVE_FATAL); + } p = b + file->ce_offset; end = p + file->ce_size; + file->ce_processed_end = ce_end; next_CE(heap); r = parse_rockridge(a, file, p, end); if (r != ARCHIVE_OK) @@ -3238,17 +3248,6 @@ heap_get_entry(struct heap_queue *heap) } } -static unsigned int -toi(const void *p, int n) -{ - const unsigned char *v = (const unsigned char *)p; - if (n > 1) - return v[0] + 256 * toi(v + 1, n - 1); - if (n == 1) - return v[0]; - return (0); -} - /* * ECMA119/ISO9660 stores multi-byte integers in one of * three different formats: @@ -3493,6 +3492,8 @@ build_pathname_utf16be(unsigned char *p, size_t max, size_t *len, if (file->parent != NULL && file->parent->utf16be_bytes > 0) { if (build_pathname_utf16be(p, max, len, file->parent) != 0) return (-1); + if (*len + 2 > max) + return (-1);/* Path is too long! */ p[*len] = 0; p[*len + 1] = '/'; *len += 2; @@ -3517,26 +3518,24 @@ static void dump_isodirrec(FILE *out, const unsigned char *isodirrec) { fprintf(out, " l %d,", - toi(isodirrec + DR_length_offset, DR_length_size)); + isodirrec[DR_length_offset]); fprintf(out, " a %d,", - toi(isodirrec + DR_ext_attr_length_offset, DR_ext_attr_length_size)); + isodirrec[DR_ext_attr_length_offset]); fprintf(out, " ext 0x%x,", - toi(isodirrec + DR_extent_offset, DR_extent_size)); + archive_le32dec(isodirrec + DR_extent_offset)); fprintf(out, " s %d,", - toi(isodirrec + DR_size_offset, DR_extent_size)); + archive_le32dec(isodirrec + DR_size_offset)); fprintf(out, " f 0x%x,", - toi(isodirrec + DR_flags_offset, DR_flags_size)); + isodirrec[DR_flags_offset]); fprintf(out, " u %d,", - toi(isodirrec + DR_file_unit_size_offset, DR_file_unit_size_size)); + isodirrec[DR_file_unit_size_offset]); fprintf(out, " ilv %d,", - toi(isodirrec + DR_interleave_offset, DR_interleave_size)); + isodirrec[DR_interleave_offset]); fprintf(out, " seq %d,", - toi(isodirrec + DR_volume_sequence_number_offset, - DR_volume_sequence_number_size)); + archive_le16dec(isodirrec + DR_volume_sequence_number_offset)); fprintf(out, " nl %d:", - toi(isodirrec + DR_name_len_offset, DR_name_len_size)); + isodirrec[DR_name_len_offset]); fprintf(out, " `%.*s'", - toi(isodirrec + DR_name_len_offset, DR_name_len_size), - isodirrec + DR_name_offset); + isodirrec[DR_name_len_offset], isodirrec + DR_name_offset); } #endif diff --git a/libarchive/archive_read_support_format_lha.c b/libarchive/archive_read_support_format_lha.c index ff6dbb8df1cd..b9e6a178934f 100644 --- a/libarchive/archive_read_support_format_lha.c +++ b/libarchive/archive_read_support_format_lha.c @@ -107,8 +107,8 @@ struct lzh_dec { unsigned char *bitlen; /* - * Use a index table. It's faster than searching a huffman - * coding tree, which is a binary tree. But a use of a large + * Use an index table. It's faster than searching a huffman + * coding tree, which is a binary tree. But usage of a large * index table causes L1 cache read miss many times. */ #define HTBL_BITS 10 @@ -142,7 +142,6 @@ struct lzh_stream { int64_t total_in; const unsigned char *ref_ptr; int avail_out; - int64_t total_out; struct lzh_dec *ds; }; @@ -239,7 +238,6 @@ static int lha_read_data_none(struct archive_read *, const void **, size_t *, int64_t *); static int lha_read_data_lzh(struct archive_read *, const void **, size_t *, int64_t *); -static void lha_crc16_init(void); static uint16_t lha_crc16(uint16_t, const void *, size_t); static int lzh_decode_init(struct lzh_stream *, const char *); static void lzh_decode_free(struct lzh_stream *); @@ -483,8 +481,6 @@ archive_read_format_lha_read_header(struct archive_read *a, struct archive_mstring conv_buffer; const wchar_t *conv_buffer_p; - lha_crc16_init(); - a->archive.archive_format = ARCHIVE_FORMAT_LHA; if (a->archive.archive_format_name == NULL) a->archive.archive_format_name = "lha"; @@ -1588,7 +1584,6 @@ lha_read_data_lzh(struct archive_read *a, const void **buff, /* We've initialized decompression for this stream. */ lha->decompress_init = 1; lha->strm.avail_out = 0; - lha->strm.total_out = 0; } /* @@ -1733,30 +1728,86 @@ lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size) return (sum); } -static uint16_t crc16tbl[2][256]; -static void -lha_crc16_init(void) -{ - unsigned int i; - static int crc16init = 0; - - if (crc16init) - return; - crc16init = 1; - - for (i = 0; i < 256; i++) { - unsigned int j; - uint16_t crc = (uint16_t)i; - for (j = 8; j; j--) - crc = (crc >> 1) ^ ((crc & 1) * 0xA001); - crc16tbl[0][i] = crc; - } - - for (i = 0; i < 256; i++) { - crc16tbl[1][i] = (crc16tbl[0][i] >> 8) - ^ crc16tbl[0][crc16tbl[0][i] & 0xff]; +static const uint16_t crc16tbl[2][256] = { + { + 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, + 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, + 0xc481, 0x0440, 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, + 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, + 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0, 0x1980, + 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, + 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 0x1400, + 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, + 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, + 0x1040, 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, + 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, + 0x35c0, 0x3480, 0xf441, 0x3c00, 0xfcc1, 0xfd81, 0x3d40, + 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, + 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1, + 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, + 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, + 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, + 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, + 0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, + 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, + 0xa501, 0x65c0, 0x6480, 0xa441, 0x6c00, 0xacc1, 0xad81, + 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, + 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, + 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, + 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, + 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, + 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, + 0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, + 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, + 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 0x9c01, 0x5cc0, + 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, + 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, + 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, + 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, + 0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, + 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, + 0x4100, 0x81c1, 0x8081, 0x4040 + }, + { + 0x0000, 0x9001, 0x6001, 0xf000, 0xc002, 0x5003, 0xa003, + 0x3002, 0xc007, 0x5006, 0xa006, 0x3007, 0x0005, 0x9004, + 0x6004, 0xf005, 0xc00d, 0x500c, 0xa00c, 0x300d, 0x000f, + 0x900e, 0x600e, 0xf00f, 0x000a, 0x900b, 0x600b, 0xf00a, + 0xc008, 0x5009, 0xa009, 0x3008, 0xc019, 0x5018, 0xa018, + 0x3019, 0x001b, 0x901a, 0x601a, 0xf01b, 0x001e, 0x901f, + 0x601f, 0xf01e, 0xc01c, 0x501d, 0xa01d, 0x301c, 0x0014, + 0x9015, 0x6015, 0xf014, 0xc016, 0x5017, 0xa017, 0x3016, + 0xc013, 0x5012, 0xa012, 0x3013, 0x0011, 0x9010, 0x6010, + 0xf011, 0xc031, 0x5030, 0xa030, 0x3031, 0x0033, 0x9032, + 0x6032, 0xf033, 0x0036, 0x9037, 0x6037, 0xf036, 0xc034, + 0x5035, 0xa035, 0x3034, 0x003c, 0x903d, 0x603d, 0xf03c, + 0xc03e, 0x503f, 0xa03f, 0x303e, 0xc03b, 0x503a, 0xa03a, + 0x303b, 0x0039, 0x9038, 0x6038, 0xf039, 0x0028, 0x9029, + 0x6029, 0xf028, 0xc02a, 0x502b, 0xa02b, 0x302a, 0xc02f, + 0x502e, 0xa02e, 0x302f, 0x002d, 0x902c, 0x602c, 0xf02d, + 0xc025, 0x5024, 0xa024, 0x3025, 0x0027, 0x9026, 0x6026, + 0xf027, 0x0022, 0x9023, 0x6023, 0xf022, 0xc020, 0x5021, + 0xa021, 0x3020, 0xc061, 0x5060, 0xa060, 0x3061, 0x0063, + 0x9062, 0x6062, 0xf063, 0x0066, 0x9067, 0x6067, 0xf066, + 0xc064, 0x5065, 0xa065, 0x3064, 0x006c, 0x906d, 0x606d, + 0xf06c, 0xc06e, 0x506f, 0xa06f, 0x306e, 0xc06b, 0x506a, + 0xa06a, 0x306b, 0x0069, 0x9068, 0x6068, 0xf069, 0x0078, + 0x9079, 0x6079, 0xf078, 0xc07a, 0x507b, 0xa07b, 0x307a, + 0xc07f, 0x507e, 0xa07e, 0x307f, 0x007d, 0x907c, 0x607c, + 0xf07d, 0xc075, 0x5074, 0xa074, 0x3075, 0x0077, 0x9076, + 0x6076, 0xf077, 0x0072, 0x9073, 0x6073, 0xf072, 0xc070, + 0x5071, 0xa071, 0x3070, 0x0050, 0x9051, 0x6051, 0xf050, + 0xc052, 0x5053, 0xa053, 0x3052, 0xc057, 0x5056, 0xa056, + 0x3057, 0x0055, 0x9054, 0x6054, 0xf055, 0xc05d, 0x505c, + 0xa05c, 0x305d, 0x005f, 0x905e, 0x605e, 0xf05f, 0x005a, + 0x905b, 0x605b, 0xf05a, 0xc058, 0x5059, 0xa059, 0x3058, + 0xc049, 0x5048, 0xa048, 0x3049, 0x004b, 0x904a, 0x604a, + 0xf04b, 0x004e, 0x904f, 0x604f, 0xf04e, 0xc04c, 0x504d, + 0xa04d, 0x304c, 0x0044, 0x9045, 0x6045, 0xf044, 0xc046, + 0x5047, 0xa047, 0x3046, 0xc043, 0x5042, 0xa042, 0x3043, + 0x0041, 0x9040, 0x6040, 0xf041 } -} +}; static uint16_t lha_crc16(uint16_t crc, const void *pp, size_t len) @@ -2084,7 +2135,6 @@ lzh_emit_window(struct lzh_stream *strm, size_t s) { strm->ref_ptr = strm->ds->w_buff; strm->avail_out = (int)s; - strm->total_out += s; } static int diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c index 4a5a49ca8136..66e2cb160532 100644 --- a/libarchive/archive_read_support_format_mtree.c +++ b/libarchive/archive_read_support_format_mtree.c @@ -51,6 +51,7 @@ #include "archive.h" #include "archive_entry.h" #include "archive_entry_private.h" +#include "archive_integer.h" #include "archive_platform_stat.h" #include "archive_private.h" #include "archive_rb.h" @@ -1790,12 +1791,16 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, * 123456789.1 represents 123456789 * seconds and 1 nanosecond. */ if (*val == '.') { + int64_t v; + ++val; - ns = (long)mtree_atol(&val, 10); - if (ns < 0) + v = mtree_atol(&val, 10); + if (v < 0) ns = 0; - else if (ns > 999999999) + else if (v > 999999999) ns = 999999999; + else + ns = (long)v; } if (m > my_time_t_max) m = my_time_t_max; @@ -2029,9 +2034,9 @@ parsedigit(char c) if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'a' && c <= 'f') - return c - 'a'; + return 10 + c - 'a'; else if (c >= 'A' && c <= 'F') - return c - 'A'; + return 10 + c - 'A'; else return -1; } @@ -2044,8 +2049,8 @@ parsedigit(char c) static int64_t mtree_atol(char **p, int base) { - int64_t l, limit; - int digit, last_digit_limit; + int64_t l; + int digit; if (base == 0) { if (**p != '0') @@ -2059,29 +2064,24 @@ mtree_atol(char **p, int base) } if (**p == '-') { - limit = INT64_MIN / base; - last_digit_limit = -(INT64_MIN % base); ++(*p); l = 0; digit = parsedigit(**p); while (digit >= 0 && digit < base) { - if (l < limit || (l == limit && digit >= last_digit_limit)) + if (archive_ckd_mul_i64(&l, l, base) || + archive_ckd_sub_i64(&l, l, digit)) return INT64_MIN; - l = (l * base) - digit; digit = parsedigit(*++(*p)); } return l; } else { - limit = INT64_MAX / base; - last_digit_limit = INT64_MAX % base; - l = 0; digit = parsedigit(**p); while (digit >= 0 && digit < base) { - if (l > limit || (l == limit && digit > last_digit_limit)) + if (archive_ckd_mul_i64(&l, l, base) || + archive_ckd_add_i64(&l, l, digit)) return INT64_MAX; - l = (l * base) + digit; digit = parsedigit(*++(*p)); } return l; @@ -2100,8 +2100,7 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t bytes_read; ssize_t total_size = 0; ssize_t find_off = 0; - const void *t; - void *nl; + const void *nl, *t; char *u; /* Accumulate line in a line buffer. */ diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c index 0ed2540cd0a8..803b2e281a99 100644 --- a/libarchive/archive_read_support_format_rar.c +++ b/libarchive/archive_read_support_format_rar.c @@ -154,7 +154,7 @@ #define UNP_BUFFER_SIZE (128 * 1024) /* Define this here for non-Windows platforms */ -#if !((defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)) +#ifndef FILE_ATTRIBUTE_DIRECTORY #define FILE_ATTRIBUTE_DIRECTORY 0x10 #endif @@ -1142,7 +1142,7 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff, default: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Unsupported compression method for RAR file"); - ret = ARCHIVE_FATAL; + ret = ARCHIVE_FAILED; break; } return (ret); @@ -1513,27 +1513,23 @@ read_header(struct archive_read *a, struct archive_entry *entry, * consumed at the end. */ if (head_type == NEWSUB_HEAD) { - size_t distance = p - (const char *)h; if (rar->packed_size > INT64_MAX - header_size) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Extended header size too large"); + "Invalid RAR file: Overlarge extended header"); return (ARCHIVE_FATAL); } - header_size += rar->packed_size; - if ((uintmax_t)header_size > SIZE_MAX) { + if (__archive_read_consume(a, header_size + rar->packed_size - 7) < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Unable to read extended header data"); + "Invalid RAR file: Cannot read extended header data"); return (ARCHIVE_FATAL); } - /* Make sure we have the extended data. */ - if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Failed to read extended header data"); - return (ARCHIVE_FATAL); - } - p = h; - endp = p + header_size - 7; - p += distance; + + /* + * NEWSUB records are metadata-only in this reader. The block header + * has already been validated, so it is safe to skip exactly the + * remaining header bytes and the associated data payload. + */ + return ret; } filename_size = archive_le16dec(file_header.name_size); @@ -1829,10 +1825,6 @@ read_header(struct archive_read *a, struct archive_entry *entry, rar->ppmd_valid = rar->ppmd_eod = 0; rar->filters.filterstart = INT64_MAX; - /* Don't set any archive entries for non-file header types */ - if (head_type == NEWSUB_HEAD) - return ret; - archive_entry_set_mtime(entry, rar->mtime, rar->mnsec); archive_entry_set_ctime(entry, rar->ctime, rar->cnsec); archive_entry_set_atime(entry, rar->atime, rar->ansec); @@ -2026,7 +2018,7 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size, #ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "File CRC error"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); #endif } rar->entry_eof = 1; @@ -2038,7 +2030,7 @@ read_data_stored(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } *size = bytes_avail; @@ -2058,7 +2050,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, int64_t *offset, size_t looper) { if (looper++ > MAX_COMPRESS_DEPTH) - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); struct rar *rar; int64_t start, end; @@ -2069,7 +2061,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, do { if (!rar->valid) - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); if (rar->filters.bytes_ready > 0) { @@ -2121,7 +2113,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, #ifndef DONT_FAIL_ON_CRC_ERROR archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "File CRC error"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); #endif } rar->entry_eof = 1; @@ -2155,7 +2147,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, if (rar->filters.lastend == rar->filters.filterstart) { if (!run_filters(a)) - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); continue; } @@ -2172,7 +2164,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid symbol"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if(sym != rar->ppmd_escape) { @@ -2186,7 +2178,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid symbol"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } switch(code) @@ -2213,7 +2205,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid symbol"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } lzss_offset |= code << (i * 8); } @@ -2222,7 +2214,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid symbol"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } lzss_emit_match(rar, lzss_offset + 2, length + 32); rar->bytes_uncopied += length + 32; @@ -2234,7 +2226,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid symbol"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } lzss_emit_match(rar, 1, length + 4); rar->bytes_uncopied += length + 4; @@ -2280,7 +2272,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, * what we would do to solve it. */ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Internal error extracting RAR file"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } } if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset)) @@ -2363,7 +2355,7 @@ parse_codes(struct archive_read *a) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } /* Make sure ppmd7_context is freed before Ppmd7_Construct @@ -2379,7 +2371,7 @@ parse_codes(struct archive_read *a) if (rar->dictionary_size == 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid zero dictionary size"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context, @@ -2393,7 +2385,7 @@ parse_codes(struct archive_read *a) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Unable to initialize PPMd range decoder"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } __archive_ppmd7_functions.Ppmd7_Init(&rar->ppmd7_context, maxorder); rar->ppmd_valid = 1; @@ -2403,13 +2395,13 @@ parse_codes(struct archive_read *a) if (!rar->ppmd_valid) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid PPMd sequence"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (!__archive_ppmd7_functions.PpmdRAR_RangeDec_Init(&rar->range_dec)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Unable to initialize PPMd range decoder"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } } } @@ -2417,6 +2409,13 @@ parse_codes(struct archive_read *a) { rar_br_consume(br, 1); + /* + * Low-distance repeat state belongs to the current LZ table and + * must not be reused after starting a new table. + */ + rar->lastlowoffset = 0; + rar->numlowoffsetrepeats = 0; + /* Keep existing table flag */ if (!rar_br_read_ahead(a, br, 1)) goto truncated_data; @@ -2459,7 +2458,7 @@ parse_codes(struct archive_read *a) if ((val = read_next_symbol(a, &precode)) < 0) { free(precode.tree); free(precode.table); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (val < 16) { @@ -2474,7 +2473,7 @@ parse_codes(struct archive_read *a) free(precode.table); archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Internal error extracting RAR file"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if(val == 16) { @@ -2564,7 +2563,7 @@ parse_codes(struct archive_read *a) if (new_size == 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Zero window size is invalid"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } new_window = realloc(rar->lzss.window, new_size); if (new_window == NULL) { @@ -2584,7 +2583,7 @@ truncated_data: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated RAR file data"); rar->valid = 0; - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } static void @@ -2700,7 +2699,7 @@ create_code(struct archive_read *a, struct huffman_code *code, { if (lengths[j] != i) continue; if (add_value(a, code, j, codebits, i) != ARCHIVE_OK) - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); codebits++; if (--symbolsleft <= 0) break; @@ -2752,7 +2751,7 @@ add_value(struct archive_read *a, struct huffman_code *code, int value, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Prefix found"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } /* @@ -2811,7 +2810,7 @@ add_value(struct archive_read *a, struct huffman_code *code, int value, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Prefix found"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } /* Set leaf value */ @@ -2850,6 +2849,10 @@ make_table(struct archive_read *a, struct huffman_code *code) code->tablesize = code->maxlength; code->table = calloc(((size_t)1U) << code->tablesize, sizeof(*code->table)); + if (code->table == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } return make_table_recurse(a, code, 0, code->table, 0, code->tablesize); } @@ -2865,13 +2868,13 @@ make_table_recurse(struct archive_read *a, struct huffman_code *code, int node, { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Huffman tree was not created"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (node < 0 || node >= code->numentries) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid location to Huffman tree specified"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } currtablesize = 1 << (maxdepth - depth); @@ -3134,11 +3137,11 @@ truncated_data: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated RAR file data"); rar->valid = 0; - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); bad_data: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } static int @@ -3153,12 +3156,12 @@ copy_from_lzss_window(struct archive_read *a, uint8_t *buffer, if (length > lzss_size(&rar->lzss)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (firstpart < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if (firstpart < length) { memcpy(buffer, &rar->lzss.window[windowoffs], firstpart); @@ -3200,7 +3203,7 @@ copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer, if (firstpart < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } if ((size_t)firstpart < length) { memcpy(&rar->unp_buffer[rar->unp_offset], @@ -3224,7 +3227,7 @@ copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer, fatal: archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Bad RAR file data"); - return (ARCHIVE_FATAL); + return (ARCHIVE_FAILED); } static const void * @@ -3556,7 +3559,13 @@ compile_program(const uint8_t *bytes, size_t length) if (membr_bits(&br, 1)) { - prog->staticdatalen = membr_next_rarvm_number(&br) + 1; + uint32_t staticdatalen = membr_next_rarvm_number(&br); + if (staticdatalen >= VM_MEMORY_SIZE) + { + delete_program_code(prog); + return NULL; + } + prog->staticdatalen = staticdatalen + 1; prog->staticdata = malloc(prog->staticdatalen); if (!prog->staticdata) { diff --git a/libarchive/archive_read_support_format_rar5.c b/libarchive/archive_read_support_format_rar5.c index 63dd97b3008a..ae36a7562e28 100644 --- a/libarchive/archive_read_support_format_rar5.c +++ b/libarchive/archive_read_support_format_rar5.c @@ -81,7 +81,9 @@ * * The array itself is decrypted in `rar5_init` function. */ -static unsigned char rar5_signature_xor[] = { 243, 192, 211, 128, 187, 166, 160, 161 }; +static const unsigned char rar5_signature_xor[] = { + 243, 192, 211, 128, 187, 166, 160, 161 +}; static const size_t g_unpack_window_size = 0x20000; /* These could have been static const's, but they aren't, because of @@ -700,7 +702,7 @@ static int run_filter(struct archive_read* a, struct filter_info* flt) { ARCHIVE_ERRNO_FILE_FORMAT, "Unsupported filter type: 0x%x", (unsigned int)flt->type); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } if(ret != ARCHIVE_OK) { @@ -905,11 +907,10 @@ static inline int get_archive_read(struct archive* a, static int read_ahead(struct archive_read* a, size_t how_many, const uint8_t** ptr) { - ssize_t avail = -1; if(!ptr) return 0; - *ptr = __archive_read_ahead(a, how_many, &avail); + *ptr = __archive_read_ahead(a, how_many, NULL); if(*ptr == NULL) { return 0; } @@ -1046,10 +1047,7 @@ static int read_bits_32(struct archive_read* a, struct rar5* rar, return ARCHIVE_FATAL; } - uint32_t bits = ((uint32_t) p[rar->bits.in_addr]) << 24; - bits |= p[rar->bits.in_addr + 1] << 16; - bits |= p[rar->bits.in_addr + 2] << 8; - bits |= p[rar->bits.in_addr + 3]; + uint32_t bits = archive_be32dec(p + rar->bits.in_addr); bits <<= rar->bits.bit_addr; bits |= p[rar->bits.in_addr + 4] >> (8 - rar->bits.bit_addr); *value = bits; @@ -1066,9 +1064,7 @@ static int read_bits_16(struct archive_read* a, struct rar5* rar, return ARCHIVE_FATAL; } - int bits = (int) ((uint32_t) p[rar->bits.in_addr]) << 16; - bits |= (int) p[rar->bits.in_addr + 1] << 8; - bits |= (int) p[rar->bits.in_addr + 2]; + uint32_t bits = archive_be24dec(p + (unsigned)rar->bits.in_addr); bits >>= (8 - rar->bits.bit_addr); *value = bits & 0xffff; return ARCHIVE_OK; @@ -1790,6 +1786,13 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, if(!read_var_sized(a, &data_size, NULL)) return ARCHIVE_EOF; + if(data_size > SSIZE_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "File data size is too large"); + return ARCHIVE_FATAL; + } + rar->file.bytes_remaining = data_size; } else { rar->file.bytes_remaining = 0; @@ -1946,29 +1949,20 @@ static int process_head_file(struct archive_read* a, struct rar5* rar, archive_entry_set_mode(entry, mode); if (file_attr & (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM)) { - char *fflags_text, *ptr; - /* allocate for ",rdonly,hidden,system" */ - fflags_text = malloc(22 * sizeof(*fflags_text)); - if (fflags_text != NULL) { - ptr = fflags_text; - if (file_attr & ATTR_READONLY) { - strcpy(ptr, ",rdonly"); - ptr = ptr + 7; - } - if (file_attr & ATTR_HIDDEN) { - strcpy(ptr, ",hidden"); - ptr = ptr + 7; - } - if (file_attr & ATTR_SYSTEM) { - strcpy(ptr, ",system"); - ptr = ptr + 7; - } - if (ptr > fflags_text) { - archive_entry_copy_fflags_text(entry, - fflags_text + 1); - } - free(fflags_text); - } + char buf[sizeof(",rdonly,hidden,system")]; + char *fflags[3] = { "", "", "" }; + char **flag = fflags; + + if (file_attr & ATTR_READONLY) + *flag++ = ",rdonly"; + if (file_attr & ATTR_HIDDEN) + *flag++ = ",hidden"; + if (file_attr & ATTR_SYSTEM) + *flag++ = ",system"; + + snprintf(buf, sizeof(buf), "%s%s%s", + fflags[0], fflags[1], fflags[2]); + archive_entry_copy_fflags_text(entry, buf + 1); } } else if(host_os == HOST_UNIX) { /* Host OS is Unix */ @@ -2274,6 +2268,33 @@ static int scan_for_signature(struct archive_read* a); * <FILE> block. */ +/* + * A header that carries no file data (HEAD_MAIN, or an unknown block + * flagged HFL_SKIP_IF_UNKNOWN) may leave bytes in its body that the + * sub-parser did not read. Skip them before returning ARCHIVE_RETRY, + * otherwise rar5_read_header() re-parses the same block region O(N) + * times instead of O(1), letting a crafted RAR5 file stall the reader + * (GHSA-9h2c-464f-j3hj). + * + * Safe because read_ahead(a, hdr_size, &p) pre-loaded the whole block + * into one contiguous buffer with no compaction until we return, so + * body_start stays valid and (cur - body_start) is the exact number of + * body bytes consumed so far. + */ +static void +rar5_skip_remaining_block(struct archive_read* a, + const uint8_t* body_start, size_t raw_hdr_size) +{ + const uint8_t* cur; + + if(read_ahead(a, 1, &cur)) { + size_t body_used = (size_t)(cur - body_start); + + if(body_used < raw_hdr_size) + (void)consume(a, raw_hdr_size - body_used); + } +} + static int process_base_block(struct archive_read* a, struct archive_entry* entry) { @@ -2285,6 +2306,7 @@ static int process_base_block(struct archive_read* a, size_t header_id = 0; size_t header_flags = 0; const uint8_t* p; + const uint8_t* body_start; int ret; enum HEADER_TYPE { @@ -2346,6 +2368,10 @@ static int process_base_block(struct archive_read* a, #endif } + /* Remember the first byte of the block body so we can later skip + * any bytes the sub-parser leaves unconsumed. */ + body_start = p + hdr_size_len; + /* If the checksum is OK, we proceed with parsing. */ if(ARCHIVE_OK != consume(a, hdr_size_len)) { return ARCHIVE_EOF; @@ -2371,8 +2397,11 @@ static int process_base_block(struct archive_read* a, /* Main header doesn't have any files in it, so it's * pointless to return to the caller. Retry to next * header, which should be HEAD_FILE/HEAD_SERVICE. */ - if(ret == ARCHIVE_OK) + if(ret == ARCHIVE_OK) { + rar5_skip_remaining_block(a, body_start, + raw_hdr_size); return ARCHIVE_RETRY; + } return ret; case HEAD_SERVICE: @@ -2432,6 +2461,8 @@ static int process_base_block(struct archive_read* a, /* If the block is marked as 'skip if unknown', * do as the flag says: skip the block * instead on failing on it. */ + rar5_skip_remaining_block(a, body_start, + raw_hdr_size); return ARCHIVE_RETRY; } } @@ -2561,19 +2592,23 @@ static int rar5_read_header(struct archive_read *a, return ret; } -static void init_unpack(struct rar5* rar) { +static int init_unpack(struct rar5* rar) { rar->file.calculated_crc32 = 0; init_window_mask(rar); free(rar->cstate.window_buf); free(rar->cstate.filtered_buf); + rar->cstate.window_buf = NULL; + rar->cstate.filtered_buf = NULL; + if(rar->cstate.window_size > 0) { rar->cstate.window_buf = calloc(1, rar->cstate.window_size); + if(rar->cstate.window_buf == NULL) + return ARCHIVE_FATAL; rar->cstate.filtered_buf = calloc(1, rar->cstate.window_size); - } else { - rar->cstate.window_buf = NULL; - rar->cstate.filtered_buf = NULL; + if(rar->cstate.filtered_buf == NULL) + return ARCHIVE_FATAL; } clear_data_ready_stack(rar); @@ -2586,6 +2621,7 @@ static void init_unpack(struct rar5* rar) { memset(&rar->cstate.dd, 0, sizeof(rar->cstate.dd)); memset(&rar->cstate.ldd, 0, sizeof(rar->cstate.ldd)); memset(&rar->cstate.rd, 0, sizeof(rar->cstate.rd)); + return ARCHIVE_OK; } static void update_crc(struct rar5* rar, const uint8_t* p, size_t to_read) { @@ -2647,6 +2683,15 @@ static int create_decode_tables(uint8_t* bit_length, upper_limit <<= 1; } + /* Verify the code-length distribution is not over-subscribed. + * After the loop above, upper_limit == sum(lc[i] * 2^(16-i)). + * For a valid prefix-free code this must be <= 2^16 = 65536. + * An over-subscribed table (> 65536) cannot produce a valid + * decode table and must be rejected. */ + if(upper_limit > 65536) { + return ARCHIVE_FAILED; + } + memcpy(decode_pos_clone, table->decode_pos, sizeof(decode_pos_clone)); for(i = 0; i < size; i++) { @@ -2748,7 +2793,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated data in huffman tables"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } value = (p[i] & nibble_mask) >> nibble_shift; @@ -2794,7 +2839,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, if(ret != ARCHIVE_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Decoding huffman tables failed"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } for(i = 0; i < HUFF_TABLE_SIZE;) { @@ -2805,7 +2850,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Decoding huffman tables failed"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } if(num < 16) { @@ -2839,7 +2884,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, ARCHIVE_ERRNO_FILE_FORMAT, "Unexpected error when decoding " "huffman tables"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } } else { /* other codes: fill with zeroes `n` times */ @@ -2867,7 +2912,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, if(ret != ARCHIVE_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Failed to create literal table"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } idx += HUFF_NC; @@ -2876,7 +2921,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, if(ret != ARCHIVE_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Failed to create distance table"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } idx += HUFF_DC; @@ -2885,7 +2930,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, if(ret != ARCHIVE_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Failed to create lower bits of distances table"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } idx += HUFF_LDC; @@ -2894,7 +2939,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar, if(ret != ARCHIVE_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Failed to create repeating distances table"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } return ARCHIVE_OK; @@ -2912,7 +2957,7 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p, archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Unsupported block header size (was %d, max is 2)", bf_byte_count(hdr)); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } /* This should probably use bit reader interface in order to be more @@ -2956,7 +3001,7 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p, "Block checksum error: got 0x%x, expected 0x%x", hdr->block_cksum, calculated_cksum); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; #endif } @@ -3037,20 +3082,17 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) { filter_type >>= 13; skip_bits(rar, 3); - /* Perform some sanity checks on this filter parameters. Note that we - * allow only DELTA, E8/E9 and ARM filters here, because rest of - * filters are not used in RARv5. */ + /* Perform some sanity checks on this filter parameters. */ if(block_length < 4 || block_length > 0x400000 || - filter_type > FILTER_ARM || !is_valid_filter_block_start(rar, block_start) || (rar->cstate.window_size > 0 && (ssize_t)block_length > rar->cstate.window_size >> 1)) { archive_set_error(&ar->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid filter encountered"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } /* Allocate a new filter. */ @@ -3203,7 +3245,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { ARCHIVE_ERRNO_PROGRAMMER, "Failed to decode the code length"); - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } if(ARCHIVE_OK != decode_number(a, &rar->cstate.dd, p, @@ -3213,7 +3255,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { ARCHIVE_ERRNO_PROGRAMMER, "Failed to decode the distance slot"); - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } if(dist_slot < 4) { @@ -3258,7 +3300,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { "Failed to decode the " "distance slot"); - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } if(dist >= INT_MAX - low_dist - 1) { @@ -3268,7 +3310,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { ARCHIVE_ERRNO_FILE_FORMAT, "Distance pointer " "overflow"); - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } dist += low_dist; @@ -3303,7 +3345,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { rar->cstate.last_len = len; if(ARCHIVE_OK != copy_string(a, len, dist)) - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; continue; } else if(num == 256) { @@ -3319,7 +3361,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { rar->cstate.last_len, rar->cstate.dist_cache[0])) { - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } } @@ -3334,18 +3376,18 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) { if(ARCHIVE_OK != decode_number(a, &rar->cstate.rd, p, &len_slot)) { - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } len = decode_code_length(a, rar, p, len_slot); if (len == -1) { - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; } rar->cstate.last_len = len; if(ARCHIVE_OK != copy_string(a, len, dist)) - return ARCHIVE_FATAL; + return rar->main.solid ? ARCHIVE_FATAL : ARCHIVE_FAILED; continue; } @@ -3507,6 +3549,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size, if(!rar->vol.push_buf) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for a merge block buffer"); + rar->cstate.switch_multivolume = 0; return ARCHIVE_FATAL; } @@ -3524,15 +3567,21 @@ static int merge_block(struct archive_read* a, ssize_t block_size, cur_block_size = rar5_min(rar->file.bytes_remaining, block_size - partial_offset); - if(cur_block_size == 0) { + if(cur_block_size < 1) { + /* bytes_remaining is less than 1 at the wrong point in + * the merge loop, indicating corrupt volume + * accounting. */ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Encountered block size == 0 during block merge"); + "Encountered invalid block size during block merge"); + rar->cstate.switch_multivolume = 0; return ARCHIVE_FATAL; } - if(!read_ahead(a, cur_block_size, &lp)) + if(!read_ahead(a, cur_block_size, &lp)) { + rar->cstate.switch_multivolume = 0; return ARCHIVE_EOF; + } /* Sanity check; there should never be a situation where this * function reads more data than the block's size. */ @@ -3540,6 +3589,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size, archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, "Consumed too much data when merging blocks"); + rar->cstate.switch_multivolume = 0; return ARCHIVE_FATAL; } @@ -3549,8 +3599,12 @@ static int merge_block(struct archive_read* a, ssize_t block_size, memcpy(&rar->vol.push_buf[partial_offset], lp, cur_block_size); /* Advance the stream read pointer by this block chunk size. */ - if(ARCHIVE_OK != consume(a, cur_block_size)) - return ARCHIVE_EOF; + if(ARCHIVE_OK != consume(a, cur_block_size)) { + /* Data was copied but stream pointer didn't advance; + * stream position is unrecoverable. */ + rar->cstate.switch_multivolume = 0; + return ARCHIVE_FATAL; + } /* Update the pointers. `partial_offset` contains information * about the sum of merged block chunks. */ @@ -3571,6 +3625,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size, ret = advance_multivolume(a); rar->merge_mode--; if(ret != ARCHIVE_OK) { + rar->cstate.switch_multivolume = 0; return ret; } } @@ -3627,6 +3682,15 @@ static int process_block(struct archive_read* a) { to_skip = sizeof(struct compressed_block_header) + bf_byte_count(&rar->last_block_hdr) + 1; + /* If the block header's to_skip value exceeds the declared + * remaining data, the archive is malformed. */ + if(to_skip > rar->file.bytes_remaining) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Block header size exceeds remaining file data"); + return ARCHIVE_FATAL; + } + if(ARCHIVE_OK != consume(a, to_skip)) return ARCHIVE_EOF; @@ -3863,7 +3927,8 @@ static int do_uncompress_file(struct archive_read* a) { /* Don't perform full context reinitialization if we're * processing a solid archive. */ if(!rar->main.solid || !rar->cstate.window_buf) { - init_unpack(rar); + if((ret = init_unpack(rar)) != ARCHIVE_OK) + return ret; } rar->cstate.initialized = 1; @@ -3876,7 +3941,7 @@ static int do_uncompress_file(struct archive_read* a) { "Invalid window size declaration in this file"); /* This should never happen in valid files. */ - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } if(rar->cstate.all_filters_applied == 1) { @@ -3887,7 +3952,7 @@ static int do_uncompress_file(struct archive_read* a) { * files). */ while(1) { ret = process_block(a); - if(ret == ARCHIVE_EOF || ret == ARCHIVE_FATAL) + if(ret != ARCHIVE_OK) return ret; if(rar->cstate.last_write_ptr == @@ -3913,12 +3978,10 @@ static int do_uncompress_file(struct archive_read* a) { ret = apply_filters(a); if(ret == ARCHIVE_RETRY) { return ARCHIVE_OK; - } else if(ret == ARCHIVE_FATAL) { - return ARCHIVE_FATAL; + } else if(ret != ARCHIVE_OK) { + return ret; } - /* If apply_filters() will return ARCHIVE_OK, we can continue here. */ - if(cdeque_size(&rar->cstate.filters) > 0) { /* Check if we can write something before hitting first * filter. */ @@ -4131,7 +4194,7 @@ static int verify_checksums(struct archive_read* a) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Checksum error: CRC32"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; #endif } else { DEBUG_CODE { @@ -4166,7 +4229,7 @@ static int verify_checksums(struct archive_read* a) { ARCHIVE_ERRNO_FILE_FORMAT, "Checksum error: BLAKE2"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; #endif } } @@ -4207,7 +4270,7 @@ static int rar5_read_data(struct archive_read *a, const void **buff, if (rar->headers_are_encrypted || rar->cstate.data_encrypted) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Reading encrypted data is not currently supported"); - return ARCHIVE_FATAL; + return ARCHIVE_FAILED; } if(rar->file.dir > 0) { diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index 2979492767ed..ac3dd446cb68 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -42,6 +42,7 @@ #include "archive_acl_private.h" /* For ACL parsing routines. */ #include "archive_entry.h" #include "archive_entry_locale.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" @@ -153,6 +154,8 @@ struct tar { int compat_2x; int process_mac_extensions; int read_concatenated_archives; + int default_inode; + int default_dev; }; /* Track which size fields were present in the headers */ @@ -248,6 +251,36 @@ static const size_t fflags_limit = 512; /* Longest fflags */ static const size_t acl_limit = 131072; /* Longest textual ACL: 128kiB */ static const int64_t entry_limit = 0xfffffffffffffffLL; /* 2^60 bytes = 1 ExbiByte */ +/* + * There's no standard for TIME_T_MAX. So we compute it + * here. TODO: Move this to configure time, but be careful + * about cross-compile environments. + */ +static time_t +get_time_t_max(void) +{ +#if defined(TIME_T_MAX) + return TIME_T_MAX; +#else + /* ISO C allows time_t to be a floating-point type, + but POSIX requires an integer type. The following + should work on any system that follows the POSIX + conventions. */ + if (((time_t)0) < ((time_t)-1)) { + /* Time_t is unsigned */ + return (~(time_t)0); + } else { + /* Time_t is signed. */ + /* Assume it's the same as int64_t or int32_t */ + if (sizeof(time_t) == sizeof(int64_t)) { + return (time_t)INT64_MAX; + } else { + return (time_t)INT32_MAX; + } + } +#endif +} + int archive_read_support_format_gnutar(struct archive *a) { @@ -522,10 +555,6 @@ archive_read_format_tar_read_header(struct archive_read *a, * probably not worthwhile just to support the relatively * obscure tar->cpio conversion case. */ - /* TODO: Move this into `struct tar` to avoid conflicts - * when reading multiple archives */ - static int default_inode; - static int default_dev; struct tar *tar; const char *p; const wchar_t *wp; @@ -533,16 +562,17 @@ archive_read_format_tar_read_header(struct archive_read *a, size_t l; int64_t unconsumed = 0; + tar = (struct tar *)(a->format->data); + /* Assign default device/inode values. */ - archive_entry_set_dev(entry, 1 + default_dev); /* Don't use zero. */ - archive_entry_set_ino(entry, ++default_inode); /* Don't use zero. */ + archive_entry_set_dev(entry, 1 + tar->default_dev); /* Don't use zero. */ + archive_entry_set_ino(entry, ++tar->default_inode); /* Don't use zero. */ /* Limit generated st_ino number to 16 bits. */ - if (default_inode >= 0xffff) { - ++default_dev; - default_inode = 0; + if (tar->default_inode >= 0xffff) { + ++tar->default_dev; + tar->default_inode = 0; } - tar = (struct tar *)(a->format->data); tar->entry_offset = 0; gnu_clear_sparse_list(tar); tar->size_fields = 0; /* We don't have any size info yet */ @@ -586,16 +616,16 @@ archive_read_format_tar_read_header(struct archive_read *a, * directory: This is needed for certain old tar * variants and even for some broken newer ones. */ - if ((wp = archive_entry_pathname_w(entry)) != NULL) { - l = wcslen(wp); - if (l > 0 && wp[l - 1] == L'/') { + if ((p = archive_entry_pathname(entry)) != NULL) { + l = strlen(p); + if (l > 0 && p[l - 1] == '/') { archive_entry_set_filetype(entry, AE_IFDIR); tar->entry_bytes_remaining = 0; tar->entry_padding = 0; } - } else if ((p = archive_entry_pathname(entry)) != NULL) { - l = strlen(p); - if (l > 0 && p[l - 1] == '/') { + } else if ((wp = archive_entry_pathname_w(entry)) != NULL) { + l = wcslen(wp); + if (l > 0 && wp[l - 1] == L'/') { archive_entry_set_filetype(entry, AE_IFDIR); tar->entry_bytes_remaining = 0; tar->entry_padding = 0; @@ -1369,7 +1399,12 @@ header_common(struct archive_read *a, struct tar *tar, archive_entry_set_gid(entry, tar_atol(header->gid, sizeof(header->gid))); } if (!archive_entry_mtime_is_set(entry)) { - archive_entry_set_mtime(entry, tar_atol(header->mtime, sizeof(header->mtime)), 0); + int64_t t64 = tar_atol(header->mtime, sizeof(header->mtime)); + time_t t = (time_t)t64; + if ((int64_t)t != t64) { /* time_t overflowed */ + t = get_time_t_max(); + } + archive_entry_set_mtime(entry, t, 0); } /* Reconcile the size info. */ @@ -1782,32 +1817,42 @@ header_ustar(struct archive_read *a, struct tar *tar, struct archive_entry *entry, const void *h) { const struct archive_entry_header_ustar *header; - struct archive_string as; int err = ARCHIVE_OK, r; header = (const struct archive_entry_header_ustar *)h; - /* Copy name into an internal buffer to ensure null-termination. */ + /* + * The name field is fixed-width and may not be NUL-terminated. + * Use a temporary string only when prefix/name joining is required. + */ const char *existing_pathname = archive_entry_pathname(entry); const wchar_t *existing_wcs_pathname = archive_entry_pathname_w(entry); if ((existing_pathname == NULL || existing_pathname[0] == '\0') && (existing_wcs_pathname == NULL || existing_wcs_pathname[0] == '\0')) { + struct archive_string as; + const char *pathname; + size_t pathname_length; + archive_string_init(&as); if (header->prefix[0]) { archive_strncpy(&as, header->prefix, sizeof(header->prefix)); if (as.s[archive_strlen(&as) - 1] != '/') archive_strappend_char(&as, '/'); archive_strncat(&as, header->name, sizeof(header->name)); + pathname = as.s; + pathname_length = archive_strlen(&as); } else { - archive_strncpy(&as, header->name, sizeof(header->name)); + pathname = header->name; + pathname_length = sizeof(header->name); } - if (archive_entry_copy_pathname_l(entry, as.s, archive_strlen(&as), - tar->sconv) != 0) { + r = archive_entry_copy_pathname_l(entry, pathname, + pathname_length, tar->sconv); + archive_string_free(&as); + if (r != 0) { err = set_conversion_failed_error(a, tar->sconv, "Pathname"); if (err == ARCHIVE_FATAL) return (err); } - archive_string_free(&as); } /* Handle rest of common fields. */ @@ -2009,6 +2054,7 @@ header_pax_extension(struct archive_read *a, struct tar *tar, /* Consume size, name, and `=` */ *unconsumed += p - attr_start; if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { + archive_string_free(&attr_name); return (ARCHIVE_FATAL); } @@ -2016,6 +2062,7 @@ header_pax_extension(struct archive_read *a, struct tar *tar, archive_set_error(&a->archive, EINVAL, "Malformed pax attributes"); *unconsumed += ext_size + ext_padding; + archive_string_free(&attr_name); return (ARCHIVE_WARN); } @@ -2266,7 +2313,7 @@ pax_attribute_SCHILY_acl(struct archive_read *a, struct tar *tar, } static int -pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps, long *pn, int64_t *unconsumed) { +pax_attribute_read_time(struct archive_read *a, size_t value_length, __LA_TIME_T *ps, long *pn, int64_t *unconsumed) { struct archive_string as; int r; @@ -2286,12 +2333,16 @@ pax_attribute_read_time(struct archive_read *a, size_t value_length, int64_t *ps return (r); } - pax_time(as.s, archive_strlen(&as), ps, pn); + int64_t sec = 0; + pax_time(as.s, archive_strlen(&as), &sec, pn); archive_string_free(&as); - if (*ps == INT64_MIN) { + + if (sec == INT64_MIN) { *ps = 0; *pn = 0; return (ARCHIVE_WARN); + } else { + *ps = (__LA_TIME_T)sec; } return (ARCHIVE_OK); } @@ -2348,7 +2399,6 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent int64_t t; long n; const char *p; - ssize_t bytes_read; int err = ARCHIVE_OK; switch (key[0]) { @@ -2432,7 +2482,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent (unsigned long long)sparse_map_limit); err = ARCHIVE_FAILED; } else { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, EINVAL, "Truncated archive" @@ -2507,15 +2557,20 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent */ if (key_length == 12 && memcmp(key, "creationtime", 12) == 0) { /* LIBARCHIVE.creationtime */ - if ((err = pax_attribute_read_time(a, value_length, &t, &n, unconsumed)) == ARCHIVE_OK) { - archive_entry_set_birthtime(entry, t, n); + __LA_TIME_T sec = 0; + if ((err = pax_attribute_read_time(a, value_length, &sec, &n, unconsumed)) == ARCHIVE_OK) { + archive_entry_set_birthtime(entry, sec, n); + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Ignoring malformed pax creationtime"); } return (err); } else if (key_length == 11 && memcmp(key, "symlinktype", 11) == 0) { /* LIBARCHIVE.symlinktype */ if (value_length < 16) { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated tar archive " @@ -2549,7 +2604,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent if (value_length > xattr_limit) { err = ARCHIVE_WARN; } else { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, EINVAL, "Truncated archive" @@ -2579,7 +2634,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent /* TODO: Should this be FAILED instead? */ err = ARCHIVE_WARN; } else { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, EINVAL, "Truncated archive" @@ -2632,7 +2687,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent } else if (key_length == 6 && memcmp(key, "fflags", 6) == 0) { if (value_length < fflags_limit) { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { /* Truncated archive */ archive_set_error(&a->archive, EINVAL, @@ -2679,7 +2734,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent key_length -= 6; key += 6; if (value_length < xattr_limit) { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, EINVAL, "Truncated archive" @@ -2709,7 +2764,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent if (key_length == 9 && memcmp(key, "holesdata", 9) == 0) { /* SUN.holesdata */ if (value_length < sparse_map_limit) { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, EINVAL, "Truncated archive" @@ -2736,16 +2791,26 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent break; case 'a': if (key_length == 5 && memcmp(key, "atime", 5) == 0) { - if ((err = pax_attribute_read_time(a, value_length, &t, &n, unconsumed)) == ARCHIVE_OK) { - archive_entry_set_atime(entry, t, n); + __LA_TIME_T sec = 0; + if ((err = pax_attribute_read_time(a, value_length, &sec, &n, unconsumed)) == ARCHIVE_OK) { + archive_entry_set_atime(entry, sec, n); + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Ignoring malformed pax atime"); } return (err); } break; case 'c': if (key_length == 5 && memcmp(key, "ctime", 5) == 0) { - if ((err = pax_attribute_read_time(a, value_length, &t, &n, unconsumed)) == ARCHIVE_OK) { - archive_entry_set_ctime(entry, t, n); + __LA_TIME_T sec = 0; + if ((err = pax_attribute_read_time(a, value_length, &sec, &n, unconsumed)) == ARCHIVE_OK) { + archive_entry_set_ctime(entry, sec, n); + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Ignoring malformed pax ctime"); } return (err); } else if (key_length == 7 && memcmp(key, "charset", 7) == 0) { @@ -2773,7 +2838,7 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent case 'h': if (key_length == 10 && memcmp(key, "hdrcharset", 10) == 0) { if (value_length < 64) { - p = __archive_read_ahead(a, value_length, &bytes_read); + p = __archive_read_ahead(a, value_length, NULL); if (p == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated tar archive " @@ -2817,8 +2882,13 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent break; case 'm': if (key_length == 5 && memcmp(key, "mtime", 5) == 0) { - if ((err = pax_attribute_read_time(a, value_length, &t, &n, unconsumed)) == ARCHIVE_OK) { - archive_entry_set_mtime(entry, t, n); + __LA_TIME_T sec; + if ((err = pax_attribute_read_time(a, value_length, &sec, &n, unconsumed)) == ARCHIVE_OK) { + archive_entry_set_mtime(entry, sec, n); + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Ignoring malformed pax mtime"); } return (err); } @@ -2885,7 +2955,8 @@ pax_attribute(struct archive_read *a, struct tar *tar, struct archive_entry *ent /* * Parse a decimal time value, which may include a fractional portion * - * Sets ps to INT64_MIN on error. + * Sets ps to INT64_MIN on error, including syntax issues such as non-digits, + * or a time value that's outside the range of time_t. */ static void pax_time(const char *p, size_t length, int64_t *ps, long *pn) @@ -2894,10 +2965,6 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn) int64_t s; unsigned long l; int sign; - int64_t limit, last_digit_limit; - - limit = INT64_MAX / 10; - last_digit_limit = INT64_MAX % 10; if (length <= 0) { *ps = 0; @@ -2913,34 +2980,73 @@ pax_time(const char *p, size_t length, int64_t *ps, long *pn) } while (length > 0 && *p >= '0' && *p <= '9') { digit = *p - '0'; - if (s > limit || - (s == limit && digit > last_digit_limit)) { + if (archive_ckd_mul_i64(&s, s, 10) || + archive_ckd_add_i64(&s, s, digit)) { *ps = INT64_MIN; *pn = 0; return; } - s = (s * 10) + digit; ++p; --length; } *ps = s * sign; +#if ARCHIVE_VERSION_NUMBER < 4000000 + /* Libarchive 4.0 will have __LA_TIME_T == int64_t, so + this will be unnecessary. */ + /* Test whether it overflows __LA_TIME_T */ + __LA_TIME_T sec = (__LA_TIME_T)*ps; + if ((int64_t)sec != *ps) { + *ps = INT64_MIN; + *pn = 0; + return; + } +#endif + /* Calculate nanoseconds. */ *pn = 0; - if (length <= 0 || *p != '.') + if (length <= 0) { return; + } + + /* Skip `.` */ + if (*p != '.') { + *ps = INT64_MIN; + *pn = 0; + return; + } + ++p; + --length; l = 100000000UL; do { + if (length <= 0) { + return; + } + if (*p >= '0' && *p <= '9') { + *pn += (*p - '0') * l; + } else { + *ps = INT64_MIN; + *pn = 0; + return; + } ++p; --length; - if (length > 0 && *p >= '0' && *p <= '9') - *pn += (*p - '0') * l; - else - break; } while (l /= 10); + + /* Ignore resolution beyond nanoseconds, + but verify it's all decimal digits. */ + while (length > 0) { + if (*p < '0' || *p > '9') { + *ps = INT64_MIN; + *pn = 0; + return; + } + ++p; + --length; + } } /* @@ -3103,7 +3209,6 @@ static int gnu_sparse_old_read(struct archive_read *a, struct tar *tar, const struct archive_entry_header_gnutar *header, int64_t *unconsumed) { - ssize_t bytes_read; const void *data; struct extended { struct gnu_sparse sparse[21]; @@ -3121,7 +3226,7 @@ gnu_sparse_old_read(struct archive_read *a, struct tar *tar, if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { return (ARCHIVE_FATAL); } - data = __archive_read_ahead(a, 512, &bytes_read); + data = __archive_read_ahead(a, 512, NULL); if (data == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated tar archive " @@ -3239,14 +3344,12 @@ static int64_t gnu_sparse_10_atol(struct archive_read *a, struct tar *tar, int64_t *remaining, int64_t *unconsumed) { - int64_t l, limit, last_digit_limit; + int64_t l; const char *p; ssize_t bytes_read; int base, digit; base = 10; - limit = INT64_MAX / base; - last_digit_limit = INT64_MAX % base; /* * Skip any lines starting with '#'; GNU tar specs @@ -3267,10 +3370,10 @@ gnu_sparse_10_atol(struct archive_read *a, struct tar *tar, if (*p < '0' || *p >= '0' + base) return (ARCHIVE_WARN); digit = *p - '0'; - if (l > limit || (l == limit && digit > last_digit_limit)) + if (archive_ckd_mul_i64(&l, l, base) || + archive_ckd_add_i64(&l, l, digit)) { l = INT64_MAX; /* Truncate on overflow. */ - else - l = (l * base) + digit; + } p++; bytes_read--; } @@ -3416,13 +3519,9 @@ tar_atol(const char *p, size_t char_cnt) static int64_t tar_atol_base_n(const char *p, size_t char_cnt, int base) { - int64_t l, maxval, limit, last_digit_limit; + int64_t l; int digit, sign; - maxval = INT64_MAX; - limit = INT64_MAX / base; - last_digit_limit = INT64_MAX % base; - /* the pointer will not be dereferenced if char_cnt is zero * due to the way the && operator is evaluated. */ @@ -3436,25 +3535,22 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base) sign = -1; p++; char_cnt--; - - maxval = INT64_MIN; - limit = -(INT64_MIN / base); - last_digit_limit = -(INT64_MIN % base); } l = 0; if (char_cnt != 0) { digit = *p - '0'; - while (digit >= 0 && digit < base && char_cnt != 0) { - if (l>limit || (l == limit && digit >= last_digit_limit)) { - return maxval; /* Truncate on overflow. */ + while (digit >= 0 && digit < base && char_cnt != 0) { + if (archive_ckd_mul_i64(&l, l, base) || + archive_ckd_add_i64(&l, l, sign * digit)) { + /* Truncate on overflow. */ + return sign < 0 ? INT64_MIN : INT64_MAX; } - l = (l * base) + digit; digit = *++p - '0'; char_cnt--; } } - return (sign < 0) ? -l : l; + return l; } static int64_t @@ -3534,9 +3630,8 @@ readline(struct archive_read *a, struct tar *tar, const char **start, { ssize_t bytes_read; ssize_t total_size = 0; - const void *t; + const void *p, *t; const char *s; - void *p; if (tar_flush_unconsumed(a, unconsumed) != ARCHIVE_OK) { return (ARCHIVE_FATAL); @@ -3608,24 +3703,20 @@ readline(struct archive_read *a, struct tar *tar, const char **start, static char * base64_decode(const char *s, size_t len, size_t *out_len) { - static const unsigned char digits[64] = { - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N', - 'O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b', - 'c','d','e','f','g','h','i','j','k','l','m','n','o','p', - 'q','r','s','t','u','v','w','x','y','z','0','1','2','3', - '4','5','6','7','8','9','+','/' }; - static unsigned char decode_table[128]; + static const unsigned char decode_table[128] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, + 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, + 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 255, 255, 255, 255, 255 }; char *out, *d; const unsigned char *src = (const unsigned char *)s; - /* If the decode table is not yet initialized, prepare it. */ - if (decode_table[digits[1]] != 1) { - unsigned i; - memset(decode_table, 0xff, sizeof(decode_table)); - for (i = 0; i < sizeof(digits); i++) - decode_table[digits[i]] = i; - } - /* Allocate enough space to hold the entire output. */ /* Note that we may not use all of this... */ out = malloc(len - len / 4 + 1); diff --git a/libarchive/archive_read_support_format_xar.c b/libarchive/archive_read_support_format_xar.c index 874501fc0782..e61ca0e6423f 100644 --- a/libarchive/archive_read_support_format_xar.c +++ b/libarchive/archive_read_support_format_xar.c @@ -56,6 +56,7 @@ #include "archive_endian.h" #include "archive_entry.h" #include "archive_entry_locale.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_read_private.h" @@ -387,8 +388,7 @@ static int rd_contents_init(struct archive_read *, enum enctype, int, int); static int rd_contents(struct archive_read *, const void **, size_t *, size_t *, uint64_t); -static uint64_t atol10(const char *, size_t); -static int64_t atol8(const char *, size_t); +static int atou64(const char *, size_t, int, uint64_t *); static size_t atohex(unsigned char *, size_t, const char *, size_t); static time_t parse_time(const char *p, size_t n); static int heap_add_entry(struct archive_read *a, @@ -421,7 +421,7 @@ static void unknowntag_end(struct xar *, const char *); static int xml_start(struct archive_read *, const char *, struct xmlattr_list *); static void xml_end(void *, const char *); -static void xml_data(void *, const char *, size_t); +static int xml_data(void *, const char *, size_t); static int xml_parse_file_flags(struct xar *, const char *); static int xml_parse_file_ext2(struct xar *, const char *); #if defined(HAVE_LIBXML_XMLREADER_H) @@ -1071,44 +1071,26 @@ rd_contents(struct archive_read *a, const void **buff, size_t *size, * it does obey locale. */ -static uint64_t -atol10(const char *p, size_t char_cnt) +static int +atou64(const char *p, size_t char_cnt, int base, uint64_t *val) { uint64_t l; - int digit; - - if (char_cnt == 0) - return (0); l = 0; - digit = *p - '0'; - while (digit >= 0 && digit < 10 && char_cnt-- > 0) { - l = (l * 10) + digit; - digit = *++p - '0'; - } - return (l); -} + if (char_cnt > 0) { + int digit; -static int64_t -atol8(const char *p, size_t char_cnt) -{ - int64_t l; - int digit; - - if (char_cnt == 0) - return (0); - - l = 0; - while (char_cnt-- > 0) { - if (*p >= '0' && *p <= '7') - digit = *p - '0'; - else - break; - p++; - l <<= 3; - l |= digit; + digit = *p - '0'; + while (digit >= 0 && digit < base && char_cnt-- > 0) { + if (archive_ckd_mul_u64(&l, l, base) || + archive_ckd_add_u64(&l, l, digit)) + return (ARCHIVE_FATAL); + digit = *++p - '0'; + } } - return (l); + + *val = l; + return (ARCHIVE_OK); } static size_t @@ -1173,48 +1155,42 @@ parse_time(const char *p, size_t n) { struct tm tm; time_t t = 0; - int64_t data; + uint64_t data; memset(&tm, 0, sizeof(tm)); if (n != 20) return (t); - data = atol10(p, 4); - if (data < 1900) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data < 1900) return (t); tm.tm_year = (int)data - 1900; p += 4; if (*p++ != '-') return (t); - data = atol10(p, 2); - if (data < 1 || data > 12) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data < 1 || data > 12) return (t); tm.tm_mon = (int)data -1; p += 2; if (*p++ != '-') return (t); - data = atol10(p, 2); - if (data < 1 || data > 31) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data < 1 || data > 31) return (t); tm.tm_mday = (int)data; p += 2; if (*p++ != 'T') return (t); - data = atol10(p, 2); - if (data < 0 || data > 23) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data > 23) return (t); tm.tm_hour = (int)data; p += 2; if (*p++ != ':') return (t); - data = atol10(p, 2); - if (data < 0 || data > 59) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data > 59) return (t); tm.tm_min = (int)data; p += 2; if (*p++ != ':') return (t); - data = atol10(p, 2); - if (data < 0 || data > 60) + if (atou64(p, 4, 10, &data) != ARCHIVE_OK || data > 60) return (t); tm.tm_sec = (int)data; #if 0 @@ -1800,12 +1776,20 @@ file_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list) file->mode = 0777 | AE_IFREG; file->atime = 0; file->mtime = 0; - xar->file = file; xar->xattr = NULL; for (attr = list->first; attr != NULL; attr = attr->next) { - if (strcmp(attr->name, "id") == 0) - file->id = atol10(attr->value, strlen(attr->value)); + if (strcmp(attr->name, "id") == 0) { + int r; + + r = atou64(attr->value, strlen(attr->value), + 10, &file->id); + if (r != ARCHIVE_OK) { + free(file); + return (r); + } + } } + xar->file = file; file->nlink = 1; if (heap_add_entry(a, &(xar->file_queue), file) != ARCHIVE_OK) return (ARCHIVE_FATAL); @@ -1822,6 +1806,7 @@ file_free(struct xar_file *file) archive_string_free(&(file->uname)); archive_string_free(&(file->gname)); archive_string_free(&(file->hardlink)); + archive_string_free(&(file->fflags_text)); xattr = file->xattr_list; while (xattr != NULL) { struct xattr *next; @@ -1845,11 +1830,19 @@ xattr_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list) archive_set_error(&a->archive, ENOMEM, "Out of memory"); return (ARCHIVE_FATAL); } - xar->xattr = xattr; for (attr = list->first; attr != NULL; attr = attr->next) { - if (strcmp(attr->name, "id") == 0) - xattr->id = atol10(attr->value, strlen(attr->value)); + if (strcmp(attr->name, "id") == 0) { + int r; + + r = atou64(attr->value, strlen(attr->value), + 10, &xattr->id); + if (r != ARCHIVE_OK) { + free(xattr); + return (r); + } + } } + xar->xattr = xattr; /* Chain to xattr list. */ for (nx = &(xar->file->xattr_list); *nx != NULL; nx = &((*nx)->next)) { @@ -1866,6 +1859,7 @@ static void xattr_free(struct xattr *xattr) { archive_string_free(&(xattr->name)); + archive_string_free(&(xattr->fstype)); free(xattr); } @@ -2065,8 +2059,17 @@ xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list) xar->file->hdnext = xar->hdlink_orgs; xar->hdlink_orgs = xar->file; } else { - xar->file->link = (unsigned)atol10(attr->value, - strlen(attr->value)); + uint64_t val; + int r; + r = atou64(attr->value, + strlen(attr->value), 10, &val); + if (r != ARCHIVE_OK) { + return (r); + } + if (val > UINT_MAX) { + return (ARCHIVE_FATAL); + } + xar->file->link = (unsigned)val; if (xar->file->link > 0) if (add_link(a, xar, xar->file) != ARCHIVE_OK) { return (ARCHIVE_FATAL); @@ -2673,11 +2676,13 @@ is_string(const char *known, const char *data, size_t len) return memcmp(data, known, len); } -static void +static int xml_data(void *userData, const char *s, size_t len) { + uint64_t val; struct archive_read *a; struct xar *xar; + int r; a = (struct archive_read *)userData; xar = (struct xar *)(a->format->data); @@ -2685,25 +2690,30 @@ xml_data(void *userData, const char *s, size_t len) #if DEBUG { char buff[1024]; - if (len > (int)(sizeof(buff)-1)) - len = (int)(sizeof(buff)-1); - strncpy(buff, s, len); - buff[len] = 0; - fprintf(stderr, "\tlen=%d:\"%s\"\n", len, buff); + size_t dlen = len; + if (dlen > sizeof(buff) - 1) + dlen = sizeof(buff) - 1; + strncpy(buff, s, dlen); + buff[dlen] = 0; + fprintf(stderr, "\tlen=%zu:\"%s\"\n", dlen, buff); } #endif switch (xar->xmlsts) { case TOC_CHECKSUM_OFFSET: - xar->toc_chksum_offset = atol10(s, len); + r = atou64(s, len, 10, &xar->toc_chksum_offset); + if (r != ARCHIVE_OK) + return (r); break; case TOC_CHECKSUM_SIZE: - xar->toc_chksum_size = atol10(s, len); + r = atou64(s, len, 10, &xar->toc_chksum_size); + if (r != ARCHIVE_OK) + return (r); break; default: break; } if (xar->file == NULL) - return; + return (ARCHIVE_OK); switch (xar->xmlsts) { case FILE_NAME: @@ -2752,42 +2762,76 @@ xml_data(void *userData, const char *s, size_t len) xar->file->has |= HAS_TYPE; break; case FILE_INODE: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val > (uint64_t)INT64_MAX) + return (ARCHIVE_FATAL); xar->file->has |= HAS_INO; - xar->file->ino64 = atol10(s, len); + xar->file->ino64 = (int64_t)val; break; case FILE_DEVICE_MAJOR: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val != (dev_t)val) + return (ARCHIVE_FATAL); xar->file->has |= HAS_DEVMAJOR; - xar->file->devmajor = (dev_t)atol10(s, len); + xar->file->devmajor = (dev_t)val; break; case FILE_DEVICE_MINOR: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val != (dev_t)val) + return (ARCHIVE_FATAL); xar->file->has |= HAS_DEVMINOR; - xar->file->devminor = (dev_t)atol10(s, len); + xar->file->devminor = (dev_t)val; break; case FILE_DEVICENO: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val != (dev_t)val) + return (ARCHIVE_FATAL); xar->file->has |= HAS_DEV; - xar->file->dev = (dev_t)atol10(s, len); + xar->file->dev = (dev_t)val; break; case FILE_MODE: + r = atou64(s, len, 8, &val); + if (r != ARCHIVE_OK) + return (r); + if (val != (mode_t)val) + return (ARCHIVE_FATAL); xar->file->has |= HAS_MODE; xar->file->mode = - (xar->file->mode & AE_IFMT) | - ((mode_t)(atol8(s, len)) & ~AE_IFMT); + (xar->file->mode & AE_IFMT) | ((mode_t)val & ~AE_IFMT); break; case FILE_GROUP: xar->file->has |= HAS_GID; archive_strncpy(&(xar->file->gname), s, len); break; case FILE_GID: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val > (uint64_t)INT64_MAX) + return (ARCHIVE_FATAL); xar->file->has |= HAS_GID; - xar->file->gid = atol10(s, len); + xar->file->gid = (int64_t)val; break; case FILE_USER: xar->file->has |= HAS_UID; archive_strncpy(&(xar->file->uname), s, len); break; case FILE_UID: + r = atou64(s, len, 10, &val); + if (r != ARCHIVE_OK) + return (r); + if (val > (uint64_t)INT64_MAX) + return (ARCHIVE_FATAL); xar->file->has |= HAS_UID; - xar->file->uid = atol10(s, len); + xar->file->uid = (int64_t)val; break; case FILE_CTIME: xar->file->has |= HAS_TIME | HAS_CTIME; @@ -2802,16 +2846,22 @@ xml_data(void *userData, const char *s, size_t len) xar->file->atime = parse_time(s, len); break; case FILE_DATA_LENGTH: + r = atou64(s, len, 10, &xar->file->length); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_DATA; - xar->file->length = atol10(s, len); break; case FILE_DATA_OFFSET: + r = atou64(s, len, 10, &xar->file->offset); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_DATA; - xar->file->offset = atol10(s, len); break; case FILE_DATA_SIZE: + r = atou64(s, len, 10, &xar->file->size); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_DATA; - xar->file->size = atol10(s, len); break; case FILE_DATA_A_CHECKSUM: xar->file->a_sum.len = atohex(xar->file->a_sum.val, @@ -2822,16 +2872,22 @@ xml_data(void *userData, const char *s, size_t len) sizeof(xar->file->e_sum.val), s, len); break; case FILE_EA_LENGTH: + r = atou64(s, len, 10, &xar->xattr->length); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_XATTR; - xar->xattr->length = atol10(s, len); break; case FILE_EA_OFFSET: + r = atou64(s, len, 10, &xar->xattr->offset); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_XATTR; - xar->xattr->offset = atol10(s, len); break; case FILE_EA_SIZE: + r = atou64(s, len, 10, &xar->xattr->size); + if (r != ARCHIVE_OK) + return (r); xar->file->has |= HAS_XATTR; - xar->xattr->size = atol10(s, len); break; case FILE_EA_A_CHECKSUM: xar->file->has |= HAS_XATTR; @@ -2907,6 +2963,8 @@ xml_data(void *userData, const char *s, size_t len) case UNKNOWN: break; } + + return (ARCHIVE_OK); } /* @@ -3205,7 +3263,12 @@ xml2_read_toc(struct archive_read *a) break; case XML_READER_TYPE_TEXT: value = (const char *)xmlTextReaderConstValue(reader); - xml_data(a, value, strlen(value)); + r = xml_data(a, value, strlen(value)); + if (r != ARCHIVE_OK) { + xmlFreeTextReader(reader); + xmlCleanupParser(); + return (r); + } break; case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: default: @@ -3285,7 +3348,10 @@ expat_data_cb(void *userData, const XML_Char *s, int len) { struct expat_userData *ud = (struct expat_userData *)userData; - xml_data(ud->archive, s, (size_t)len); + if (ud->state != ARCHIVE_OK) + return; + + ud->state = xml_data(ud->archive, s, (size_t)len); } static int @@ -3321,7 +3387,7 @@ expat_read_toc(struct archive_read *a) d = NULL; r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining); - if (r != ARCHIVE_OK) { + if (r != ARCHIVE_OK || outbytes > INT_MAX) { XML_ParserFree(parser); return (r); } @@ -3638,7 +3704,11 @@ xmllite_read_toc(struct archive_read *a) goto out; } - xml_data(a, as.s, (int)archive_strlen(&as)); + r = xml_data(a, as.s, archive_strlen(&as)); + if (r != ARCHIVE_OK) { + /* xml_data sets an appropriate error */ + goto out; + } archive_string_free(&as); case XmlNodeType_None: diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index 00796b288a48..fa9995d963d4 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -272,6 +272,10 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, size_t *size, int64_t *offset); #endif +static void +trad_enc_decrypt_update(struct trad_enc_ctx *, const uint8_t *, size_t, + uint8_t *, size_t); + /* This function is used by Ppmd8_DecodeSymbol during decompression of Ppmd8 * streams inside ZIP files. It has 2 purposes: one is to fetch the next * compressed byte from the stream, second one is to increase the counter how @@ -281,15 +285,32 @@ ppmd_read(void* p) { /* Get the handle to current decompression context. */ struct archive_read *a = ((IByteIn*)p)->a; struct zip *zip = (struct zip*) a->format->data; - ssize_t bytes_avail = 0; /* Fetch next byte. */ - const uint8_t* data = __archive_read_ahead(a, 1, &bytes_avail); - if(bytes_avail < 1) { + const uint8_t* data = __archive_read_ahead(a, 1, NULL); + if(data == NULL) { zip->ppmd8_stream_failed = 1; return 0; } + if (zip->tctx_valid || zip->cctx_valid) { + uint8_t val; + if (zip->tctx_valid) { + trad_enc_decrypt_update(&zip->tctx, + data, 1, &val, 1); + } else { + size_t dsize = 1; + archive_decrypto_aes_ctr_update(&zip->cctx, + data, 1, &val, &dsize); + } + if (zip->hctx_valid) + archive_hmac_sha1_update(&zip->hctx, data, 1); + + __archive_read_consume(a, 1); + ++zip->zipx_ppmd_read_compressed; + return val; + } + __archive_read_consume(a, 1); /* Increment the counter. */ @@ -401,6 +422,146 @@ crypt_derive_key_sha1(const void *p, int size, unsigned char *key, } #endif +/* Read and decrypt bytes for zipx init headers. + * Used by format-specific init functions (lzma, ppmd) that need to + * read a small header from the compressed stream. When encryption is + * active the bytes are decrypted in-place into the decryption buffer. */ +static int +zipx_read_header_and_decrypt(struct archive_read *a, const void **buf, size_t in_len, + size_t *out_len, size_t *consumed) +{ + struct zip *zip = (struct zip *)(a->format->data); + const void *raw; + ssize_t bytes_avail; + size_t to_decrypt; + + raw = __archive_read_ahead(a, in_len, &bytes_avail); + if (raw == NULL || bytes_avail < (ssize_t)in_len) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + + if (zip->tctx_valid || zip->cctx_valid) { + to_decrypt = in_len; + if (to_decrypt > zip->decrypted_buffer_size) + to_decrypt = zip->decrypted_buffer_size; + + if (zip->tctx_valid) { + trad_enc_decrypt_update(&zip->tctx, + raw, to_decrypt, + zip->decrypted_buffer, to_decrypt); + } else { + size_t dsize = to_decrypt; + archive_decrypto_aes_ctr_update(&zip->cctx, + raw, to_decrypt, + zip->decrypted_buffer, &dsize); + } + if (zip->hctx_valid) + archive_hmac_sha1_update(&zip->hctx, + raw, to_decrypt); + + *buf = zip->decrypted_buffer; + *out_len = to_decrypt; + *consumed = to_decrypt; + } else { + *buf = raw; + *out_len = in_len; + *consumed = in_len; + } + return (ARCHIVE_OK); +} + +/* Decrypt bulk compressed data for zipx decompression. + * Manages the decryption buffer, handles partial fills, and returns decrypted + * data pointer + length. `sp` is set to the raw pointer for HMAC accounting. */ +static void +zip_read_decrypt(struct zip *zip, const void *compressed_buff, + ssize_t bytes_avail, const void **result_buff, ssize_t *result_avail, + const void **sp) +{ + *sp = compressed_buff; + + if (zip->tctx_valid || zip->cctx_valid) { + if (zip->decrypted_bytes_remaining < (size_t)bytes_avail) { + size_t buff_remaining = + (zip->decrypted_buffer + + zip->decrypted_buffer_size) + - (zip->decrypted_ptr + + zip->decrypted_bytes_remaining); + /* The new bytes to decrypt start after decrypted_bytes_remaining + * in the raw stream: those leading bytes were already + * decrypted on a previous call but have not yet been consumed. */ + size_t new_bytes = + (size_t)bytes_avail + - zip->decrypted_bytes_remaining; + + if (buff_remaining > new_bytes) + buff_remaining = new_bytes; + + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) && + zip->entry_bytes_remaining > 0) { + if ((int64_t)(zip->decrypted_bytes_remaining + + buff_remaining) + > zip->entry_bytes_remaining) { + if (zip->entry_bytes_remaining < + (int64_t)zip->decrypted_bytes_remaining) + buff_remaining = 0; + else + buff_remaining = + (size_t)zip->entry_bytes_remaining + - zip->decrypted_bytes_remaining; + } + } + if (buff_remaining > 0) { + if (zip->tctx_valid) { + trad_enc_decrypt_update(&zip->tctx, + (const uint8_t *)compressed_buff + + zip->decrypted_bytes_remaining, + buff_remaining, + zip->decrypted_ptr + + zip->decrypted_bytes_remaining, + buff_remaining); + } else { + size_t dsize = buff_remaining; + archive_decrypto_aes_ctr_update( + &zip->cctx, + (const uint8_t *)compressed_buff + + zip->decrypted_bytes_remaining, + buff_remaining, + zip->decrypted_ptr + + zip->decrypted_bytes_remaining, + &dsize); + } + zip->decrypted_bytes_remaining += + buff_remaining; + } + } + *result_avail = zip->decrypted_bytes_remaining; + *result_buff = (const char *)zip->decrypted_ptr; + } else { + *result_buff = compressed_buff; + *result_avail = bytes_avail; + } +} + +/* Post-decompression decrypt state update. + * Updates decrypt buffer pointers and HMAC after the decompressor + * has consumed `to_consume` bytes. */ +static void +zip_read_decrypt_update(struct zip *zip, ssize_t to_consume, const void *sp) +{ + if (zip->tctx_valid || zip->cctx_valid) { + zip->decrypted_bytes_remaining -= to_consume; + if (zip->decrypted_bytes_remaining == 0) + zip->decrypted_ptr = zip->decrypted_buffer; + else + zip->decrypted_ptr += to_consume; + } + if (zip->hctx_valid) + archive_hmac_sha1_update(&zip->hctx, sp, to_consume); +} + /* * Common code for streaming or seeking modes. * @@ -1775,7 +1936,7 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip) * "lzma alone" decoder from XZ Utils. */ memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream)); - r = lzma_alone_decoder(&zip->zipx_lzma_stream, UINT64_MAX); + r = lzma_alone_decoder(&zip->zipx_lzma_stream, 576 * ((uint64_t)1 << 20)); if (r != LZMA_OK) { archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, "lzma initialization failed (%d)", r); @@ -1825,12 +1986,32 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip) */ /* Read magic1,magic2,lzma_params from the ZIPX stream. */ - if(zip->entry_bytes_remaining < 9 || (p = __archive_read_ahead(a, 9, NULL)) == NULL) { + if(zip->entry_bytes_remaining < 9) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzma data"); return (ARCHIVE_FATAL); } + if (zip->tctx_valid || zip->cctx_valid) { + const void *decrypted; + size_t out_len; + size_t consumed; + int ret; + + ret = zipx_read_header_and_decrypt(a, &decrypted, 9, &out_len, &consumed); + if (ret != ARCHIVE_OK) + return ret; + p = decrypted; + } else { + p = __archive_read_ahead(a, 9, NULL); + if (p == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated lzma data"); + return (ARCHIVE_FATAL); + } + } + if(p[2] != 0x05 || p[3] != 0x00) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Invalid lzma data"); @@ -1868,8 +2049,12 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip) * output bytes yet. */ r = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN); if (r != LZMA_OK) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, - "lzma stream initialization error"); + if (r == LZMA_MEMLIMIT_ERROR) + archive_set_error(&a->archive, ENOMEM, + "lzma stream requires too much memory"); + else + archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER, + "lzma stream initialization error"); return ARCHIVE_FATAL; } @@ -1890,6 +2075,7 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff, int ret; lzma_ret lz_ret; const void* compressed_buf; + const void* sp; ssize_t bytes_avail, in_bytes, to_consume = 0; (void) offset; /* UNUSED */ @@ -1901,7 +2087,7 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff, return (ret); } - compressed_buf = __archive_read_ahead(a, 1, &bytes_avail); + compressed_buf = sp = __archive_read_ahead(a, 1, &bytes_avail); if (bytes_avail < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated xz file body"); @@ -1909,6 +2095,10 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff, } in_bytes = (ssize_t)zipmin(zip->entry_bytes_remaining, bytes_avail); + + zip_read_decrypt(zip, compressed_buf, in_bytes, + &compressed_buf, &in_bytes, &sp); + zip->zipx_lzma_stream.next_in = compressed_buf; zip->zipx_lzma_stream.avail_in = in_bytes; zip->zipx_lzma_stream.total_in = 0; @@ -1957,6 +2147,16 @@ zip_read_data_zipx_xz(struct archive_read *a, const void **buff, zip->entry_compressed_bytes_read += to_consume; zip->entry_uncompressed_bytes_read += zip->zipx_lzma_stream.total_out; + zip_read_decrypt_update(zip, to_consume, sp); + + if (zip->end_of_entry) { + if (zip->hctx_valid) { + ret = check_authentication_code(a, NULL); + if (ret != ARCHIVE_OK) + return ret; + } + } + *size = (size_t)zip->zipx_lzma_stream.total_out; *buff = zip->uncompressed_buffer; @@ -1971,6 +2171,7 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, int ret; lzma_ret lz_ret; const void* compressed_buf; + const void* sp; ssize_t bytes_avail, in_bytes, to_consume; (void) offset; /* UNUSED */ @@ -2000,6 +2201,9 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, /* Set decompressor parameters. */ in_bytes = (ssize_t)zipmin(zip->entry_bytes_remaining, bytes_avail); + zip_read_decrypt(zip, compressed_buf, in_bytes, + &compressed_buf, &in_bytes, &sp); + zip->zipx_lzma_stream.next_in = compressed_buf; zip->zipx_lzma_stream.avail_in = in_bytes; zip->zipx_lzma_stream.total_in = 0; @@ -2039,6 +2243,12 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, case LZMA_OK: break; + case LZMA_BUF_ERROR: + if (zip->zipx_lzma_stream.avail_out == 0) { + zip->end_of_entry = 1; + break; + } + /* FALL THROUGH */ default: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "lzma unknown error (%d)", (int) lz_ret); @@ -2053,16 +2263,37 @@ zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff, zip->entry_compressed_bytes_read += to_consume; zip->entry_uncompressed_bytes_read += zip->zipx_lzma_stream.total_out; + zip_read_decrypt_update(zip, to_consume, sp); + if(zip->entry_bytes_remaining == 0) { zip->end_of_entry = 1; } + if(zip->end_of_entry && zip->entry_bytes_remaining > 0) { + ssize_t remaining = (ssize_t)zip->entry_bytes_remaining; + const void *p = __archive_read_ahead(a, remaining, NULL); + if (p != NULL) { + if (zip->hctx_valid) + archive_hmac_sha1_update(&zip->hctx, + p, remaining); + __archive_read_consume(a, remaining); + zip->entry_compressed_bytes_read += remaining; + zip->entry_bytes_remaining = 0; + } + } + /* Free lzma decoder handle because we'll no longer need it. */ /* This cannot be folded into LZMA_STREAM_END handling above * because the stream end marker is not required in this format. */ if(zip->end_of_entry) { lzma_end(&zip->zipx_lzma_stream); zip->zipx_lzma_valid = 0; + + if (zip->hctx_valid) { + ret = check_authentication_code(a, NULL); + if (ret != ARCHIVE_OK) + return ret; + } } /* Return values. */ @@ -2104,11 +2335,22 @@ zipx_ppmd8_init(struct archive_read *a, struct zip *zip) zip->zipx_ppmd_read_compressed = 0; /* Read Ppmd8 header (2 bytes). */ - p = __archive_read_ahead(a, 2, NULL); - if(!p) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated file data in PPMd8 stream"); - return (ARCHIVE_FATAL); + if (zip->tctx_valid || zip->cctx_valid) { + size_t out_len; + size_t consumed; + int ret; + + ret = zipx_read_header_and_decrypt(a, &p, 2, &out_len, &consumed); + if (ret != ARCHIVE_OK) + return ret; + } else { + p = __archive_read_ahead(a, 2, NULL); + if(!p) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated file data in PPMd8 stream"); + return (ARCHIVE_FATAL); + } } __archive_read_consume(a, 2); @@ -2178,7 +2420,6 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff, struct zip* zip = (struct zip *)(a->format->data); int ret; size_t consumed_bytes = 0; - ssize_t bytes_avail = 0; (void) offset; /* UNUSED */ @@ -2192,8 +2433,7 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff, /* Fetch for more data. We're reading 1 byte here, but libarchive * should prefetch more bytes. */ - (void) __archive_read_ahead(a, 1, &bytes_avail); - if(bytes_avail < 0) { + if(__archive_read_ahead(a, 1, NULL) == NULL) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated PPMd8 file body"); return (ARCHIVE_FATAL); @@ -2234,6 +2474,12 @@ zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff, if(zip->end_of_entry) { __archive_ppmd8_functions.Ppmd8_Free(&zip->ppmd8); zip->ppmd8_valid = 0; + + if (zip->hctx_valid) { + int r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) + return (r); + } } /* Update pointers for libarchive. */ @@ -2293,6 +2539,7 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff, struct zip *zip = (struct zip *)(a->format->data); ssize_t bytes_avail = 0, in_bytes, to_consume; const void *compressed_buff; + const void *sp; int r; uint64_t total_out; @@ -2325,6 +2572,9 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff, return (ARCHIVE_FATAL); } + zip_read_decrypt(zip, compressed_buff, in_bytes, + &compressed_buff, &in_bytes, &sp); + /* Setup buffer boundaries. */ zip->bzstream.next_in = (char*)(uintptr_t) compressed_buff; zip->bzstream.avail_in = (uint32_t)in_bytes; @@ -2375,6 +2625,14 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff, zip->entry_compressed_bytes_read += to_consume; zip->entry_uncompressed_bytes_read += total_out; + zip_read_decrypt_update(zip, to_consume, sp); + + if (zip->end_of_entry && zip->hctx_valid) { + r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) + return r; + } + /* Give libarchive its due. */ *size = (size_t)total_out; *buff = zip->uncompressed_buffer; @@ -2436,6 +2694,7 @@ zip_read_data_zipx_zstd(struct archive_read *a, const void **buff, struct zip *zip = (struct zip *)(a->format->data); ssize_t bytes_avail = 0, in_bytes, to_consume; const void *compressed_buff; + const void *sp; int r; size_t ret; uint64_t total_out; @@ -2452,7 +2711,7 @@ zip_read_data_zipx_zstd(struct archive_read *a, const void **buff, } /* Fetch more compressed bytes */ - compressed_buff = __archive_read_ahead(a, 1, &bytes_avail); + compressed_buff = sp = __archive_read_ahead(a, 1, &bytes_avail); if(bytes_avail < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated zstd file body"); @@ -2470,6 +2729,9 @@ zip_read_data_zipx_zstd(struct archive_read *a, const void **buff, return (ARCHIVE_FATAL); } + zip_read_decrypt(zip, compressed_buff, in_bytes, + &compressed_buff, &in_bytes, &sp); + /* Setup buffer boundaries */ in.src = compressed_buff; in.size = in_bytes; @@ -2504,6 +2766,14 @@ zip_read_data_zipx_zstd(struct archive_read *a, const void **buff, zip->entry_compressed_bytes_read += to_consume; zip->entry_uncompressed_bytes_read += total_out; + zip_read_decrypt_update(zip, to_consume, sp); + + if (zip->end_of_entry && zip->hctx_valid) { + r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) + return r; + } + /* Give libarchive its due. */ *size = (size_t)total_out; *buff = zip->uncompressed_buffer; @@ -2544,7 +2814,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, { struct zip *zip; ssize_t bytes_avail, to_consume = 0; - const void *compressed_buff, *sp; + const void *compressed_buff; + const void *sp; int r; (void)offset; /* UNUSED */ @@ -2584,54 +2855,8 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, return (ARCHIVE_FATAL); } - if (zip->tctx_valid || zip->cctx_valid) { - if (zip->decrypted_bytes_remaining < (size_t)bytes_avail) { - size_t buff_remaining = - (zip->decrypted_buffer + - zip->decrypted_buffer_size) - - (zip->decrypted_ptr + - zip->decrypted_bytes_remaining); - - if (buff_remaining > (size_t)bytes_avail) - buff_remaining = (size_t)bytes_avail; - - if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) && - zip->entry_bytes_remaining > 0) { - if ((int64_t)(zip->decrypted_bytes_remaining - + buff_remaining) - > zip->entry_bytes_remaining) { - if (zip->entry_bytes_remaining < - (int64_t)zip->decrypted_bytes_remaining) - buff_remaining = 0; - else - buff_remaining = - (size_t)zip->entry_bytes_remaining - - zip->decrypted_bytes_remaining; - } - } - if (buff_remaining > 0) { - if (zip->tctx_valid) { - trad_enc_decrypt_update(&zip->tctx, - compressed_buff, buff_remaining, - zip->decrypted_ptr - + zip->decrypted_bytes_remaining, - buff_remaining); - } else { - size_t dsize = buff_remaining; - archive_decrypto_aes_ctr_update( - &zip->cctx, - compressed_buff, buff_remaining, - zip->decrypted_ptr - + zip->decrypted_bytes_remaining, - &dsize); - } - zip->decrypted_bytes_remaining += - buff_remaining; - } - } - bytes_avail = zip->decrypted_bytes_remaining; - compressed_buff = (const char *)zip->decrypted_ptr; - } + zip_read_decrypt(zip, compressed_buff, bytes_avail, + &compressed_buff, &bytes_avail, &sp); /* * A bug in zlib.h: stream.next_in should be marked 'const' @@ -2670,22 +2895,12 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, zip->entry_compressed_bytes_read += to_consume; zip->entry_uncompressed_bytes_read += zip->stream.total_out; - if (zip->tctx_valid || zip->cctx_valid) { - zip->decrypted_bytes_remaining -= to_consume; - if (zip->decrypted_bytes_remaining == 0) - zip->decrypted_ptr = zip->decrypted_buffer; - else - zip->decrypted_ptr += to_consume; - } - if (zip->hctx_valid) - archive_hmac_sha1_update(&zip->hctx, sp, to_consume); + zip_read_decrypt_update(zip, to_consume, sp); - if (zip->end_of_entry) { - if (zip->hctx_valid) { - r = check_authentication_code(a, NULL); - if (r != ARCHIVE_OK) { - return (r); - } + if (zip->end_of_entry && zip->hctx_valid) { + r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) { + return r; } } diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c index c6ae8968d54f..bbcec444b843 100644 --- a/libarchive/archive_string.c +++ b/libarchive/archive_string.c @@ -1314,7 +1314,17 @@ create_sconv_object(const char *fc, const char *tc, else if (strcmp(fc, "CP932") == 0) sc->cd = iconv_open(tc, "SJIS"); } -#if defined(_WIN32) && !defined(__CYGWIN__) +#if defined(__FreeBSD__) && !defined(HAVE_LIBICONV) + /* + * FreeBSD's native iconv() by default returns the number of + * invalid characters in the input string, as specified by + * POSIX, but iconv_strncat_in_locale() assumes GNU iconv + * semantics. + */ + int v = 1; + + (void)iconvctl(sc->cd, ICONV_SET_ILSEQ_INVALID, &v); +#elif defined(_WIN32) && !defined(__CYGWIN__) /* * archive_mstring on Windows directly convert multi-bytes * into archive_wstring in order not to depend on locale @@ -1362,7 +1372,7 @@ free_sconv_object(struct archive_string_conv *sc) } #if defined(_WIN32) && !defined(__CYGWIN__) -# if defined(WINAPI_FAMILY_PARTITION) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) # define GetOEMCP() CP_OEMCP # endif diff --git a/libarchive/archive_time.c b/libarchive/archive_time.c index 3352c809bd11..bc7708288976 100644 --- a/libarchive/archive_time.c +++ b/libarchive/archive_time.c @@ -24,11 +24,20 @@ */ #include "archive_platform.h" -#include "archive_private.h" -#include "archive_time_private.h" + +#ifdef HAVE_LIMITS_H #include <limits.h> +#endif +#ifdef HAVE_STDLIB_H #include <stdlib.h> +#endif +#ifdef HAVE_STRING_H #include <string.h> +#endif + +#include "archive_integer.h" +#include "archive_private.h" +#include "archive_time_private.h" #define NTFS_EPOC_TIME ARCHIVE_LITERAL_ULL(11644473600) #define NTFS_TICKS ARCHIVE_LITERAL_ULL(10000000) @@ -149,15 +158,11 @@ unix_to_ntfs(int64_t secs, uint32_t nsecs) if (secs < -(int64_t)NTFS_EPOC_TIME) return 0; - ntfs = secs + NTFS_EPOC_TIME; - - if (ntfs > UINT64_MAX / NTFS_TICKS) - return UINT64_MAX; - - ntfs *= NTFS_TICKS; - - if (ntfs > UINT64_MAX - nsecs/100) + /* (secs + NTFS_EPOC_TIME) * NTFS_TICKS + nsecs / 100 */ + if (archive_ckd_add_u64(&ntfs, secs, NTFS_EPOC_TIME) || + archive_ckd_mul_u64(&ntfs, ntfs, NTFS_TICKS) || + archive_ckd_add_u64(&ntfs, ntfs, nsecs / 100)) return UINT64_MAX; - return ntfs + nsecs/100; + return ntfs; } diff --git a/libarchive/archive_util.3 b/libarchive/archive_util.3 index 3aa508f25aa2..26026d432302 100644 --- a/libarchive/archive_util.3 +++ b/libarchive/archive_util.3 @@ -33,12 +33,15 @@ .Nm archive_errno , .Nm archive_error_string , .Nm archive_file_count , +.Nm archive_filter_bytes , .Nm archive_filter_code , .Nm archive_filter_count , .Nm archive_filter_name , .Nm archive_format , .Nm archive_format_name , -.Nm archive_position , +.Nm archive_free , +.Nm archive_position_compressed , +.Nm archive_position_uncompressed , .Nm archive_set_error .Nd libarchive utility functions .Sh LIBRARY @@ -59,6 +62,8 @@ Streaming Archive Library (libarchive, -larchive) .Fn archive_error_string "struct archive *" .Ft int .Fn archive_file_count "struct archive *" +.Ft int64_t +.Fn archive_filter_bytes "struct archive *" "int" .Ft int .Fn archive_filter_code "struct archive *" "int" .Ft int @@ -69,8 +74,12 @@ Streaming Archive Library (libarchive, -larchive) .Fn archive_format "struct archive *" .Ft const char * .Fn archive_format_name "struct archive *" +.Ft int +.Fn archive_free "struct archive *" +.Ft int64_t +.Fn archive_position_compressed "struct archive *" .Ft int64_t -.Fn archive_position "struct archive *" "int" +.Fn archive_position_uncompressed "struct archive *" .Ft void .Fo archive_set_error .Fa "struct archive *" @@ -140,13 +149,13 @@ filter 0 is the gunzip filter, filter 1 is the uudecode filter, and filter 2 is the pseudo-filter that wraps the archive read functions. In this case, requesting -.Fn archive_position a -1 +.Fn archive_filter_bytes a -1 would be a synonym for -.Fn archive_position a 2 +.Fn archive_filter_bytes a 2 which would return the number of bytes currently read from the archive, while -.Fn archive_position a 1 +.Fn archive_filter_bytes a 1 would return the number of bytes after uudecoding, and -.Fn archive_position a 0 +.Fn archive_filter_bytes a 0 would return the number of bytes after decompression. .It Fn archive_filter_name Returns a textual name identifying the indicated filter. @@ -165,16 +174,24 @@ utilize GNU tar extensions and several entries that do not. These entries will have different format codes. .It Fn archive_format_name A textual description of the format of the current entry. -.It Fn archive_position +.It Fn archive_free +Closes the archive if necessary, then releases all resources. +.It Fn archive_filter_bytes Returns the number of bytes read from or written to the indicated filter. In particular, -.Fn archive_position a 0 +.Fn archive_filter_bytes a 0 returns the number of bytes read or written by the format handler, while -.Fn archive_position a -1 +.Fn archive_filter_bytes a -1 returns the number of bytes read or written to the archive. See .Fn archive_filter_count for details of the numbering here. +.It Fn archive_position_compressed +Synonym for +.Fn archive_filter_bytes a -1 . +.It Fn archive_position_uncompressed +Synonym for +.Fn archive_filter_bytes a 0 . .It Fn archive_set_error Sets the numeric error code and error description that will be returned by diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c index 0d1de1ef2091..5e0b916de432 100644 --- a/libarchive/archive_util.c +++ b/libarchive/archive_util.c @@ -42,18 +42,12 @@ #include <string.h> #endif #if defined(_WIN32) && !defined(__CYGWIN__) -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA -/* don't use bcrypt when XP needs to be supported */ #include <bcrypt.h> /* Common in other bcrypt implementations, but missing from VS2008. */ #ifndef BCRYPT_SUCCESS #define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS) #endif - -#elif defined(HAVE_WINCRYPT_H) -#include <wincrypt.h> -#endif #endif #ifdef HAVE_ZLIB_H #include <zlib.h> @@ -110,8 +104,7 @@ archive_errno(struct archive *a) const char * archive_error_string(struct archive *a) { - - if (a->error != NULL && *a->error != '\0') + if (a->error != NULL && *a->error != '\0') return (a->error); else return (NULL); @@ -250,11 +243,7 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) DWORD attr; wchar_t *xp, *ep; int fd; -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA BCRYPT_ALG_HANDLE hAlg = NULL; -#else - HCRYPTPROV hProv = (HCRYPTPROV)NULL; -#endif fd = -1; ws = NULL; archive_string_init(&temp_name); @@ -262,22 +251,36 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) if (template == NULL) { /* Get a temporary directory. */ if (tmpdir == NULL) { - size_t l; - wchar_t *tmp; + wchar_t buf[MAX_PATH + 1]; + wchar_t *p = buf, *buf2 = NULL; + size_t l, s; - l = GetTempPathW(0, NULL); + s = MAX_PATH + 1; + l = GetTempPathW((DWORD)s, buf); if (l == 0) { la_dosmaperr(GetLastError()); goto exit_tmpfile; } - tmp = malloc(l*sizeof(wchar_t)); - if (tmp == NULL) { - errno = ENOMEM; - goto exit_tmpfile; + while (l > s) { + wchar_t *tmp; + + s = l; + tmp = realloc(buf2, s * sizeof(wchar_t)); + if (tmp == NULL) { + free(buf2); + errno = ENOMEM; + goto exit_tmpfile; + } + p = buf2 = tmp; + l = GetTempPathW((DWORD)s, buf2); + if (l == 0) { + free(buf2); + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } } - GetTempPathW((DWORD)l, tmp); - archive_wstrcpy(&temp_name, tmp); - free(tmp); + archive_wstrcpy(&temp_name, p); + free(buf2); } else { if (archive_wstring_append_from_mbs(&temp_name, tmpdir, strlen(tmpdir)) < 0) @@ -328,19 +331,11 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) abort(); } -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, NULL, 0))) { la_dosmaperr(GetLastError()); goto exit_tmpfile; } -#else - if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - la_dosmaperr(GetLastError()); - goto exit_tmpfile; - } -#endif for (;;) { wchar_t *p; @@ -351,19 +346,11 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) /* Generate a random file name through CryptGenRandom(). */ p = xp; -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA if (!BCRYPT_SUCCESS(BCryptGenRandom(hAlg, (PUCHAR)p, (DWORD)(ep - p)*sizeof(wchar_t), 0))) { la_dosmaperr(GetLastError()); goto exit_tmpfile; } -#else - if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t), - (BYTE*)p)) { - la_dosmaperr(GetLastError()); - goto exit_tmpfile; - } -#endif for (; p < ep; p++) *p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))]; @@ -417,13 +404,8 @@ __archive_mktempx(const char *tmpdir, wchar_t *template) break;/* success! */ } exit_tmpfile: -#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA if (hAlg != NULL) BCryptCloseAlgorithmProvider(hAlg, 0); -#else - if (hProv != (HCRYPTPROV)NULL) - CryptReleaseContext(hProv, 0); -#endif free(ws); if (template == temp_name.s) archive_wstring_free(&temp_name); diff --git a/libarchive/archive_version_details.c b/libarchive/archive_version_details.c index 9063faa79426..be11aad67e2e 100644 --- a/libarchive/archive_version_details.c +++ b/libarchive/archive_version_details.c @@ -158,10 +158,6 @@ archive_crypto_version(struct archive_string* str) archive_strcat(str, " libmd/"); archive_strcat(str, archive_libmd_version()); #endif -#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) - archive_strcat(str, " WinCrypt/"); - archive_strcat(str, archive_wincrypt_version()); -#endif // Just in case (void)str; /* UNUSED */ } @@ -180,7 +176,7 @@ archive_version_details(void) const char *libiconv = archive_libiconv_version(); const char *libacl = archive_libacl_version(); const char *librichacl = archive_librichacl_version(); - const char *libattr = archive_libacl_version(); + const char *libattr = archive_libattr_version(); if (!init) { archive_string_init(&str); @@ -234,6 +230,7 @@ archive_version_details(void) archive_strcat(&str, " libiconv/"); archive_strcat(&str, libiconv); } + init = 1; } return str.s; } @@ -431,27 +428,7 @@ archive_cng_version(void) const char * archive_wincrypt_version(void) { -#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) || defined(ARCHIVE_CRYPTO_WINCRYPT) - HCRYPTPROV prov; - if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - if (GetLastError() != (DWORD)NTE_BAD_KEYSET) - return NULL; - if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) - return NULL; - } - DWORD version, length = sizeof(version); - if (!CryptGetProvParam(prov, PP_VERSION, (BYTE *)&version, &length, 0)) { - return NULL; - } else { - char major = (version >> 8) & 0xFF; - char minor = version & 0xFF; - static char wincrypt_version[6]; - snprintf(wincrypt_version, 6, "%hhd.%hhd", major, minor); - return wincrypt_version; - } -#else return NULL; -#endif } const char * diff --git a/libarchive/archive_windows.c b/libarchive/archive_windows.c index 3fbea6c5b6dd..b787a0d37688 100644 --- a/libarchive/archive_windows.c +++ b/libarchive/archive_windows.c @@ -63,23 +63,6 @@ #include <windows.h> #include <share.h> -#if defined(__LA_LSEEK_NEEDED) -static BOOL SetFilePointerEx_perso(HANDLE hFile, - LARGE_INTEGER liDistanceToMove, - PLARGE_INTEGER lpNewFilePointer, - DWORD dwMoveMethod) -{ - LARGE_INTEGER li; - li.QuadPart = liDistanceToMove.QuadPart; - li.LowPart = SetFilePointer( - hFile, li.LowPart, &li.HighPart, dwMoveMethod); - if(lpNewFilePointer) { - lpNewFilePointer->QuadPart = li.QuadPart; - } - return li.LowPart != -1 || GetLastError() == NO_ERROR; -} -#endif - struct ustat { int64_t st_atime; uint32_t st_atime_nsec; @@ -236,7 +219,7 @@ la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode, CREATEFILE2_EXTENDED_PARAMETERS createExParams; #endif -#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) +#if WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) handle = CreateFileA(path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); @@ -285,7 +268,7 @@ __la_lseek(int fd, __int64 offset, int whence) return (-1); } distance.QuadPart = offset; - if (!SetFilePointerEx_perso(handle, distance, &newpointer, whence)) { + if (!SetFilePointerEx(handle, distance, &newpointer, whence)) { DWORD lasterr; lasterr = GetLastError(); @@ -324,7 +307,7 @@ __la_open(const char *path, int flags, ...) * "Permission denied" error. */ attr = GetFileAttributesA(path); -#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) +#if WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) if (attr == (DWORD)-1 && GetLastError() == ERROR_PATH_NOT_FOUND) #endif { @@ -342,7 +325,7 @@ __la_open(const char *path, int flags, ...) } if (attr & FILE_ATTRIBUTE_DIRECTORY) { HANDLE handle; -#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) +#if WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) if (ws != NULL) handle = CreateFileW(ws, 0, 0, NULL, OPEN_EXISTING, @@ -437,7 +420,7 @@ __la_wopen(const wchar_t *path, int flags, ...) * "Permission denied" error. */ attr = GetFileAttributesW(path); -#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) +#if WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) if (attr == (DWORD)-1 && GetLastError() == ERROR_PATH_NOT_FOUND) #endif { @@ -456,7 +439,7 @@ __la_wopen(const wchar_t *path, int flags, ...) } if (attr & FILE_ATTRIBUTE_DIRECTORY) { HANDLE handle; -#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) +#if WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) if (fullpath != NULL) handle = CreateFileW(fullpath, 0, 0, NULL, OPEN_EXISTING, diff --git a/libarchive/archive_windows.h b/libarchive/archive_windows.h index ecb14e01087b..fef7cf90df4c 100644 --- a/libarchive/archive_windows.h +++ b/libarchive/archive_windows.h @@ -299,6 +299,26 @@ typedef int mbstate_t; size_t wcrtomb(char *, wchar_t, mbstate_t *); #endif +#ifndef WINAPI_FAMILY_PARTITION +#define WINAPI_FAMILY_PARTITION(x) (x) +#endif + +#ifndef WINAPI_PARTITION_DESKTOP +#define WINAPI_PARTITION_DESKTOP 1 +#endif + +#ifndef WINAPI_PARTITION_SYSTEM +#define WINAPI_PARTITION_SYSTEM 1 +#endif + +#ifndef NTDDI_VERSION +#define NTDDI_VERSION 0x05020000 +#endif + +#ifndef NTDDI_WIN10_VB +#define NTDDI_WIN10_VB 0x0A000008 +#endif + #if !WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP) && NTDDI_VERSION < NTDDI_WIN10_VB // not supported in UWP SDK before 20H1 #define GetVolumePathNameW(f, v, c) (0) @@ -309,17 +329,4 @@ WINBASEAPI BOOL WINAPI GetVolumePathNameW( DWORD cchBufferLength ); #endif -#if defined(_MSC_VER) && _MSC_VER < 1300 -# if _WIN32_WINNT < 0x0500 /* windows.h not providing 0x500 API */ -typedef struct _FILE_ALLOCATED_RANGE_BUFFER { - LARGE_INTEGER FileOffset; - LARGE_INTEGER Length; -} FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER; -# define FSCTL_SET_SPARSE \ - CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_WRITE_DATA) -# define FSCTL_QUERY_ALLOCATED_RANGES \ - CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 51, METHOD_NEITHER, FILE_READ_DATA) -# endif -#endif - #endif /* !LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED */ diff --git a/libarchive/archive_write.c b/libarchive/archive_write.c index 14dc7339ec5a..68f452ec30e3 100644 --- a/libarchive/archive_write.c +++ b/libarchive/archive_write.c @@ -761,7 +761,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry) archive_entry_ino_is_set(entry) && archive_entry_dev(entry) == (dev_t)a->skip_file_dev && archive_entry_ino64(entry) == a->skip_file_ino) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EIO, "Can't add archive to itself"); return (ARCHIVE_FAILED); } diff --git a/libarchive/archive_write_add_filter.c b/libarchive/archive_write_add_filter.c index aa962515a044..ddcf2825385a 100644 --- a/libarchive/archive_write_add_filter.c +++ b/libarchive/archive_write_add_filter.c @@ -49,7 +49,7 @@ struct { int code; int (*setter)(struct archive *); } codes[] = { ARCHIVE_FILTER_LZ4, archive_write_add_filter_lz4 }, { ARCHIVE_FILTER_LZIP, archive_write_add_filter_lzip }, { ARCHIVE_FILTER_LZMA, archive_write_add_filter_lzma }, - { ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzip }, + { ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzop }, { ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode }, { ARCHIVE_FILTER_XZ, archive_write_add_filter_xz }, { ARCHIVE_FILTER_ZSTD, archive_write_add_filter_zstd }, diff --git a/libarchive/archive_write_add_filter_b64encode.c b/libarchive/archive_write_add_filter_b64encode.c index d2c4742d2ef6..2c4e5ba6ee50 100644 --- a/libarchive/archive_write_add_filter_b64encode.c +++ b/libarchive/archive_write_add_filter_b64encode.c @@ -39,6 +39,7 @@ #endif #include "archive.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_string.h" #include "archive_write_private.h" @@ -308,10 +309,9 @@ atol8(const char *p, size_t char_cnt) else return (-1); p++; - if (l > (INT64_MAX >> 3)) + if (archive_ckd_mul_i64(&l, l, 8) || + archive_ckd_add_i64(&l, l, digit)) return (-1); - l <<= 3; - l |= digit; } return (l); } diff --git a/libarchive/archive_write_add_filter_bzip2.c b/libarchive/archive_write_add_filter_bzip2.c index 94b342d41b74..209b15285415 100644 --- a/libarchive/archive_write_add_filter_bzip2.c +++ b/libarchive/archive_write_add_filter_bzip2.c @@ -57,7 +57,6 @@ struct private_data { int compression_level; #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) bz_stream stream; - int64_t total_in; char *compressed; size_t compressed_buffer_size; #else @@ -239,9 +238,6 @@ archive_compressor_bzip2_write(struct archive_write_filter *f, { struct private_data *data = (struct private_data *)f->data; - /* Update statistics */ - data->total_in += length; - /* Compress input data to output buffer */ SET_NEXT_IN(data, buff); data->stream.avail_in = (uint32_t)length; diff --git a/libarchive/archive_write_add_filter_gzip.c b/libarchive/archive_write_add_filter_gzip.c index 0a2f22408bad..7112ef372862 100644 --- a/libarchive/archive_write_add_filter_gzip.c +++ b/libarchive/archive_write_add_filter_gzip.c @@ -40,6 +40,7 @@ #endif #include "archive.h" +#include "archive_endian.h" #include "archive_private.h" #include "archive_string.h" #include "archive_write_private.h" @@ -61,7 +62,7 @@ struct private_data { char *original_filename; #ifdef HAVE_ZLIB_H z_stream stream; - int64_t total_in; + uint64_t total_in; unsigned char *compressed; size_t compressed_buffer_size; unsigned long crc; @@ -178,7 +179,7 @@ archive_compressor_gzip_options(struct archive_write_filter *f, const char *key, if (value) { data->original_filename = strdup(value); if (data->original_filename == NULL) - return (ARCHIVE_WARN); + return (ARCHIVE_FAILED); } return (ARCHIVE_OK); } @@ -230,11 +231,8 @@ archive_compressor_gzip_open(struct archive_write_filter *f) data->compressed[2] = 0x08; /* "Deflate" compression */ data->compressed[3] = 0x00; /* Flags */ if (data->timestamp >= 0) { - time_t t = time(NULL); - data->compressed[4] = (uint8_t)(t)&0xff; /* Timestamp */ - data->compressed[5] = (uint8_t)(t>>8)&0xff; - data->compressed[6] = (uint8_t)(t>>16)&0xff; - data->compressed[7] = (uint8_t)(t>>24)&0xff; + uint32_t t = (uint32_t)time(NULL); + archive_le32enc(data->compressed + 4, t); /* Timestamp */ } else { memset(&data->compressed[4], 0, 4); } @@ -253,9 +251,9 @@ archive_compressor_gzip_open(struct archive_write_filter *f) /* Limit "original filename" to 32k or the * remaining space in the buffer, whichever is smaller. */ - int ofn_length = strlen(data->original_filename); - int ofn_max_length = 32768; - int ofn_space_available = data->compressed + size_t ofn_length = strlen(data->original_filename); + size_t ofn_max_length = 32768; + size_t ofn_space_available = data->compressed + data->compressed_buffer_size - data->stream.next_out - 1; @@ -358,14 +356,8 @@ archive_compressor_gzip_close(struct archive_write_filter *f) } if (ret == ARCHIVE_OK) { /* Build and write out 8-byte trailer. */ - trailer[0] = (uint8_t)(data->crc)&0xff; - trailer[1] = (uint8_t)(data->crc >> 8)&0xff; - trailer[2] = (uint8_t)(data->crc >> 16)&0xff; - trailer[3] = (uint8_t)(data->crc >> 24)&0xff; - trailer[4] = (uint8_t)(data->total_in)&0xff; - trailer[5] = (uint8_t)(data->total_in >> 8)&0xff; - trailer[6] = (uint8_t)(data->total_in >> 16)&0xff; - trailer[7] = (uint8_t)(data->total_in >> 24)&0xff; + archive_le32enc(trailer, data->crc); + archive_le32enc(trailer + 4, data->total_in); ret = __archive_write_filter(f->next_filter, trailer, 8); } diff --git a/libarchive/archive_write_add_filter_lz4.c b/libarchive/archive_write_add_filter_lz4.c index efc408e2a3f8..de5283f15658 100644 --- a/libarchive/archive_write_add_filter_lz4.c +++ b/libarchive/archive_write_add_filter_lz4.c @@ -61,7 +61,6 @@ struct private_data { unsigned preset_dictionary:1; unsigned block_maximum_size:3; #if defined(HAVE_LIBLZ4) && LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 2 - int64_t total_in; char *out; char *out_buffer; size_t out_buffer_size; @@ -88,7 +87,7 @@ static int archive_filter_lz4_write(struct archive_write_filter *, const void *, size_t); /* - * Add a lz4 compression filter to this write handle. + * Add an lz4 compression filter to this write handle. */ int archive_write_add_filter_lz4(struct archive *_a) @@ -228,7 +227,7 @@ archive_filter_lz4_open(struct archive_write_filter *f) { struct private_data *data = (struct private_data *)f->data; size_t required_size; - static size_t const bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024, + static const size_t bkmap[] = { 64 * 1024, 256 * 1024, 1 * 1024 * 1024, 4 * 1024 * 1024 }; size_t pre_block_size; @@ -243,7 +242,7 @@ archive_filter_lz4_open(struct archive_write_filter *f) free(data->out_buffer); if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { /* Buffer size should be a multiple number of - * the of bytes per block for performance. */ + * the bytes per block for performance. */ bpb = archive_write_get_bytes_per_block(f->archive); if (bpb > bs) bs = bpb; @@ -306,9 +305,6 @@ archive_filter_lz4_write(struct archive_write_filter *f, data->header_written = 1; } - /* Update statistics */ - data->total_in += length; - p = (const char *)buff; remaining = length; while (remaining) { @@ -417,9 +413,11 @@ lz4_write_stream_descriptor(struct archive_write_filter *f) sd[5] = (data->block_maximum_size << 4); sd[6] = (__archive_xxhash.XXH32(&sd[4], 2, 0) >> 8) & 0xff; data->out += 7; - if (data->stream_checksum) + if (data->stream_checksum) { data->xxh32_state = __archive_xxhash.XXH32_init(0); - else + if (data->xxh32_state == NULL) + return (ARCHIVE_FATAL); + } else data->xxh32_state = NULL; return (ARCHIVE_OK); } diff --git a/libarchive/archive_write_add_filter_program.c b/libarchive/archive_write_add_filter_program.c index f12db3373883..cb92dc04f0d1 100644 --- a/libarchive/archive_write_add_filter_program.c +++ b/libarchive/archive_write_add_filter_program.c @@ -184,6 +184,10 @@ __archive_write_program_allocate(const char *program) data->child_stdin = -1; data->child_stdout = -1; data->program_name = strdup(program); + if (data->program_name == NULL) { + free(data); + return (NULL); + } return (data); } diff --git a/libarchive/archive_write_add_filter_uuencode.c b/libarchive/archive_write_add_filter_uuencode.c index d25236fa9b26..b338b4aff083 100644 --- a/libarchive/archive_write_add_filter_uuencode.c +++ b/libarchive/archive_write_add_filter_uuencode.c @@ -39,6 +39,7 @@ #endif #include "archive.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_string.h" #include "archive_write_private.h" @@ -299,10 +300,9 @@ atol8(const char *p, size_t char_cnt) else return (-1); p++; - if (l > (INT64_MAX >> 3)) + if (archive_ckd_mul_i64(&l, l, 8) || + archive_ckd_add_i64(&l, l, digit)) return (-1); - l <<= 3; - l |= digit; } return (l); } diff --git a/libarchive/archive_write_add_filter_zstd.c b/libarchive/archive_write_add_filter_zstd.c index 7149abb2b8a8..2c6b91eba18a 100644 --- a/libarchive/archive_write_add_filter_zstd.c +++ b/libarchive/archive_write_add_filter_zstd.c @@ -73,7 +73,6 @@ struct private_data { size_t cur_frame; size_t cur_frame_in; size_t cur_frame_out; - size_t total_in; ZSTD_CStream *cstream; ZSTD_outBuffer out; #else @@ -505,7 +504,6 @@ drive_compressor(struct archive_write_filter *f, data->state = running; break; } - data->total_in += in.pos - ipos; data->cur_frame_in += in.pos - ipos; data->cur_frame_out += data->out.pos - opos; if (data->state == running) { diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c index 7b90fc25fa54..df46a5cc59ca 100644 --- a/libarchive/archive_write_disk_posix.c +++ b/libarchive/archive_write_disk_posix.c @@ -308,6 +308,10 @@ struct archive_write_disk { int stream_valid; int decmpfs_compression_level; #endif +#if !(ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX ||\ + ARCHIVE_XATTR_FREEBSD) + int warning_done; +#endif }; /* @@ -596,11 +600,12 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) a->pst = NULL; a->current_fixup = NULL; a->deferred = 0; - if (a->entry) { - archive_entry_free(a->entry); - a->entry = NULL; - } + archive_entry_free(a->entry); a->entry = archive_entry_clone(entry); + if (a->entry == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } a->fd = -1; a->fd_offset = 0; a->offset = 0; @@ -971,7 +976,7 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size) return (ARCHIVE_OK); if (a->filesize == 0 || a->fd < 0) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EIO, "Attempt to write to an empty file"); return (ARCHIVE_WARN); } @@ -1595,7 +1600,7 @@ hfs_write_data_block(struct archive_write_disk *a, const char *buff, return (ARCHIVE_OK); if (a->filesize == 0 || a->fd < 0) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EIO, "Attempt to write to an empty file"); return (ARCHIVE_WARN); } @@ -1674,7 +1679,7 @@ _archive_write_disk_data_block(struct archive *_a, if (r < ARCHIVE_OK) return (r); if ((size_t)r < size) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EOVERFLOW, "Too much data: Truncating file at %ju bytes", (uintmax_t)a->filesize); return (ARCHIVE_WARN); @@ -2196,7 +2201,7 @@ restore_entry(struct archive_write_disk *a) if (a->skip_file_set && a->st.st_dev == (dev_t)a->skip_file_dev && a->st.st_ino == (ino_t)a->skip_file_ino) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EIO, "Refusing to overwrite archive"); return (ARCHIVE_FAILED); } @@ -2996,7 +3001,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, */ /* if (!S_ISLNK(path)) { - fsobj_error(a_eno, a_estr, 0, + fsobj_error(a_eno, a_estr, -1, "Removing symlink ", path); } */ @@ -3012,7 +3017,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, #endif if (r != 0) { tail[0] = c; - fsobj_error(a_eno, a_estr, 0, + fsobj_error(a_eno, a_estr, EIO, "Cannot remove intervening " "symlink ", path); res = ARCHIVE_FAILED; @@ -3072,7 +3077,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, head = tail + 1; } else { tail[0] = c; - fsobj_error(a_eno, a_estr, 0, + fsobj_error(a_eno, a_estr, ELOOP, "Cannot extract through " "symlink ", path); res = ARCHIVE_FAILED; @@ -3080,7 +3085,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, } } else { tail[0] = c; - fsobj_error(a_eno, a_estr, 0, + fsobj_error(a_eno, a_estr, ELOOP, "Cannot extract through symlink ", path); res = ARCHIVE_FAILED; break; @@ -4693,12 +4698,10 @@ set_xattrs(struct archive_write_disk *a) static int set_xattrs(struct archive_write_disk *a) { - static int warning_done = 0; - /* If there aren't any extended attributes, then it's okay not * to extract them, otherwise, issue a single warning. */ - if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) { - warning_done = 1; + if (archive_entry_xattr_count(a->entry) != 0 && !a->warning_done) { + a->warning_done = 1; archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Cannot restore extended attributes on this system"); return (ARCHIVE_WARN); diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c index 8a970de1ad04..435f0cdb9ced 100644 --- a/libarchive/archive_write_disk_windows.c +++ b/libarchive/archive_write_disk_windows.c @@ -70,21 +70,6 @@ #define IO_REPARSE_TAG_SYMLINK 0xA000000CL #endif -static BOOL SetFilePointerEx_perso(HANDLE hFile, - LARGE_INTEGER liDistanceToMove, - PLARGE_INTEGER lpNewFilePointer, - DWORD dwMoveMethod) -{ - LARGE_INTEGER li; - li.QuadPart = liDistanceToMove.QuadPart; - li.LowPart = SetFilePointer( - hFile, li.LowPart, &li.HighPart, dwMoveMethod); - if(lpNewFilePointer) { - lpNewFilePointer->QuadPart = li.QuadPart; - } - return li.LowPart != (DWORD)-1 || GetLastError() == NO_ERROR; -} - struct fixup_entry { struct fixup_entry *next; struct archive_acl acl; @@ -595,45 +580,11 @@ la_mktemp(struct archive_write_disk *a) return (fd); } -#if _WIN32_WINNT < _WIN32_WINNT_VISTA -static void * -la_GetFunctionKernel32(const char *name) -{ - static HINSTANCE lib; - static int set; - if (!set) { - set = 1; - lib = LoadLibrary(TEXT("kernel32.dll")); - } - if (lib == NULL) { - fprintf(stderr, "Can't load kernel32.dll?!\n"); - exit(1); - } - return (void *)GetProcAddress(lib, name); -} -#endif - static int la_CreateHardLinkW(wchar_t *linkname, wchar_t *target) { - static BOOL (WINAPI *f)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES); BOOL ret; - -#if _WIN32_WINNT < _WIN32_WINNT_XP - static int set; -/* CreateHardLinkW is available since XP and always loaded */ - if (!set) { - set = 1; - f = la_GetFunctionKernel32("CreateHardLinkW"); - } -#else - f = CreateHardLinkW; -#endif - if (!f) { - errno = ENOTSUP; - return (0); - } - ret = (*f)(linkname, target, NULL); + ret = CreateHardLinkW(linkname, target, NULL); if (!ret) { /* Under windows 2000, it is necessary to remove * the "\\?\" prefix. */ @@ -652,7 +603,7 @@ la_CreateHardLinkW(wchar_t *linkname, wchar_t *target) target += 4; } #undef IS_UNC - ret = (*f)(linkname, target, NULL); + ret = CreateHardLinkW(linkname, target, NULL); } return (ret); } @@ -666,30 +617,18 @@ la_CreateHardLinkW(wchar_t *linkname, wchar_t *target) static int la_CreateSymbolicLinkW(const wchar_t *linkname, const wchar_t *target, int linktype) { - static BOOLEAN (WINAPI *f)(LPCWSTR, LPCWSTR, DWORD); + BOOL ret = 0; +#if _WIN32_WINNT < _WIN32_WINNT_VISTA ||\ + !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) + (void)linkname; /* UNUSED */ + (void)target; /* UNUSED */ + (void)linktype; /* UNUSED */ +#else wchar_t *ttarget, *p; size_t len; DWORD attrs = 0; DWORD flags = 0; DWORD newflags = 0; - BOOL ret = 0; - -#if _WIN32_WINNT < _WIN32_WINNT_VISTA -/* CreateSymbolicLinkW is available since Vista and always loaded */ - static int set; - if (!set) { - set = 1; - f = la_GetFunctionKernel32("CreateSymbolicLinkW"); - } -#else -# if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - f = CreateSymbolicLinkW; -# else - f = NULL; -# endif -#endif - if (!f) - return (0); len = wcslen(target); if (len == 0) { @@ -751,15 +690,16 @@ la_CreateSymbolicLinkW(const wchar_t *linkname, const wchar_t *target, disk_unlink(linkname); } - ret = (*f)(linkname, ttarget, newflags); + ret = CreateSymbolicLinkW(linkname, ttarget, newflags); /* * Prior to Windows 10 calling CreateSymbolicLinkW() will fail * if SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE is set */ if (!ret) { - ret = (*f)(linkname, ttarget, flags); + ret = CreateSymbolicLinkW(linkname, ttarget, flags); } free(ttarget); +#endif return (ret); } @@ -773,7 +713,7 @@ la_ftruncate(HANDLE handle, int64_t length) return (-1); } distance.QuadPart = length; - if (!SetFilePointerEx_perso(handle, distance, NULL, FILE_BEGIN)) { + if (!SetFilePointerEx(handle, distance, NULL, FILE_BEGIN)) { la_dosmaperr(GetLastError()); return (-1); } @@ -874,8 +814,11 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) a->current_fixup = NULL; a->deferred = 0; archive_entry_free(a->entry); - a->entry = NULL; a->entry = archive_entry_clone(entry); + if (a->entry == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } a->fh = INVALID_HANDLE_VALUE; a->fd_offset = 0; a->offset = 0; @@ -1106,7 +1049,7 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size) return (ARCHIVE_OK); if (a->filesize == 0 || a->fh == INVALID_HANDLE_VALUE) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EIO, "Attempt to write to an empty file"); return (ARCHIVE_WARN); } @@ -1190,7 +1133,7 @@ _archive_write_disk_data_block(struct archive *_a, if (r < ARCHIVE_OK) return (r); if ((size_t)r < size) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EOVERFLOW, "Write request too large"); return (ARCHIVE_WARN); } @@ -1607,7 +1550,7 @@ restore_entry(struct archive_write_disk *a) if (a->skip_file_set && bhfi_dev(&a->st) == a->skip_file_dev && bhfi_ino(&a->st) == a->skip_file_ino) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EIO, "Refusing to overwrite archive"); return (ARCHIVE_FAILED); } @@ -2198,7 +2141,7 @@ check_symlinks(struct archive_write_disk *a) * symlink with another symlink. */ if (!S_ISLNK(a->mode)) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, -1, "Removing symlink %ls", a->name); } @@ -2218,7 +2161,7 @@ check_symlinks(struct archive_write_disk *a) r = disk_unlink(a->name); } if (r != 0) { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, EIO, "Cannot remove intervening " "symlink %ls", a->name); pn[0] = c; @@ -2226,7 +2169,7 @@ check_symlinks(struct archive_write_disk *a) } a->pst = NULL; } else { - archive_set_error(&a->archive, 0, + archive_set_error(&a->archive, ELOOP, "Cannot extract through symlink %ls", a->name); pn[0] = c; diff --git a/libarchive/archive_write_filter.3 b/libarchive/archive_write_filter.3 index b39cabe04782..9939de414bba 100644 --- a/libarchive/archive_write_filter.3 +++ b/libarchive/archive_write_filter.3 @@ -50,6 +50,8 @@ Streaming Archive Library (libarchive, -larchive) .Ft int .Fn archive_write_add_filter_b64encode "struct archive *" .Ft int +.Fn archive_write_add_filter_by_name "struct archive *" "const char *name" +.Ft int .Fn archive_write_add_filter_bzip2 "struct archive *" .Ft int .Fn archive_write_add_filter_compress "struct archive *" @@ -100,6 +102,8 @@ Note that the compressed output is always properly blocked. .Xc The output will be encoded as specified. The encoded output is always properly blocked. +.It Fn archive_write_add_filter_by_name +Sets the corresponding filter based on the common name. .It Fn archive_write_add_filter_none This is never necessary. It is provided only for backwards compatibility. @@ -111,6 +115,10 @@ write callbacks. .Sh RETURN VALUES These functions return .Cm ARCHIVE_OK +.Po or +.Cm ARCHIVE_WARN +if an external program had to be executed to handle the filter +.Pc on success, or .Cm ARCHIVE_FATAL . .\" diff --git a/libarchive/archive_write_format.3 b/libarchive/archive_write_format.3 index 9e331368aeef..1b26c1c4640c 100644 --- a/libarchive/archive_write_format.3 +++ b/libarchive/archive_write_format.3 @@ -129,7 +129,9 @@ Sets the corresponding format based on the common name. .Fn archive_write_set_format_filter_by_ext .Fn archive_write_set_format_filter_by_ext_def .Xc -Sets both filters and format based on the output filename. +Sets both filters and format based on the output filename, optionally +referring to a default extension if the supplied filename does not have a +known one. Supported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz .It Xo .Fn archive_write_set_format_7zip diff --git a/libarchive/archive_write_set_format_7zip.c b/libarchive/archive_write_set_format_7zip.c index 1bbd24d632e7..74da63abd1a8 100644 --- a/libarchive/archive_write_set_format_7zip.c +++ b/libarchive/archive_write_set_format_7zip.c @@ -314,7 +314,7 @@ static int _7z_compression_init_encoder(struct archive_write *, unsigned, int); static int compression_init_encoder_zstd(struct archive *, struct la_zstream *, int, int); -#if defined(HAVE_ZSTD_H) +#if HAVE_ZSTD_H && HAVE_ZSTD_compressStream static int compression_code_zstd(struct archive *, struct la_zstream *, enum la_zaction); static int compression_end_zstd(struct archive *, struct la_zstream *); @@ -379,7 +379,7 @@ archive_write_set_format_7zip(struct archive *_a) zip->opt_compression = _7Z_BZIP2; #elif defined(HAVE_ZLIB_H) zip->opt_compression = _7Z_DEFLATE; -#elif HAVE_ZSTD_H +#elif HAVE_ZSTD_H && HAVE_ZSTD_compressStream zip->opt_compression = _7Z_ZSTD; #else zip->opt_compression = _7Z_COPY; @@ -841,7 +841,8 @@ copy_out(struct archive_write *a, uint64_t offset, uint64_t length) return (ARCHIVE_FATAL); } if (rs == 0) { - archive_set_error(&(a->archive), 0, + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated 7-Zip archive"); return (ARCHIVE_FATAL); } @@ -1685,7 +1686,7 @@ file_new(struct archive_write *a, struct archive_entry *entry, const char* linkpath; linkpath = archive_entry_symlink_utf8(entry); if (linkpath == NULL) { - free(file); + file_free(file); archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "symlink path could not be converted to UTF-8"); return (ARCHIVE_FAILED); diff --git a/libarchive/archive_write_set_format_ar.c b/libarchive/archive_write_set_format_ar.c index e5e9c806b639..9912835b8fcf 100644 --- a/libarchive/archive_write_set_format_ar.c +++ b/libarchive/archive_write_set_format_ar.c @@ -172,7 +172,7 @@ archive_write_ar_header(struct archive_write *a, struct archive_entry *entry) /* * If we are now at the beginning of the archive, - * we need first write the ar global header. + * we have to write the ar global header first. */ if (!ar->wrote_global_header) { __archive_write_output(a, "!<arch>\n", 8); diff --git a/libarchive/archive_write_set_format_cpio_binary.c b/libarchive/archive_write_set_format_cpio_binary.c index 4777e75f2912..b0864a0dc97c 100644 --- a/libarchive/archive_write_set_format_cpio_binary.c +++ b/libarchive/archive_write_set_format_cpio_binary.c @@ -380,12 +380,12 @@ write_header(struct archive_write *a, struct archive_entry *entry) { struct cpio *cpio; const char *p, *path; - int pathlength, ret, ret_final; + int ret, ret_final; int64_t ino; struct cpio_binary_header h; struct archive_string_conv *sconv; struct archive_entry *entry_main; - size_t len; + size_t len, pathlength; cpio = (struct cpio *)a->format_data; ret_final = ARCHIVE_OK; @@ -423,7 +423,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) ret_final = ARCHIVE_WARN; } /* Include trailing null */ - pathlength = (int)len + 1; + pathlength = len + 1; h.h_magic = la_swap16(070707); h.h_dev = la_swap16(archive_entry_dev(entry)); @@ -472,7 +472,13 @@ write_header(struct archive_write *a, struct archive_entry *entry) h.h_majmin = 0; h.h_mtime = la_swap32((uint32_t)archive_entry_mtime(entry)); - h.h_namesize = la_swap16(pathlength); + if (pathlength > 0xffff) { + archive_set_error(&a->archive, ERANGE, + "Filename is too long for cpio format"); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; + } + h.h_namesize = la_swap16((uint16_t)pathlength); /* Non-regular files don't store bodies. */ if (archive_entry_filetype(entry) != AE_IFREG) diff --git a/libarchive/archive_write_set_format_cpio_newc.c b/libarchive/archive_write_set_format_cpio_newc.c index d72434d8ae88..e281417bf6f9 100644 --- a/libarchive/archive_write_set_format_cpio_newc.c +++ b/libarchive/archive_write_set_format_cpio_newc.c @@ -219,11 +219,11 @@ write_header(struct archive_write *a, struct archive_entry *entry) int64_t ino; struct cpio *cpio; const char *p, *path; - int pathlength, ret, ret_final; + int ret, ret_final; char h[c_header_size]; struct archive_string_conv *sconv; struct archive_entry *entry_main; - size_t len; + size_t len, pathlength; int pad; cpio = (struct cpio *)a->format_data; @@ -261,7 +261,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) archive_string_conversion_charset_name(sconv)); ret_final = ARCHIVE_WARN; } - pathlength = (int)len + 1; /* Include trailing null. */ + pathlength = len + 1; /* Include trailing null. */ memset(h, 0, c_header_size); format_hex(0x070701, h + c_magic_offset, c_magic_size); @@ -292,7 +292,12 @@ write_header(struct archive_write *a, struct archive_entry *entry) format_hex(0, h + c_rdevminor_offset, c_rdevminor_size); } format_hex(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size); - format_hex(pathlength, h + c_namesize_offset, c_namesize_size); + if (format_hex(pathlength, h + c_namesize_offset, c_namesize_size)) { + archive_set_error(&a->archive, ERANGE, + "Filename is too long for cpio format"); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; + } format_hex(0, h + c_checksum_offset, c_checksum_size); /* Non-regular files don't store bodies. */ diff --git a/libarchive/archive_write_set_format_cpio_odc.c b/libarchive/archive_write_set_format_cpio_odc.c index ffac716b8e75..6b9a7f4ec669 100644 --- a/libarchive/archive_write_set_format_cpio_odc.c +++ b/libarchive/archive_write_set_format_cpio_odc.c @@ -277,12 +277,12 @@ write_header(struct archive_write *a, struct archive_entry *entry) { struct cpio *cpio; const char *p, *path; - int pathlength, ret, ret_final; + int ret, ret_final; int64_t ino; char h[76]; struct archive_string_conv *sconv; struct archive_entry *entry_main; - size_t len; + size_t len, pathlength; cpio = (struct cpio *)a->format_data; ret_final = ARCHIVE_OK; @@ -320,7 +320,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) ret_final = ARCHIVE_WARN; } /* Include trailing null. */ - pathlength = (int)len + 1; + pathlength = len + 1; memset(h, 0, sizeof(h)); format_octal(070707, h + c_magic_offset, c_magic_size); @@ -351,7 +351,12 @@ write_header(struct archive_write *a, struct archive_entry *entry) else format_octal(0, h + c_rdev_offset, c_rdev_size); format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size); - format_octal(pathlength, h + c_namesize_offset, c_namesize_size); + if (format_octal((int64_t)pathlength, h + c_namesize_offset, c_namesize_size)) { + archive_set_error(&a->archive, ERANGE, + "Filename is too long for cpio format"); + ret_final = ARCHIVE_FAILED; + goto exit_write_header; + } /* Non-regular files don't store bodies. */ if (archive_entry_filetype(entry) != AE_IFREG) diff --git a/libarchive/archive_write_set_format_gnutar.c b/libarchive/archive_write_set_format_gnutar.c index b67007a631c0..f2ba4a0db4dc 100644 --- a/libarchive/archive_write_set_format_gnutar.c +++ b/libarchive/archive_write_set_format_gnutar.c @@ -321,7 +321,8 @@ archive_write_gnutar_header(struct archive_write *a, const wchar_t *wp; wp = archive_entry_pathname_w(entry); - if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + if (wp != NULL && wp[0] != L'\0' && + wp[wcslen(wp) - 1] != L'/') { struct archive_wstring ws; archive_string_init(&ws); diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c index 359a2737365f..e3cf9aad2a3b 100644 --- a/libarchive/archive_write_set_format_iso9660.c +++ b/libarchive/archive_write_set_format_iso9660.c @@ -119,6 +119,8 @@ static const unsigned char zisofs_magic[8] = { #define ZF_LOG2_BS 15 /* log2 block size; 32K bytes. */ #define ZF_BLOCK_SIZE (1UL << ZF_LOG2_BS) +#define MAX_JOLIET_ID_NUM 46656 /* 3 base 36 digits */ + /* * Manage extra records. */ @@ -764,7 +766,7 @@ struct iso9660 { #ifdef HAVE_ZLIB_H /* * Copy a compressed file to iso9660.zisofs.temp_fd - * and also copy a uncompressed file(original file) to + * and also copy an uncompressed file(original file) to * iso9660.temp_fd . If the number of logical block * of the compressed file is less than the number of * logical block of the uncompressed file, use it and @@ -1008,7 +1010,7 @@ static int idr_start(struct archive_write *, struct idr *, static void idr_register(struct idr *, struct isoent *, int, int); static void idr_extend_identifier(struct idrent *, int, int); -static void idr_resolve(struct idr *, void (*)(unsigned char *, int)); +static int idr_resolve(struct idr *, void (*)(unsigned char *, int)); static void idr_set_num(unsigned char *, int); static void idr_set_num_beutf16(unsigned char *, int); static int isoent_gen_iso9660_identifier(struct archive_write *, @@ -1168,6 +1170,7 @@ archive_write_set_format_iso9660(struct archive *_a) iso9660->cur_dirent = iso9660->primary.rootent; archive_string_init(&(iso9660->cur_dirstr)); if (archive_string_ensure(&(iso9660->cur_dirstr), 1) == NULL) { + free(iso9660->cur_dirent); free(iso9660); archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); @@ -3036,8 +3039,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len, const char *sl; char sl_last; - if (extra_space(&ctl) < 7) - bp = extra_next_record(&ctl, 7); + if (extra_space(&ctl) < 12) + bp = extra_next_record(&ctl, 12); sl = file->symlink.s; sl_last = '\0'; if (bp != NULL) { @@ -4281,9 +4284,11 @@ _write_path_table(struct archive_write *a, int type_m, int depth, set_num_731(bp+3, np->dir_location); /* Parent Directory Number */ if (type_m) - set_num_722(bp+7, np->parent->dir_number); + set_num_722(bp+7, + np->parent != NULL ? np->parent->dir_number : 0); else - set_num_721(bp+7, np->parent->dir_number); + set_num_721(bp+7, + np->parent != NULL ? np->parent->dir_number : 0); /* Directory Identifier */ if (np->identifier == NULL) bp[9] = 0; @@ -4910,20 +4915,29 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file) * --> 'dir/dir2/' */ char *rp = p -1; + size_t off; + for (off = 4; p[off] == '/'; off++) + ; while (rp >= dirname) { if (*rp == '/') break; --rp; } if (rp > dirname) { - strcpy(rp, p+3); + memmove(rp + 1, p + off, strlen(p + off) + 1); p = rp; } else { - strcpy(dirname, p+4); + memmove(dirname, p + off, strlen(p + off) + 1); p = dirname; } } else p++; + } else if (p == dirname && p[0] == '.' && p[1] == '.' && p[2] == '/') { + size_t off; + for (off = 3; p[off] == '/'; off++) + ; + memmove(dirname, p + off, strlen(p + off) + 1); + p = dirname; } else p++; } @@ -5526,7 +5540,7 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location) static int get_path_component(char *name, size_t n, const char *fn) { - char *p; + const char *p; size_t l; p = strchr(fn, '/'); @@ -5903,21 +5917,22 @@ idr_register(struct idr *idr, struct isoent *isoent, int weight, int noff) static void idr_extend_identifier(struct idrent *wnp, int numsize, int nullsize) { - unsigned char *p; - int wnp_ext_off; - - wnp_ext_off = wnp->isoent->ext_off; - if (wnp->noff + numsize != wnp_ext_off) { - p = (unsigned char *)wnp->isoent->identifier; - /* Extend the filename; foo.c --> foo___.c */ - memmove(p + wnp->noff + numsize, p + wnp_ext_off, + if (wnp->noff + numsize != wnp->isoent->ext_off) { + /* + * Extend the filename; foo.c --> foo___.c + * + * The caller must verify that enough memory is available. + */ + memmove(wnp->isoent->identifier + wnp->noff + numsize, + wnp->isoent->identifier + wnp->isoent->ext_off, wnp->isoent->ext_len + nullsize); - wnp->isoent->ext_off = wnp_ext_off = wnp->noff + numsize; - wnp->isoent->id_len = wnp_ext_off + wnp->isoent->ext_len; + wnp->isoent->ext_off = wnp->noff + numsize; + wnp->isoent->id_len = + wnp->isoent->ext_off + wnp->isoent->ext_len; } } -static void +static int idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num)) { struct idrent *n; @@ -5927,10 +5942,13 @@ idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num)) idr_extend_identifier(n, idr->num_size, idr->null_size); p = (unsigned char *)n->isoent->identifier + n->noff; do { + if (n->avail->rename_num >= MAX_JOLIET_ID_NUM) + return (-ERANGE); fsetnum(p, n->avail->rename_num++); } while (!__archive_rb_tree_insert_node( &(idr->rbtree), &(n->rbnode))); } + return (0); } static void @@ -5990,6 +6008,10 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, static const struct archive_rb_tree_ops rb_ops = { isoent_cmp_node_iso9660, isoent_cmp_key_iso9660 }; + const int num_size = 3; + const int dot_size = 1; + const int version_size = 2; + const int null_size = 1; if (isoent->children.cnt == 0) return (0); @@ -6030,7 +6052,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, fnmax = ffmax = dnmax = 207; } - r = idr_start(a, idr, isoent->children.cnt, ffmax, 3, 1, &rb_ops); + r = idr_start(a, idr, isoent->children.cnt, ffmax, num_size, null_size, &rb_ops); if (r < 0) return (r); @@ -6039,7 +6061,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, int ext_off, noff, weight; l = (int)np->file->basename.length; - p = malloc(l+31+2+1); + p = malloc(l + num_size + dot_size + version_size + null_size); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); @@ -6189,13 +6211,19 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, noff = ext_off - 1; else noff = ext_off; + if (noff < 0) + noff = 0; } /* Register entry to the identifier resolver. */ idr_register(idr, np, weight, noff); } /* Resolve duplicate identifier. */ - idr_resolve(idr, idr_set_num); + r = idr_resolve(idr, idr_set_num); + if (r < 0) { + archive_set_error(&a->archive, -r, "Too many duplicated identifiers"); + return (ARCHIVE_FATAL); + } /* Add a period and a version number to identifiers. */ for (np = isoent->children.first; np != NULL; np = np->chnext) { @@ -6239,6 +6267,8 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, static const struct archive_rb_tree_ops rb_ops = { isoent_cmp_node_joliet, isoent_cmp_key_joliet }; + const int num_size = 6; + const int null_size = 2; if (isoent->children.cnt == 0) return (0); @@ -6249,7 +6279,7 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, else ffmax = 128; - r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, 6, 2, &rb_ops); + r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, num_size, null_size, &rb_ops); if (r < 0) return (r); @@ -6265,7 +6295,7 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, if ((l = np->file->basename_utf16.length) > ffmax) l = ffmax; - p = malloc((l+1)*2); + p = malloc(l + num_size + null_size); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); @@ -6334,12 +6364,18 @@ isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, noff = ext_off - 2; else noff = ext_off; + if (noff < 0) + noff = 0; /* Register entry to the identifier resolver. */ idr_register(idr, np, weight, noff); } /* Resolve duplicate identifier with Joliet Volume. */ - idr_resolve(idr, idr_set_num_beutf16); + r = idr_resolve(idr, idr_set_num_beutf16); + if (r < 0) { + archive_set_error(&a->archive, -r, "Too many duplicated identifiers"); + return (ARCHIVE_FATAL); + } return (ARCHIVE_OK); } @@ -6727,7 +6763,12 @@ isoent_rr_move_dir(struct archive_write *a, struct isoent **rr_moved, /* * The mvent becomes a child of the rr_moved entry. */ - isoent_add_child_tail(rrmoved, mvent); + if (!isoent_add_child_tail(rrmoved, mvent)) { + _isoent_free(mvent); + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unable to insert rr_moved entry"); + return (ARCHIVE_FATAL); + } archive_entry_set_nlink(rrmoved->file->entry, archive_entry_nlink(rrmoved->file->entry) + 1); /* @@ -6820,7 +6861,15 @@ _compare_path_table(const void *v1, const void *v2) p2 = *((const struct isoent **)(uintptr_t)v2); /* Compare parent directory number */ - cmp = p1->parent->dir_number - p2->parent->dir_number; + if (p1->parent == NULL || p2->parent == NULL) { + if (p1->parent == p2->parent) + cmp = 0; + else if (p1->parent == NULL) + return (-1); + else + return (1); + } else + cmp = p1->parent->dir_number - p2->parent->dir_number; if (cmp != 0) return (cmp); @@ -6863,7 +6912,15 @@ _compare_path_table_joliet(const void *v1, const void *v2) p2 = *((const struct isoent **)(uintptr_t)v2); /* Compare parent directory number */ - cmp = p1->parent->dir_number - p2->parent->dir_number; + if (p1->parent == NULL || p2->parent == NULL) { + if (p1->parent == p2->parent) + cmp = 0; + else if (p1->parent == NULL) + return (-1); + else + return (1); + } else + cmp = p1->parent->dir_number - p2->parent->dir_number; if (cmp != 0) return (cmp); diff --git a/libarchive/archive_write_set_format_mtree.c b/libarchive/archive_write_set_format_mtree.c index a4ffec8954d9..ed53849bfbbc 100644 --- a/libarchive/archive_write_set_format_mtree.c +++ b/libarchive/archive_write_set_format_mtree.c @@ -307,14 +307,14 @@ static const uint32_t crctab[] = { static const unsigned char safe_char[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 - 0F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 1F */ - /* !"$%&'()*+,-./ EXCLUSION:0x20( ) 0x23(#) */ - 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ - /* 0123456789:;<>? EXCLUSION:0x3d(=) */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, /* 30 - 3F */ + /* !"$%&'()+,-./ EXCLUSION:0x20( ) 0x23(#) 0x2a(*) */ + 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* 20 - 2F */ + /* 0123456789:;<> EXCLUSION:0x3d(=) 0x3f(?) */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, /* 30 - 3F */ /* @ABCDEFGHIJKLMNO */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ - /* PQRSTUVWXYZ[]^_ EXCLUSION:0x5c(\) */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, /* 50 - 5F */ + /* PQRSTUVWXYZ]^_ EXCLUSION:0x5b([) 0x5c(\) */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, /* 50 - 5F */ /* `abcdefghijklmno */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ /* pqrstuvwxyz{|}~ */ @@ -801,6 +801,8 @@ mtree_entry_new(struct archive_write *a, struct archive_entry *entry, archive_strcpy(&me->symlink, s); me->nlink = archive_entry_nlink(entry); me->filetype = archive_entry_filetype(entry); + if (me->filetype == AE_IFLNK && me->symlink.s == NULL) + archive_strcpy(&me->symlink, ""); me->mode = archive_entry_mode(entry) & 07777; me->uid = archive_entry_uid(entry); me->gid = archive_entry_gid(entry); @@ -988,7 +990,8 @@ write_mtree_entry(struct archive_write *a, struct mtree_entry *me) * a full pathname. */ mtree_quote(str, me->parentdir.s); - archive_strappend_char(str, '/'); + if (strcmp(me->basename.s, ".") != 0) + archive_strappend_char(str, '/'); } mtree_quote(str, me->basename.s); @@ -1145,6 +1148,8 @@ write_mtree_entry_tree(struct archive_write *a) int ret; do { + if (np->dir_info == NULL) + break; if (mtree->output_global_set) { /* * Collect attribute information to know which value @@ -1611,6 +1616,7 @@ sum_update(struct mtree_writer *mtree, const void *buff, size_t n) static void sum_final(struct mtree_writer *mtree, struct reg_info *reg) { + struct ae_digest digest; if (mtree->compute_sum & F_CKSUM) { uint64_t len; @@ -1620,40 +1626,34 @@ sum_final(struct mtree_writer *mtree, struct reg_info *reg) reg->crc = ~mtree->crc; } #ifdef ARCHIVE_HAS_MD5 - if ((mtree->compute_sum & F_MD5) - && !(reg->mset_digest & AE_MSET_DIGEST_MD5)) + if (mtree->compute_sum & F_MD5) - archive_md5_final(&mtree->md5ctx, reg->digest.md5); + archive_md5_final(&mtree->md5ctx, (reg->mset_digest & AE_MSET_DIGEST_MD5) ? digest.md5 : reg->digest.md5); #endif #ifdef ARCHIVE_HAS_RMD160 - if ((mtree->compute_sum & F_RMD160) - && !(reg->mset_digest & AE_MSET_DIGEST_RMD160)) + if (mtree->compute_sum & F_RMD160) - archive_rmd160_final(&mtree->rmd160ctx, reg->digest.rmd160); + archive_rmd160_final(&mtree->rmd160ctx, (reg->mset_digest & AE_MSET_DIGEST_RMD160) ? digest.rmd160 : reg->digest.rmd160); #endif #ifdef ARCHIVE_HAS_SHA1 - if ((mtree->compute_sum & F_SHA1) - && !(reg->mset_digest & AE_MSET_DIGEST_SHA1)) + if (mtree->compute_sum & F_SHA1) - archive_sha1_final(&mtree->sha1ctx, reg->digest.sha1); + archive_sha1_final(&mtree->sha1ctx, (reg->mset_digest & AE_MSET_DIGEST_SHA1) ? digest.sha1 : reg->digest.sha1); #endif #ifdef ARCHIVE_HAS_SHA256 - if ((mtree->compute_sum & F_SHA256) - && !(reg->mset_digest & AE_MSET_DIGEST_SHA256)) + if (mtree->compute_sum & F_SHA256) - archive_sha256_final(&mtree->sha256ctx, reg->digest.sha256); + archive_sha256_final(&mtree->sha256ctx, (reg->mset_digest & AE_MSET_DIGEST_SHA256) ? digest.sha256 : reg->digest.sha256); #endif #ifdef ARCHIVE_HAS_SHA384 - if ((mtree->compute_sum & F_SHA384) - && !(reg->mset_digest & AE_MSET_DIGEST_SHA384)) + if (mtree->compute_sum & F_SHA384) - archive_sha384_final(&mtree->sha384ctx, reg->digest.sha384); + archive_sha384_final(&mtree->sha384ctx, (reg->mset_digest & AE_MSET_DIGEST_SHA384) ? digest.sha384 : reg->digest.sha384); #endif #ifdef ARCHIVE_HAS_SHA512 - if ((mtree->compute_sum & F_SHA512) - && !(reg->mset_digest & AE_MSET_DIGEST_SHA512)) + if (mtree->compute_sum & F_SHA512) - archive_sha512_final(&mtree->sha512ctx, reg->digest.sha512); + archive_sha512_final(&mtree->sha512ctx, (reg->mset_digest & AE_MSET_DIGEST_SHA512) ? digest.sha512 : reg->digest.sha512); #endif /* Save what types of sum are computed. */ reg->compute_sum = mtree->compute_sum; @@ -1886,20 +1886,29 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file, * --> 'dir/dir2/' */ char *rp = p -1; + size_t off; + for (off = 4; p[off] == '/'; off++) + ; while (rp >= dirname) { if (*rp == '/') break; --rp; } if (rp > dirname) { - strcpy(rp, p+3); + memmove(rp + 1, p + off, strlen(p + off) + 1); p = rp; } else { - strcpy(dirname, p+4); + memmove(dirname, p + off, strlen(p + off) + 1); p = dirname; } } else p++; + } else if (p == dirname && p[0] == '.' && p[1] == '.' && p[2] == '/') { + size_t off; + for (off = 3; p[off] == '/'; off++) + ; + memmove(dirname, p + off, strlen(p + off) + 1); + p = dirname; } else p++; } @@ -2041,7 +2050,7 @@ mtree_entry_find_child(struct mtree_entry *parent, const char *child_name) static int get_path_component(char *name, size_t n, const char *fn) { - char *p; + const char *p; size_t l; p = strchr(fn, '/'); @@ -2079,6 +2088,11 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep) file = *filep; if (file->parentdir.length == 0 && file->basename.length == 1 && file->basename.s[0] == '.') { + if (file->filetype != AE_IFDIR) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Root entry '.' must be a directory"); + return (ARCHIVE_FAILED); + } file->parent = file; if (mtree->root != NULL) { np = mtree->root; diff --git a/libarchive/archive_write_set_format_pax.c b/libarchive/archive_write_set_format_pax.c index f3589d6859e3..cda1ffd904e4 100644 --- a/libarchive/archive_write_set_format_pax.c +++ b/libarchive/archive_write_set_format_pax.c @@ -40,6 +40,7 @@ #include "archive.h" #include "archive_entry.h" #include "archive_entry_locale.h" +#include "archive_integer.h" #include "archive_private.h" #include "archive_write_private.h" #include "archive_write_set_format_private.h" @@ -676,7 +677,8 @@ archive_write_pax_header(struct archive_write *a, const wchar_t *wp; wp = archive_entry_pathname_w(entry_original); - if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + if (wp != NULL && wp[0] != L'\0' && + wp[wcslen(wp) - 1] != L'/') { struct archive_wstring ws; archive_string_init(&ws); @@ -1934,17 +1936,17 @@ url_encode(const char *in) for (s = in; *s != '\0'; s++) { if (*s < 33 || *s > 126 || *s == '%' || *s == '=') { - if (SIZE_MAX - out_len < 4) + if (archive_ckd_add_size(&out_len, out_len, 3)) return (NULL); - out_len += 3; } else { - if (SIZE_MAX - out_len < 2) + if (archive_ckd_add_size(&out_len, out_len, 1)) return (NULL); - out_len++; } } - out = malloc(out_len + 1); + if (archive_ckd_add_size(&out_len, out_len, 1)) + return (NULL); + out = malloc(out_len); if (out == NULL) return (NULL); diff --git a/libarchive/archive_write_set_format_shar.c b/libarchive/archive_write_set_format_shar.c index f6f28debdfa9..ad8d5b78dc0e 100644 --- a/libarchive/archive_write_set_format_shar.c +++ b/libarchive/archive_write_set_format_shar.c @@ -38,6 +38,7 @@ #endif #include "archive.h" +#include "archive_endian.h" #include "archive_entry.h" #include "archive_private.h" #include "archive_write_private.h" @@ -173,6 +174,10 @@ archive_write_shar_header(struct archive_write *a, struct archive_entry *entry) /* Save the entry for the closing. */ archive_entry_free(shar->entry); shar->entry = archive_entry_clone(entry); + if (shar->entry == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } name = archive_entry_pathname(entry); /* Handle some preparatory issues. */ @@ -408,9 +413,9 @@ static void uuencode_group(const char _in[3], char out[4]) { const unsigned char *in = (const unsigned char *)_in; - int t; + uint32_t t; - t = (in[0] << 16) | (in[1] << 8) | in[2]; + t = archive_be24dec(in); out[0] = UUENC( 0x3f & (t >> 18) ); out[1] = UUENC( 0x3f & (t >> 12) ); out[2] = UUENC( 0x3f & (t >> 6) ); diff --git a/libarchive/archive_write_set_format_ustar.c b/libarchive/archive_write_set_format_ustar.c index 97724c1588b3..e84152ea18f5 100644 --- a/libarchive/archive_write_set_format_ustar.c +++ b/libarchive/archive_write_set_format_ustar.c @@ -281,7 +281,8 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) const wchar_t *wp; wp = archive_entry_pathname_w(entry); - if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + if (wp != NULL && wp[0] != L'\0' && + wp[wcslen(wp) - 1] != L'/') { struct archive_wstring ws; archive_string_init(&ws); diff --git a/libarchive/archive_write_set_format_v7tar.c b/libarchive/archive_write_set_format_v7tar.c index 37ba73a1320a..91c5e8e42f0b 100644 --- a/libarchive/archive_write_set_format_v7tar.c +++ b/libarchive/archive_write_set_format_v7tar.c @@ -259,7 +259,8 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry) const wchar_t *wp; wp = archive_entry_pathname_w(entry); - if (wp != NULL && wp[wcslen(wp) -1] != L'/') { + if (wp != NULL && wp[0] != L'\0' && + wp[wcslen(wp) - 1] != L'/') { struct archive_wstring ws; archive_string_init(&ws); diff --git a/libarchive/archive_write_set_format_warc.c b/libarchive/archive_write_set_format_warc.c index 3d22e1f4ba57..2192995362a5 100644 --- a/libarchive/archive_write_set_format_warc.c +++ b/libarchive/archive_write_set_format_warc.c @@ -245,6 +245,7 @@ _warc_header(struct archive_write *a, struct archive_entry *entry) r = _popul_ehdr(&hdr, MAX_HDR_SIZE, rh); if (r < 0) { /* don't bother */ + archive_string_free(&hdr); archive_set_error( &a->archive, ARCHIVE_ERRNO_FILE_FORMAT, @@ -371,7 +372,7 @@ _popul_ehdr(struct archive_string *tgt, size_t tsz, warc_essential_hdr_t hdr) static const char _uri[] = ""; static const char _fil[] = "file://"; const char *u; - char *chk = strchr(hdr.tgturi, ':'); + const char *chk = strchr(hdr.tgturi, ':'); if (chk != NULL && chk[1U] == '/' && chk[2U] == '/') { /* yep, it's definitely a URI */ diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c index 6ecccdef6499..98bc4952dad9 100644 --- a/libarchive/archive_write_set_format_xar.c +++ b/libarchive/archive_write_set_format_xar.c @@ -819,9 +819,7 @@ xar_finish_entry(struct archive_write *a) if (s > a->null_length) s = a->null_length; w = xar_write_data(a, a->nulls, s); - if (w > 0) - xar->bytes_remaining -= w; - else + if (w <= 0) return ((int)w); } file = xar->cur_file; @@ -1110,30 +1108,27 @@ make_fflags_entry(struct archive_write *a, struct xml_writer *writer, { NULL, NULL} }; const struct flagentry *fe, *flagentry; -#define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd)) - const struct flagentry *avail[FLAGENTRY_MAXSIZE]; const char *p; - int i, n, r; + int r, started; if (strcmp(element, "ext2") == 0) flagentry = flagext2; else flagentry = flagbsd; - n = 0; p = fflags_text; + started = 0; do { - const char *cp; + const char *cp, *name = NULL; cp = strchr(p, ','); if (cp == NULL) cp = p + strlen(p); for (fe = flagentry; fe->name != NULL; fe++) { - if (fe->name[cp - p] != '\0' - || p[0] != fe->name[0]) - continue; if (strncmp(p, fe->name, cp - p) == 0) { - avail[n++] = fe; + if (fe->name[cp - p] != '\0') + continue; + name = fe->xarname; break; } } @@ -1141,23 +1136,26 @@ make_fflags_entry(struct archive_write *a, struct xml_writer *writer, p = cp + 1; else p = NULL; - } while (p != NULL); - if (n > 0) { - r = xml_writer_start_element(writer, element); - if (r < 0) { - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "xml_writer_start_element() failed: %d", r); - return (ARCHIVE_FATAL); - } - for (i = 0; i < n; i++) { - r = xmlwrite_string(a, writer, - avail[i]->xarname, NULL); + if (name != NULL) { + if (!started) { + r = xml_writer_start_element(writer, element); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xml_writer_start_element()" + " failed: %d", r); + return (ARCHIVE_FATAL); + } + started = 1; + } + r = xmlwrite_string(a, writer, name, NULL); if (r != ARCHIVE_OK) return (r); } + } while (p != NULL); + if (started) { r = xml_writer_end_element(writer); if (r < 0) { archive_set_error(&a->archive, @@ -1439,7 +1437,7 @@ make_file_entry(struct archive_write *a, struct xml_writer *writer, } /* - * Make a mtime entry, "<mtime>". + * Make an mtime entry, "<mtime>". */ if (archive_entry_mtime_is_set(file->entry)) { r = xmlwrite_time(a, writer, "mtime", @@ -1866,7 +1864,8 @@ copy_out(struct archive_write *a, uint64_t offset, uint64_t length) return (ARCHIVE_FATAL); } if (rs == 0) { - archive_set_error(&(a->archive), 0, + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated xar archive"); return (ARCHIVE_FATAL); } @@ -2205,20 +2204,29 @@ file_gen_utility_names(struct archive_write *a, struct file *file) * --> 'dir/dir2/' */ char *rp = p -1; + size_t off; + for (off = 4; p[off] == '/'; off++) + ; while (rp >= dirname) { if (*rp == '/') break; --rp; } if (rp > dirname) { - strcpy(rp, p+3); + memmove(rp + 1, p + off, strlen(p + off) + 1); p = rp; } else { - strcpy(dirname, p+4); + memmove(dirname, p + off, strlen(p + off) + 1); p = dirname; } } else p++; + } else if (p == dirname && p[0] == '.' && p[1] == '.' && p[2] == '/') { + size_t off; + for (off = 3; p[off] == '/'; off++) + ; + memmove(dirname, p + off, strlen(p + off) + 1); + p = dirname; } else p++; } @@ -2272,7 +2280,7 @@ file_gen_utility_names(struct archive_write *a, struct file *file) static int get_path_component(char *name, int n, const char *fn) { - char *p; + const char *p; int l; p = strchr(fn, '/'); @@ -2378,10 +2386,24 @@ file_tree(struct archive_write *a, struct file **filepp) archive_string_init(&as); archive_strncat(&as, p, fn - p + l); - if (as.s[as.length-1] == '/') { + if (as.length > 0 && as.s[as.length-1] == '/') { as.s[as.length-1] = '\0'; as.length--; } + if (as.length == 0) { + archive_string_free(&as); + fn += strspn(fn, "/"); + l = get_path_component(name, sizeof(name), fn); + if (l < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FATAL); + } + continue; + } vp = file_create_virtual_dir(a, xar, as.s); if (vp == NULL) { archive_string_free(&as); diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c index 81d3db0db038..33d60ce864c6 100644 --- a/libarchive/archive_write_set_format_zip.c +++ b/libarchive/archive_write_set_format_zip.c @@ -797,6 +797,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) unsigned char *e; unsigned char *cd_extra; size_t filename_length; + const char *path; const char *slink = NULL; size_t slink_size = 0; struct archive_string_conv *sconv = get_sconv(a, zip); @@ -960,6 +961,19 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) } filename_length = path_length(zip->entry); + /* Reject empty or overlong pathnames */ + path = archive_entry_pathname(zip->entry); + if (path == NULL || path[0] == '\0') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "ZIP format requires a non-empty pathname"); + return (ARCHIVE_FAILED); + } + if (filename_length > 0xffff) { + archive_set_error(&a->archive, ENAMETOOLONG, + "Pathname too long for ZIP format"); + return (ARCHIVE_FAILED); + } + /* Determine appropriate compression and size for this entry. */ if (type == AE_IFLNK) { slink = archive_entry_symlink(zip->entry); @@ -2304,7 +2318,7 @@ write_path(struct archive_entry *entry, struct archive_write *archive) written_bytes += strlen(path); /* Folders are recognized by a trailing slash. */ - if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) { + if ((type == AE_IFDIR) && (path[strlen(path) - 1] != '/')) { ret = __archive_write_output(archive, "/", 1); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); diff --git a/libarchive/filter_fork_windows.c b/libarchive/filter_fork_windows.c index 9e49c5655f1d..a0fd63894044 100644 --- a/libarchive/filter_fork_windows.c +++ b/libarchive/filter_fork_windows.c @@ -31,43 +31,68 @@ #include "filter_fork.h" -#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) /* There are some editions of Windows ("nano server," for example) that * do not host user32.dll. If we want to keep running on those editions, * we need to delay-load WaitForInputIdle. */ -static void * -la_GetFunctionUser32(const char *name) + +static int +failing_wait(HANDLE hProcess, DWORD dwMilliseconds) { + /* An inability to wait for input idle is + * not _good_, but it is not catastrophic. */ + (void)hProcess; /* UNUSED */ + (void)dwMilliseconds; /* UNUSED */ + return WAIT_FAILED; +} + +# if _WIN32_WINNT < _WIN32_WINNT_VISTA +static int +la_WaitForInputIdle(HANDLE hProcess, DWORD dwMilliseconds) { - static HINSTANCE lib; - static int set; - if (!set) { - set = 1; + static DWORD (WINAPI * volatile f)(HANDLE, DWORD); + + if (f == NULL) { + HINSTANCE lib; + void *old; + DWORD (WINAPI *tmp)(HANDLE, DWORD); + lib = LoadLibrary(TEXT("user32.dll")); + tmp = (lib != NULL) ? + (PVOID)GetProcAddress(lib, "WaitForInputIdle") : + failing_wait; + old = InterlockedCompareExchangePointer((volatile PVOID *)&f, + tmp, NULL); + if (old != NULL && lib != NULL) + FreeLibrary(lib); } - if (lib == NULL) { - return NULL; - } - return (void *)GetProcAddress(lib, name); + + return (*f)(hProcess, dwMilliseconds); +} +# else +static BOOL CALLBACK +load_WaitForInputIdle(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) { + HMODULE user32 = LoadLibrary(TEXT("user32.dll")); + + (void)InitOnce; /* UNUSED */ + (void)Parameter; /* UNUSED */ + + *Context = (user32 != NULL) ? + (PVOID)GetProcAddress(user32, "WaitForInputIdle") : failing_wait; + + return TRUE; } static int la_WaitForInputIdle(HANDLE hProcess, DWORD dwMilliseconds) { static DWORD (WINAPI *f)(HANDLE, DWORD); - static int set; + static INIT_ONCE once = INIT_ONCE_STATIC_INIT; - if (!set) { - set = 1; - f = la_GetFunctionUser32("WaitForInputIdle"); - } + InitOnceExecuteOnce(&once, load_WaitForInputIdle, NULL, (PVOID)&f); - if (!f) { - /* An inability to wait for input idle is - * not _good_, but it is not catastrophic. */ - return WAIT_FAILED; - } return (*f)(hProcess, dwMilliseconds); } +# endif int __archive_create_child(const char *cmd, int *child_stdin, int *child_stdout, diff --git a/libarchive/libarchive-formats.5 b/libarchive/libarchive-formats.5 index 1b057b4da0d8..eb720eb740f5 100644 --- a/libarchive/libarchive-formats.5 +++ b/libarchive/libarchive-formats.5 @@ -210,7 +210,7 @@ values of varying byte order and length. .Bl -tag -width indent .It Cm binary The libarchive library transparently reads both big-endian and -little-endian variants of the the two binary cpio formats; the +little-endian variants of the two binary cpio formats; the original one from PWB/UNIX, and the later, more widely used, variant. This format used 32-bit binary values for file size and mtime, and 16-bit binary values for the other fields. The formats support only diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index 5734cbed5ed8..a107b3999808 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -11,10 +11,13 @@ IF(ENABLE_TEST) test.h test_7zip_filename_encoding.c test_acl_nfs4.c + test_acl_nfs4_null_id_overflow.c + test_acl_nfs4_text.c test_acl_pax.c test_acl_platform_nfs4.c test_acl_platform_posix1e.c test_acl_posix1e.c + test_acl_posix1e_text.c test_acl_text.c test_ar_mode.c test_archive_api_feature.c @@ -26,6 +29,7 @@ IF(ENABLE_TEST) test_archive_match_time.c test_archive_parse_date.c test_archive_pathmatch.c + test_archive_pathmatch_oob.c test_archive_read.c test_archive_read_add_passphrase.c test_archive_read_close_twice.c @@ -43,6 +47,7 @@ IF(ENABLE_TEST) test_archive_set_error.c test_archive_string.c test_archive_string_conversion.c + test_archive_write_add_filter.c test_archive_write_add_filter_by_name.c test_archive_write_set_filter_option.c test_archive_write_set_format_by_name.c @@ -94,20 +99,24 @@ IF(ENABLE_TEST) test_read_disk_entry_from_file.c test_read_extract.c test_read_file_nonexistent.c + test_read_files_compressed.c test_read_filter_compress.c test_read_filter_grzip.c test_read_filter_gzip_recursive.c test_read_filter_lrzip.c + test_read_filter_lz4_raw.c test_read_filter_lzop.c test_read_filter_lzop_multiple_parts.c test_read_filter_program.c test_read_filter_program_signature.c test_read_filter_uudecode.c test_read_filter_uudecode_raw.c + test_read_filter_zstd_raw.c test_read_format_7zip.c test_read_format_7zip_encryption_data.c test_read_format_7zip_encryption_header.c test_read_format_7zip_encryption_partially.c + test_read_format_7zip_entries_oom.c test_read_format_7zip_issue2765.c test_read_format_7zip_malformed.c test_read_format_7zip_packinfo_digests.c @@ -115,6 +124,8 @@ IF(ENABLE_TEST) test_read_format_cab.c test_read_format_cab_filename.c test_read_format_cab_lzx_oob.c + test_read_format_cab_mszip_oob.c + test_read_format_cab_multi.c test_read_format_cab_skip_malformed.c test_read_format_cpio_afio.c test_read_format_cpio_bin.c @@ -142,6 +153,7 @@ IF(ENABLE_TEST) test_read_format_gtar_sparse_skip_entry.c test_read_format_huge_rpm.c test_read_format_iso_Z.c + test_read_format_iso_joliet_utf16be_overflow.c test_read_format_iso_multi_extent.c test_read_format_iso_xorriso.c test_read_format_isojoliet_bz2.c @@ -150,6 +162,7 @@ IF(ENABLE_TEST) test_read_format_isojoliet_versioned.c test_read_format_isorr_bz2.c test_read_format_isorr_ce.c + test_read_format_isorr_ce_loop.c test_read_format_isorr_new_bz2.c test_read_format_isorr_rr_moved.c test_read_format_isozisofs_bz2.c @@ -171,9 +184,13 @@ IF(ENABLE_TEST) test_read_format_rar_filter.c test_read_format_rar_overflow.c test_read_format_rar5.c + test_read_format_rar5_bad_filter.c + test_read_format_rar5_bad_tables.c + test_read_format_rar5_block_hdr_fail_loop.c test_read_format_rar5_loop_bug.c test_read_format_raw.c test_read_format_tar.c + test_read_format_tar_acl_oob_read.c test_read_format_tar_V_negative_size.c test_read_format_tar_concatenated.c test_read_format_tar_empty_filename.c @@ -185,6 +202,8 @@ IF(ENABLE_TEST) test_read_format_tar_pax_g_large.c test_read_format_tar_pax_large_attr.c test_read_format_tar_pax_negative_time.c + test_read_format_tar_pax_timestamps.c + test_read_format_tar_timestamp_overflow.c test_read_format_tbz.c test_read_format_tgz.c test_read_format_tlz.c @@ -215,6 +234,8 @@ IF(ENABLE_TEST) test_read_format_zip_winzip_aes.c test_read_format_zip_winzip_aes_large.c test_read_format_zip_zip64.c + test_read_format_zip_zipx_encrypted.c + test_read_format_zip_zipx_lzma_oom.c test_read_format_zip_with_invalid_traditional_eocd.c test_read_large.c test_read_pax_empty_val_no_nl.c @@ -280,20 +301,27 @@ IF(ENABLE_TEST) test_write_format_iso9660_boot.c test_write_format_iso9660_empty.c test_write_format_iso9660_filename.c + test_write_format_iso9660_joliet_id.c + test_write_format_iso9660_rockridge.c test_write_format_iso9660_zisofs.c + test_write_format_iso9660_bugs.c test_write_format_mtree.c + test_write_format_mtree_absolute.c test_write_format_mtree_absolute_path.c test_write_format_mtree_classic.c test_write_format_mtree_classic_indent.c + test_write_format_mtree_dotdot.c test_write_format_mtree_fflags.c test_write_format_mtree_no_separator.c test_write_format_mtree_preset_digests.c test_write_format_mtree_quoted_filename.c + test_write_format_mtree_null_deref.c test_write_format_pax.c test_write_format_raw.c test_write_format_raw_b64.c test_write_format_shar_empty.c test_write_format_tar.c + test_write_format_tar_empty_dirname.c test_write_format_tar_empty.c test_write_format_tar_sparse.c test_write_format_tar_ustar.c @@ -302,6 +330,8 @@ IF(ENABLE_TEST) test_write_format_warc_empty.c test_write_format_xar.c test_write_format_xar_empty.c + test_write_format_xar_fflags.c + test_write_format_xar_bugs.c test_write_format_zip.c test_write_format_zip64_stream.c test_write_format_zip_compression_store.c @@ -309,11 +339,13 @@ IF(ENABLE_TEST) test_write_format_zip_compression_lzmaxz.c test_write_format_zip_compression_zstd.c test_write_format_zip_empty.c + test_write_format_zip_empty_pathname.c test_write_format_zip_empty_zip64.c test_write_format_zip_entry_size_unset.c test_write_format_zip_file.c test_write_format_zip_file_zip64.c test_write_format_zip_large.c + test_write_format_zip_long_pathname.c test_write_format_zip_stream.c test_write_format_zip_windows_path.c test_write_format_zip_zip64.c @@ -335,24 +367,12 @@ IF(ENABLE_TEST) # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. # GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h - ${CMAKE_CURRENT_LIST_FILE} ${libarchive_test_SOURCES}) + ${CMAKE_CURRENT_LIST_FILE} libarchive_test ${libarchive_test_SOURCES}) SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}) - # list.h has a line DEFINE_TEST(testname) for every - # test. We can use that to define the tests for cmake by - # defining a DEFINE_TEST macro and reading list.h in. - MACRO (DEFINE_TEST _testname) - ADD_TEST( - NAME libarchive_${_testname} - COMMAND libarchive_test -vv - -r ${CMAKE_CURRENT_SOURCE_DIR} - -s - ${_testname}) - SET_TESTS_PROPERTIES(libarchive_${_testname} PROPERTIES SKIP_RETURN_CODE 2) - ENDMACRO (DEFINE_TEST _testname) + DISCOVER_TESTS(libarchive ${libarchive_test_SOURCES}) - INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/libarchive/test) diff --git a/libarchive/test/test_acl_nfs4_null_id_overflow.c b/libarchive/test/test_acl_nfs4_null_id_overflow.c new file mode 100644 index 000000000000..590c704595ce --- /dev/null +++ b/libarchive/test/test_acl_nfs4_null_id_overflow.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * A USER NFSv4 ACL entry with a NULL name and a large numeric qualifier + * triggers a heap buffer overflow in archive_acl_to_text_l(). + * + * archive_acl_text_len() only reserves space for the trailing ":id" digits + * when ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID is set, but the serializer always + * writes them for USER/GROUP entries when the name is NULL. With a 7-digit + * ID the allocated buffer is too short and append_id() writes past its end. + * + * Without the fix, libarchive's own post-write guard fires: + * "Fatal Internal Error: Buffer overrun" + * (or under AddressSanitizer a heap-buffer-overflow is reported at + * archive_acl.c in append_id / append_entry). + */ +DEFINE_TEST(test_acl_nfs4_null_id_overflow) +{ + struct archive_entry *ae; + char *text; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0644); + + /* NULL name + 7-digit id: the missing ":9999999" overflows the buffer */ + archive_entry_acl_add_entry(ae, + ARCHIVE_ENTRY_ACL_TYPE_DENY, + 0, + ARCHIVE_ENTRY_ACL_USER, + 9999999, + NULL); + + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assert(text != NULL); + /* The numeric id must appear in the output as the user name */ + assert(strstr(text, "9999999") != NULL); + free(text); + + archive_entry_free(ae); +} + +/* + * The wide (wchar_t) serializer has a related bug: when the name is NULL + * it passes id=-1 to append_entry_w() instead of the actual numeric id, + * so the id is never written and a garbage character appears in the name + * slot instead. + * + * The wide estimator has the same missing-id-digits gap as the narrow one, + * and both must be fixed together with the wide serializer. + */ +DEFINE_TEST(test_acl_nfs4_null_id_overflow_w) +{ + struct archive_entry *ae; + wchar_t *wtext; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0644); + + archive_entry_acl_add_entry(ae, + ARCHIVE_ENTRY_ACL_TYPE_DENY, + 0, + ARCHIVE_ENTRY_ACL_USER, + 9999999, + NULL); + + wtext = archive_entry_acl_to_text_w(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assert(wtext != NULL); + /* The numeric id must appear in the output as the user name */ + assert(wcsstr(wtext, L"9999999") != NULL); + free(wtext); + + archive_entry_free(ae); +} diff --git a/libarchive/test/test_acl_nfs4_text.c b/libarchive/test/test_acl_nfs4_text.c new file mode 100644 index 000000000000..165d18ed8f1c --- /dev/null +++ b/libarchive/test/test_acl_nfs4_text.c @@ -0,0 +1,426 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +#include <limits.h> + +/* + * Focused tests for NFSv4 ACL text parsing and serialization. + * + * test_acl_text.c already covers basic round-trips with well-formed input. + * These tests probe areas not reached there: all four ACL types, numeric IDs, + * extra-ID field override, isint() overflow, malformed entries, compact mode, + * and the wide-char path. + */ + +/* NFSv4 text in standard (no extra ID), extra-ID, and compact+extra-ID forms. + * These are the same strings used in test_acl_text.c acltext[9..11]. */ +static const char *nfs4_std = + "user:user77:rw-p--a-R-c-o-:-------:allow\n" + "user:user101:-w-pdD--------:fdin---:deny\n" + "group:group78:r-----a-R-c---:------I:allow\n" + "owner@:rwxp--aARWcCo-:-------:allow\n" + "group@:rw-p--a-R-c---:-------:allow\n" + "everyone@:r-----a-R-c--s:-------:allow"; + +static const char *nfs4_extra_id = + "user:user77:rw-p--a-R-c-o-:-------:allow:77\n" + "user:user101:-w-pdD--------:fdin---:deny:101\n" + "group:group78:r-----a-R-c---:------I:allow:78\n" + "owner@:rwxp--aARWcCo-:-------:allow\n" + "group@:rw-p--a-R-c---:-------:allow\n" + "everyone@:r-----a-R-c--s:-------:allow"; + +static const char *nfs4_compact = + "user:user77:rwpaRco::allow:77\n" + "user:user101:wpdD:fdin:deny:101\n" + "group:group78:raRc:I:allow:78\n" + "owner@:rwxpaARWcCo::allow\n" + "group@:rwpaRc::allow\n" + "everyone@:raRcs::allow"; + +static wchar_t * +s_to_ws(const char *s) +{ + size_t len = strlen(s) + 1; + wchar_t *ws = malloc(len * sizeof(wchar_t)); + assert(ws != NULL); + assert(mbstowcs(ws, s, len) != (size_t)-1); + return (ws); +} + +/* + * Round-trip: parse NFS4 text → serialize → compare. + * Covers standard, extra-ID, and compact+extra-ID formats, + * for both the narrow and wide serializers. + */ +DEFINE_TEST(test_acl_nfs4_text_roundtrip) +{ + struct archive_entry *ae; + char *text; + wchar_t *wtext, *ws; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0644); + + /* Standard format */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, nfs4_std, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assertEqualString(nfs4_std, text); + free(text); + archive_entry_acl_clear(ae); + + /* Extra-ID format: trailing :id must be preserved */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, nfs4_extra_id, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4 | ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); + assertEqualString(nfs4_extra_id, text); + free(text); + archive_entry_acl_clear(ae); + + /* Compact format: empty perm/flag fields must round-trip */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, nfs4_compact, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4 | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_COMPACT); + assertEqualString(nfs4_compact, text); + free(text); + archive_entry_acl_clear(ae); + + /* Wide: standard format */ + ws = s_to_ws(nfs4_std); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + wtext = archive_entry_acl_to_text_w(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assertEqualWString(ws, wtext); + free(wtext); + free(ws); + archive_entry_acl_clear(ae); + + /* Wide: compact+extra-ID format */ + ws = s_to_ws(nfs4_compact); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + wtext = archive_entry_acl_to_text_w(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4 | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_COMPACT); + assertEqualWString(ws, wtext); + free(wtext); + free(ws); + archive_entry_acl_clear(ae); + + archive_entry_free(ae); +} + +/* + * All four ACL entry types: allow, deny, audit, alarm. + * test_acl_text.c only exercises allow and deny. + */ +DEFINE_TEST(test_acl_nfs4_text_types) +{ + struct archive_entry *ae; + char *text; + wchar_t *wtext, *ws; + ssize_t len; + int type, permset, tag, qual; + const char *name; + static const char *audit_alarm_text = + "user:alice:rw-p--aARWcCos:-------:audit\n" + "group:staff:rw-p--aARWcCos:-------:alarm"; + + ae = archive_entry_new(); + assert(ae != NULL); + + /* Parse and verify both audit and alarm entries are stored */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, audit_alarm_text, + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(2, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_AUDIT, type); + assertEqualString("alice", name); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ALARM, type); + assertEqualString("staff", name); + + /* Round-trip: serialize then compare */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assertEqualString(audit_alarm_text, text); + + /* Verify same round-trip via wide path */ + ws = s_to_ws(audit_alarm_text); + wtext = archive_entry_acl_to_text_w(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assertEqualWString(ws, wtext); + free(ws); + free(wtext); + free(text); + + archive_entry_free(ae); +} + +/* + * Numeric IDs in the name field and the extra-ID override field. + * + * 1. "user:1000:..." — the name field is a pure number; id is set from it. + * 2. "user:name:...:42" — the trailing id field overrides any id derived + * from the name. + * 3. "user:1000:...:42" — trailing id overrides even a numeric name. + * 4. isint() overflow: a field with more than 10 digits is clamped to INT_MAX. + */ +DEFINE_TEST(test_acl_nfs4_text_numeric_id) +{ + struct archive_entry *ae; + char *text; + ssize_t len; + int type, permset, tag, qual; + const char *name; + + ae = archive_entry_new(); + assert(ae != NULL); + + /* 1. Numeric-only name → id derived from name field */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user:1000:rw-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(1, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(1000, qual); + assertEqualString("1000", name); + /* Without EXTRA_ID the id is carried by the name string, not :id */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + assertEqualString("user:1000:rw-p--a-R-c-o-:-------:allow", text); + free(text); + /* With EXTRA_ID the id is appended */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_NFS4 | ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); + assertEqualString("user:1000:rw-p--a-R-c-o-:-------:allow:1000", text); + free(text); + archive_entry_acl_clear(ae); + + /* 2. Trailing extra-ID field overrides name-derived id */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user:user77:rw-p--a-R-c-o-:-------:allow:42", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(1, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(42, qual); + assertEqualString("user77", name); + archive_entry_acl_clear(ae); + + /* 3. Trailing extra-ID also overrides a numeric name */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user:1000:rw-p--a-R-c-o-:-------:allow:42", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(1, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(42, qual); + archive_entry_acl_clear(ae); + + /* 4. isint() overflow: extra-ID field too large → entry rejected */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:name:rw-p--a-R-c-o-:-------:allow:99999999999", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* 5. INT_MAX (2147483647) in the extra-ID field → also rejected */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:name:rw-p--a-R-c-o-:-------:allow:2147483647", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* 6. INT_MAX - 1 (2147483646) is the largest accepted id */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user:name:rw-p--a-R-c-o-:-------:allow:2147483646", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(1, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(2147483646, qual); + archive_entry_acl_clear(ae); + + /* 7. Overflow in the name field (numeric name too large) → rejected */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:99999999999:rw-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + archive_entry_free(ae); +} + +/* + * Malformed NFS4 ACL entries — each should return ARCHIVE_WARN without + * crashing. Also verifies that valid entries before an invalid one are + * still stored. + */ +DEFINE_TEST(test_acl_nfs4_text_invalid) +{ + struct archive_entry *ae; + int type, permset, tag, qual; + const char *name; + + ae = archive_entry_new(); + assert(ae != NULL); + + /* Unknown tag */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "bogus:name:rw-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* Unknown type string */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:name:rw-p--a-R-c-o-:-------:bogus", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* Invalid character in perms field */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:name:rq-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* Invalid character in flags field */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:name:rw-p--a-R-c-o-:q------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* Just a tag with no colon-separated fields */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, "user", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + /* Valid entry followed by an invalid one: valid entry must be stored + * and ARCHIVE_WARN returned (not ARCHIVE_FATAL). */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:alice:rw-p--a-R-c-o-:-------:allow\n" + "bogus:bob:rw-p--a-R-c-o-:-------:deny", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(1, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_TYPE_ALLOW, type); + assertEqualString("alice", name); + archive_entry_acl_clear(ae); + + /* Same tests via the wide parser */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"bogus:name:rw-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"user:name:rw-p--a-R-c-o-:-------:bogus", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"user:name:rq-p--a-R-c-o-:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"user:name:rw-p--a-R-c-o-:q------:allow", + ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_NFS4)); + archive_entry_acl_clear(ae); + + archive_entry_free(ae); +} diff --git a/libarchive/test/test_acl_posix1e_text.c b/libarchive/test/test_acl_posix1e_text.c new file mode 100644 index 000000000000..57084465d59e --- /dev/null +++ b/libarchive/test/test_acl_posix1e_text.c @@ -0,0 +1,530 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +#include <limits.h> + +/* + * Focused tests for POSIX.1e ACL text parsing and serialization. + * + * test_acl_text.c covers basic POSIX.1e round-trips but does not exercise: + * the mask entry, the Solaris two-field format for mask and other, uppercase + * mode letters (R/W/X), isint() overflow on the POSIX path, and various + * invalid-input error paths. These tests fill those gaps. + * + * Note: archive_entry_acl_reset(ae, TYPE_ACCESS) always returns the count + * of extended ACL entries PLUS 3 synthesized base entries (USER_OBJ, + * GROUP_OBJ, OTHER) derived from the mode bits. Tests below account for + * this by adding 3 to the expected count and skipping those 3 entries + * before iterating over the named/mask entries of interest. + */ + +/* ACCESS-only ACL including a mask entry. */ +static const char *posix1e_access = + "user::rwx\n" + "group::r-x\n" + "other::r-x\n" + "user:alice:r-x\n" + "group:staff:rwx\n" + "mask::r-x"; + +/* Combined ACCESS + DEFAULT ACL, with mask in both sections. */ +static const char *posix1e_full = + "user::rwx\n" + "group::r-x\n" + "other::r-x\n" + "user:alice:r-x\n" + "group:staff:rwx\n" + "mask::r-x\n" + "default:user::r-x\n" + "default:group::r-x\n" + "default:other::---\n" + "default:user:alice:r-x\n" + "default:group:staff:--x\n" + "default:mask::r-x"; + +/* posix1e_full with numeric IDs appended to named user/group entries. */ +static const char *posix1e_extra_id = + "user::rwx\n" + "group::r-x\n" + "other::r-x\n" + "user:alice:r-x:77\n" + "group:staff:rwx:78\n" + "mask::r-x\n" + "default:user::r-x\n" + "default:group::r-x\n" + "default:other::---\n" + "default:user:alice:r-x:77\n" + "default:group:staff:--x:78\n" + "default:mask::r-x"; + +/* + * Solaris-style ACCESS ACL: mask and other use one colon (no empty name + * field between tag and permission string). + */ +static const char *posix1e_solaris = + "user::rwx\n" + "group::r-x\n" + "other:r-x\n" + "user:alice:r-x\n" + "mask:r-x"; + +static wchar_t * +s_to_ws(const char *s) +{ + size_t len = strlen(s) + 1; + wchar_t *ws = malloc(len * sizeof(wchar_t)); + assert(ws != NULL); + assert(mbstowcs(ws, s, len) != (size_t)-1); + return (ws); +} + +/* + * Skip the three base entries (USER_OBJ, GROUP_OBJ, OTHER) that + * archive_entry_acl_reset() synthesises from mode bits and that + * archive_entry_acl_next() always returns first for ACCESS ACLs. + */ +static void +skip_base_entries(struct archive_entry *ae) +{ + int type, permset, tag, qual; + const char *name; + int i; + + for (i = 0; i < 3; i++) + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name); +} + +/* + * Round-trip: parse POSIX.1e text → serialize → compare. + * Covers ACCESS-only, combined ACCESS+DEFAULT, and the EXTRA_ID style, + * for both the narrow and wide serializers. + */ +DEFINE_TEST(test_acl_posix1e_text_roundtrip) +{ + struct archive_entry *ae; + char *text; + wchar_t *wtext, *ws; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* ACCESS-only with mask entry */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, posix1e_access, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualString(posix1e_access, text); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Combined ACCESS + DEFAULT — serializer auto-adds MARK_DEFAULT */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, posix1e_full, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + text = archive_entry_acl_to_text(ae, &len, 0); + assertEqualString(posix1e_full, text); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* EXTRA_ID format */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, posix1e_extra_id, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); + assertEqualString(posix1e_extra_id, text); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Wide: ACCESS-only round-trip */ + ws = s_to_ws(posix1e_access); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + wtext = archive_entry_acl_to_text_w(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualWString(ws, wtext); + free(wtext); + free(ws); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Wide: combined ACCESS + DEFAULT */ + ws = s_to_ws(posix1e_full); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, ws, + ARCHIVE_ENTRY_ACL_TYPE_POSIX1E)); + wtext = archive_entry_acl_to_text_w(ae, &len, 0); + assertEqualWString(ws, wtext); + free(wtext); + free(ws); + + archive_entry_free(ae); +} + +/* + * Solaris two-field format: "mask:rwx" and "other:rwx" omit the empty + * name field, so each has only two colon-separated tokens instead of three. + * The parser recognises this form; the serializer reproduces it when + * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS is set. + */ +DEFINE_TEST(test_acl_posix1e_text_solaris) +{ + struct archive_entry *ae; + char *text; + int type, permset, tag, qual; + const char *name; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* + * Parse Solaris-format text. Extended entries are: named user alice + * and mask — 2 extended + 3 base = 5 total. + */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, posix1e_solaris, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(5, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag); + assertEqualString("alice", name); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_MASK, tag); + assertEqualInt(ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE, + permset); + + /* Serialize with STYLE_SOLARIS and compare */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS); + assertEqualString(posix1e_solaris, text); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Solaris style with non-empty name on other field → ARCHIVE_WARN */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother:nobody:r-x\n", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + + archive_entry_free(ae); +} + +/* + * ismode() accepts uppercase R, W, X as well as lowercase; the serializer + * always emits lowercase. Both narrow and wide parsers share this + * behaviour. + */ +DEFINE_TEST(test_acl_posix1e_text_ismode) +{ + struct archive_entry *ae; + char *text; + int type, permset, tag, qual; + const char *name; + ssize_t len; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* + * Uppercase R/W/X treated identically to r/w/x. + * 1 extended entry (alice) + 3 base = 4 total. + */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user::RWX\ngroup::R-X\nother::---\nuser:alice:RwX", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag); + assertEqualString("alice", name); + assertEqualInt( + ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_WRITE | + ARCHIVE_ENTRY_ACL_EXECUTE, permset); + + /* Serializer always emits lowercase */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assertEqualString( + "user::rwx\ngroup::r-x\nother::---\nuser:alice:rwx", text); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Same via the wide parser */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text_w(ae, + L"user::RWX\ngroup::R-X\nother::---\nuser:alice:RwX", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt( + ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_WRITE | + ARCHIVE_ENTRY_ACL_EXECUTE, permset); + + archive_entry_free(ae); +} + +/* + * Numeric IDs in the name field and the extra-ID override field, + * including the isint() overflow boundary now enforced on the POSIX path. + */ +DEFINE_TEST(test_acl_posix1e_text_numeric_id) +{ + struct archive_entry *ae; + char *text; + ssize_t len; + int type, permset, tag, qual; + const char *name; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 1. Numeric-only name → id derived from name field */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:1000:rwx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + /* 1 extended + 3 base = 4 */ + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(1000, qual); + assertEqualString("1000", name); + /* Without EXTRA_ID the id is carried by the name string */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + assert(strstr(text, "user:1000:rwx") != NULL); + free(text); + /* With EXTRA_ID the id is also appended */ + text = archive_entry_acl_to_text(ae, &len, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS | ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID); + assert(strstr(text, "user:1000:rwx:1000") != NULL); + free(text); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 2. Trailing extra-ID field overrides name-derived id */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:alice:r-x:42", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(42, qual); + assertEqualString("alice", name); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 3. Overflow in extra-ID field → extended entry rejected, no ext entries */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:alice:r-x:99999999999", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 4. INT_MAX (2147483647) in the extra-ID field → also rejected */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:alice:r-x:2147483647", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 5. INT_MAX - 1 (2147483646) is the largest accepted id */ + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:alice:r-x:2147483646", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(2147483646, qual); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* 6. Overflow in the name field (all-digit name too large) → rejected */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\nuser:99999999999:r-x", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + + archive_entry_free(ae); +} + +/* + * Malformed POSIX.1e ACL entries — each should return ARCHIVE_WARN without + * crashing and without storing invalid data. + */ +DEFINE_TEST(test_acl_posix1e_text_invalid) +{ + struct archive_entry *ae; + int type, permset, tag, qual; + const char *name; + + ae = archive_entry_new(); + assert(ae != NULL); + archive_entry_set_pathname(ae, "file"); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Invalid character in permission field */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user:alice:rqx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Unknown tag */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "bogus:alice:rwx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* NFSv4 "everyone@" tag is not recognised by the POSIX parser */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "everyone@:r-----a-R-c--s:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Bare tag with no colon-separated fields */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, "user", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* + * Valid entry followed by invalid — valid entry must be stored. + * 1 extended (alice) + 3 base = 4 total. + */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text(ae, + "user::rwx\ngroup::r-x\nother::r-x\n" + "user:alice:r-x\n" + "bogus:bob:rwx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(4, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + skip_base_entries(ae); + assertEqualInt(ARCHIVE_OK, + archive_entry_acl_next(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + &type, &permset, &tag, &qual, &name)); + assertEqualInt(ARCHIVE_ENTRY_ACL_USER, tag); + assertEqualString("alice", name); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Wide parser: invalid permission character */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"user:alice:rqx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Wide parser: unknown tag */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"bogus:alice:rwx", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + archive_entry_acl_clear(ae); + archive_entry_set_mode(ae, AE_IFREG | 0755); + + /* Wide parser: NFSv4 tag rejected by POSIX parser */ + assertEqualInt(ARCHIVE_WARN, + archive_entry_acl_from_text_w(ae, + L"everyone@:r-----a-R-c--s:-------:allow", + ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + assertEqualInt(0, + archive_entry_acl_reset(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)); + + archive_entry_free(ae); +} diff --git a/libarchive/test/test_archive_match_path.c b/libarchive/test/test_archive_match_path.c index ce48263f7614..527413db7992 100644 --- a/libarchive/test/test_archive_match_path.c +++ b/libarchive/test/test_archive_match_path.c @@ -233,8 +233,8 @@ test_inclusion_mbs(void) return; } - /* Test for pattern "^aa*" */ - assertEqualIntA(m, 0, archive_match_include_pattern(m, "^aa*")); + /* Test for pattern "aa*" */ + assertEqualIntA(m, 0, archive_match_include_pattern(m, "aa*")); /* Test with 'aa1234', which should not be excluded. */ archive_entry_copy_pathname(ae, "aa1234"); @@ -282,8 +282,8 @@ test_inclusion_wcs(void) return; } - /* Test for pattern "^aa*" */ - assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"^aa*")); + /* Test for pattern "aa*" */ + assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"aa*")); /* Test with 'aa1234', which should not be excluded. */ archive_entry_copy_pathname(ae, "aa1234"); @@ -383,8 +383,8 @@ test_exclusion_and_inclusion(void) } assertEqualIntA(m, 0, archive_match_exclude_pattern(m, "^aaa*")); - assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"^aa*")); - assertEqualIntA(m, 0, archive_match_include_pattern(m, "^a1*")); + assertEqualIntA(m, 0, archive_match_include_pattern_w(m, L"aa*")); + assertEqualIntA(m, 0, archive_match_include_pattern(m, "a1*")); /* Test with 'aa1234', which should not be excluded. */ archive_entry_copy_pathname(ae, "aa1234"); @@ -413,13 +413,13 @@ test_exclusion_and_inclusion(void) /* Verify unmatched inclusion patterns. */ assertEqualIntA(m, ARCHIVE_OK, archive_match_path_unmatched_inclusions_next(m, &mp)); - assertEqualString("^a1*", mp); + assertEqualString("a1*", mp); assertEqualIntA(m, ARCHIVE_EOF, archive_match_path_unmatched_inclusions_next(m, &mp)); /* Verify unmatched inclusion patterns again in Wide-Char. */ assertEqualIntA(m, ARCHIVE_OK, archive_match_path_unmatched_inclusions_next_w(m, &wp)); - assertEqualWString(L"^a1*", wp); + assertEqualWString(L"a1*", wp); assertEqualIntA(m, ARCHIVE_EOF, archive_match_path_unmatched_inclusions_next_w(m, &wp)); diff --git a/libarchive/test/test_archive_parse_date.c b/libarchive/test/test_archive_parse_date.c index 5251b3393999..03e628913633 100644 --- a/libarchive/test/test_archive_parse_date.c +++ b/libarchive/test/test_archive_parse_date.c @@ -35,65 +35,72 @@ DEFINE_TEST(test_archive_parse_date) { time_t now = time(NULL); + long long expected; - assertEqualInt(get_date(now, "Jan 1, 1970 UTC"), 0); - assertEqualInt(get_date(now, "7:12:18-0530 4 May 1983"), 420900138); - assertEqualInt(get_date(now, "2004/01/29 513 mest"), 1075345980); - assertEqualInt(get_date(now, "2038-06-01 00:01:02 UTC"), + assertEqualInt(archive_parse_date(now, "Jan 1, 1970 UTC"), 0); + assertEqualInt(archive_parse_date(now, "7:12:18-0530 4 May 1983"), 420900138); + assertEqualInt(archive_parse_date(now, "2004/01/29 513 mest"), 1075345980); + assertEqualInt(archive_parse_date(now, "2038-06-01 00:01:02 UTC"), sizeof(time_t) <= 4 ? -1 : 2158963262); - assertEqualInt(get_date(now, "99/02/17 7pm utc"), 919278000); - assertEqualInt(get_date(now, "02/17/99 7:11am est"), 919253460); - assertEqualInt(get_date(now, "now - 2 hours"), - get_date(now, "2 hours ago")); - assertEqualInt(get_date(now, "2 hours ago"), - get_date(now, "+2 hours ago")); - assertEqualInt(get_date(now, "now - 2 hours"), - get_date(now, "-2 hours")); + assertEqualInt(archive_parse_date(now, "99/02/17 7pm utc"), 919278000); + assertEqualInt(archive_parse_date(now, "02/17/99 7:11am est"), 919253460); + assertEqualInt(archive_parse_date(now, "now - 2 hours"), + archive_parse_date(now, "2 hours ago")); + assertEqualInt(archive_parse_date(now, "2 hours ago"), + archive_parse_date(now, "+2 hours ago")); + assertEqualInt(archive_parse_date(now, "now - 2 hours"), + archive_parse_date(now, "-2 hours")); /* It's important that we handle ctime() format. */ - assertEqualInt(get_date(now, "Sun Feb 22 17:38:26 PST 2009"), + assertEqualInt(archive_parse_date(now, "Sun Feb 22 17:38:26 PST 2009"), 1235353106); /* Basic relative offsets. */ /* If we use the actual current time as the reference, then * these tests break around DST changes, so it's actually * important to use a specific reference time here. */ - assertEqualInt(get_date(0, "tomorrow"), 24 * 60 * 60); - assertEqualInt(get_date(0, "yesterday"), - 24 * 60 * 60); - assertEqualInt(get_date(0, "now + 1 hour"), 60 * 60); - assertEqualInt(get_date(0, "now + 1 hour + 1 minute"), 60 * 60 + 60); + assertEqualInt(archive_parse_date(0, "tomorrow"), 24 * 60 * 60); + assertEqualInt(archive_parse_date(0, "yesterday"), - 24 * 60 * 60); + assertEqualInt(archive_parse_date(0, "now + 1 hour"), 60 * 60); + assertEqualInt(archive_parse_date(0, "now + 1 hour + 1 minute"), 60 * 60 + 60); /* Repeat the above for a different start time. */ now = 1231113600; /* Jan 5, 2009 00:00 UTC */ - assertEqualInt(get_date(0, "Jan 5, 2009 00:00 UTC"), now); - assertEqualInt(get_date(now, "tomorrow"), now + 24 * 60 * 60); - assertEqualInt(get_date(now, "yesterday"), now - 24 * 60 * 60); - assertEqualInt(get_date(now, "now + 1 hour"), now + 60 * 60); - assertEqualInt(get_date(now, "now + 1 hour + 1 minute"), + assertEqualInt(archive_parse_date(0, "Jan 5, 2009 00:00 UTC"), now); + assertEqualInt(archive_parse_date(now, "tomorrow"), now + 24 * 60 * 60); + assertEqualInt(archive_parse_date(now, "yesterday"), now - 24 * 60 * 60); + assertEqualInt(archive_parse_date(now, "now + 1 hour"), now + 60 * 60); + assertEqualInt(archive_parse_date(now, "now + 1 hour + 1 minute"), now + 60 * 60 + 60); - assertEqualInt(get_date(now, "tomorrow 5:16am UTC"), + assertEqualInt(archive_parse_date(now, "tomorrow 5:16am UTC"), now + 24 * 60 * 60 + 5 * 60 * 60 + 16 * 60); - assertEqualInt(get_date(now, "UTC 5:16am tomorrow"), + assertEqualInt(archive_parse_date(now, "UTC 5:16am tomorrow"), now + 24 * 60 * 60 + 5 * 60 * 60 + 16 * 60); /* Jan 5, 2009 was a Monday. */ - assertEqualInt(get_date(now, "monday UTC"), now); - assertEqualInt(get_date(now, "sunday UTC"), now + 6 * 24 * 60 * 60); - assertEqualInt(get_date(now, "tuesday UTC"), now + 24 * 60 * 60); + assertEqualInt(archive_parse_date(now, "monday UTC"), now); + assertEqualInt(archive_parse_date(now, "sunday UTC"), now + 6 * 24 * 60 * 60); + assertEqualInt(archive_parse_date(now, "tuesday UTC"), now + 24 * 60 * 60); /* "next tuesday" is one week after "tuesday" */ - assertEqualInt(get_date(now, "UTC next tuesday"), + assertEqualInt(archive_parse_date(now, "UTC next tuesday"), now + 8 * 24 * 60 * 60); /* "last tuesday" is one week before "tuesday" */ - assertEqualInt(get_date(now, "last tuesday UTC"), + assertEqualInt(archive_parse_date(now, "last tuesday UTC"), now - 6 * 24 * 60 * 60); /* Unix epoch timestamps */ - assertEqualInt(get_date(now, "@0"), 0); - assertEqualInt(get_date(now, "@100"), 100); - assertEqualInt(get_date(now, "@+100"), 100); + assertEqualInt(archive_parse_date(now, "@0"), 0); + assertEqualInt(archive_parse_date(now, "@100"), 100); + assertEqualInt(archive_parse_date(now, "@1000000000"), 1000000000); + assertEqualInt(archive_parse_date(now, "@+100"), 100); - assertEqualInt(get_date(now, "@"), -1); - assertEqualInt(get_date(now, "@-"), -1); - assertEqualInt(get_date(now, "@+"), -1); - assertEqualInt(get_date(now, "@tenth"), -1); - assertEqualInt(get_date(now, "@100 tomorrow"), -1); + assertEqualInt(archive_parse_date(now, "@"), -1); + assertEqualInt(archive_parse_date(now, "@-"), -1); + assertEqualInt(archive_parse_date(now, "@+"), -1); + assertEqualInt(archive_parse_date(now, "@tenth"), -1); + assertEqualInt(archive_parse_date(now, "@100 tomorrow"), -1); - /* TODO: Lots more tests here. */ + /* Verify handling of overlarge numbers */ + expected = sizeof(time_t) == 4 ? -1 : 253375948800LL; + assertEqualInt(archive_parse_date(now, "Jan 1, 9999 UTC"), expected); + assertEqualInt(archive_parse_date(now, "Jan 1, 10000 UTC"), -1); + assertEqualInt(archive_parse_date(now, "Jan 1, 99999 UTC"), -1); + assertEqualInt(archive_parse_date(time(NULL), "2147483647-01-01 00:00:00"), -1); } diff --git a/libarchive/test/test_archive_pathmatch.c b/libarchive/test/test_archive_pathmatch.c index 3b212aca9d94..ea75851dbe64 100644 --- a/libarchive/test/test_archive_pathmatch.c +++ b/libarchive/test/test_archive_pathmatch.c @@ -56,6 +56,10 @@ DEFINE_TEST(test_archive_pathmatch) assertEqualInt(0, archive_pathmatch_w(L"a/b/c", NULL, 0)); /* Empty pattern only matches empty string. */ + assertEqualInt(1, archive_pathmatch(NULL,NULL, 0)); + assertEqualInt(1, archive_pathmatch(NULL,"", 0)); + assertEqualInt(0, archive_pathmatch(NULL,"a", 0)); + assertEqualInt(1, archive_pathmatch("",NULL, 0)); assertEqualInt(1, archive_pathmatch("","", 0)); assertEqualInt(0, archive_pathmatch("","a", 0)); assertEqualInt(1, archive_pathmatch("*","", 0)); @@ -76,11 +80,15 @@ DEFINE_TEST(test_archive_pathmatch) assertEqualInt(0, archive_pathmatch("a", "ab", 0)); assertEqualInt(0, archive_pathmatch("a", "ab", 0)); assertEqualInt(1, archive_pathmatch("a?c", "abc", 0)); + assertEqualInt(1, archive_pathmatch("*a", "/a", 0)); + assertEqualInt(1, archive_pathmatch("*a", "a", 0)); /* SUSv2: ? matches / */ assertEqualInt(1, archive_pathmatch("a?c", "a/c", 0)); assertEqualInt(1, archive_pathmatch("a?*c*", "a/c", 0)); assertEqualInt(1, archive_pathmatch("*a*", "a/c", 0)); assertEqualInt(1, archive_pathmatch("*a*", "/a/c", 0)); + assertEqualInt(0, archive_pathmatch("*a", "/a/c", 0)); + assertEqualInt(0, archive_pathmatch("*a", "a/c", 0)); assertEqualInt(1, archive_pathmatch("*a*", "defaaaaaaa", 0)); assertEqualInt(0, archive_pathmatch("a*", "defghi", 0)); assertEqualInt(0, archive_pathmatch("*a*", "defghi", 0)); @@ -201,6 +209,14 @@ DEFINE_TEST(test_archive_pathmatch) failure("Trailing '/.' is still the same directory."); assertEqualInt(1, archive_pathmatch("./abc*/./def", "abc/def/.", 0)); + /* Anchor characters without flags not special. */ + assertEqualInt(0, archive_pathmatch("^abc", "abc", 0)); + assertEqualInt(1, archive_pathmatch("^abc", "^abc", 0)); + assertEqualInt(0, archive_pathmatch("abc$", "abc", 0)); + assertEqualInt(1, archive_pathmatch("abc$", "abc$", 0)); + assertEqualInt(0, archive_pathmatch("^abc$", "abc", 0)); + assertEqualInt(1, archive_pathmatch("^abc$", "^abc$", 0)); + /* Matches not anchored at beginning. */ assertEqualInt(0, archive_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_START)); diff --git a/libarchive/test/test_archive_pathmatch_oob.c b/libarchive/test/test_archive_pathmatch_oob.c new file mode 100644 index 000000000000..fc8f4a5ca178 --- /dev/null +++ b/libarchive/test/test_archive_pathmatch_oob.c @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 2025 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +#include <stdlib.h> +#include <string.h> + +/* + * Regression test: malformed bracket expressions in patterns caused + * heap-buffer-overflow reads in pm() (BUG-003) and strchr OOB via + * archive_match (BUG-007). + * + * To reproduce under ASan, we must allocate tight heap buffers for the + * pattern and string (just like the fuzzer does), so that ASan's + * redzones detect overreads. + */ + +/* Declare the internal function we want to test. */ +int __archive_pathmatch(const char *pattern, const char *string, int flags); + +/* + * Replay a fuzzer repro file through __archive_pathmatch(). + * Format: byte 0 = flags, then rest is split at first '\0' into + * pattern and string, each copied into tight malloc'd buffers. + */ +static void +replay_pathmatch_repro(const char *refname) +{ + FILE *f; + unsigned char buf[4096]; + size_t size, split, rest_len, str_start, str_len; + const unsigned char *rest; + char *pattern, *string; + int flags; + size_t i; + + extract_reference_file(refname); + + f = fopen(refname, "rb"); + if (!assert(f != NULL)) + return; + size = fread(buf, 1, sizeof(buf), f); + fclose(f); + if (!assert(size >= 4)) + return; + + flags = buf[0] % 8; + rest = buf + 1; + rest_len = size - 1; + + /* Find split point (first null byte in rest). */ + split = 0; + for (i = 0; i < rest_len; i++) { + if (rest[i] == 0) { + split = i; + break; + } + } + if (split == 0) + split = rest_len / 2; + + /* Allocate tight buffers so ASan can detect overreads. */ + pattern = (char *)malloc(split + 1); + if (!assert(pattern != NULL)) + return; + memcpy(pattern, rest, split); + pattern[split] = '\0'; + + str_start = (split < rest_len && rest[split] == 0) + ? split + 1 : split; + str_len = rest_len - str_start; + string = (char *)malloc(str_len + 1); + if (!assert(string != NULL)) { + free(pattern); + return; + } + memcpy(string, rest + str_start, str_len); + string[str_len] = '\0'; + + /* This must not read past the allocated buffers. */ + __archive_pathmatch(pattern, string, flags); + + free(pattern); + free(string); +} + +DEFINE_TEST(test_archive_pathmatch_oob_bracket) +{ + replay_pathmatch_repro("test_archive_pathmatch_oob_bracket.bin"); +} + +DEFINE_TEST(test_archive_pathmatch_oob_strchr) +{ + replay_pathmatch_repro("test_archive_pathmatch_oob_strchr.bin"); +} diff --git a/libarchive/test/test_archive_pathmatch_oob_bracket.bin.uu b/libarchive/test/test_archive_pathmatch_oob_bracket.bin.uu new file mode 100644 index 000000000000..5984a0d34c94 --- /dev/null +++ b/libarchive/test/test_archive_pathmatch_oob_bracket.bin.uu @@ -0,0 +1,4 @@ +begin 644 test_archive_pathmatch_oob_bracket.bin +,6ULAC"&,*HPJ73\` +` +end diff --git a/libarchive/test/test_archive_pathmatch_oob_strchr.bin.uu b/libarchive/test/test_archive_pathmatch_oob_strchr.bin.uu new file mode 100644 index 000000000000..b961b0a08827 --- /dev/null +++ b/libarchive/test/test_archive_pathmatch_oob_strchr.bin.uu @@ -0,0 +1,8 @@ +begin 644 test_archive_pathmatch_oob_strchr.bin +M`2H_*C];(0(M7%@K,`+;725S871U<F1A>5SX*@`!*ELI+2]=`0!A$``!9(`! +M*BI;(0(J72KEY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7E +MY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>7EY>4``0@"`0`0&@``*@`J*BH` +M`2HJ*@``)```&P`!*"HJ``$`"#\D```J`"JJ``(`T@(J*@`#`"H``2HJ*@`! +'*@"3`5L``@`` +` +end diff --git a/libarchive/test/test_archive_read_close_twice.c b/libarchive/test/test_archive_read_close_twice.c index 2f5ee77f117e..4320ae670565 100644 --- a/libarchive/test/test_archive_read_close_twice.c +++ b/libarchive/test/test_archive_read_close_twice.c @@ -29,11 +29,11 @@ DEFINE_TEST(test_archive_read_close_twice) { struct archive* a = archive_read_new(); - assertEqualInt(0, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); - assertEqualInt(0, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); diff --git a/libarchive/test/test_archive_read_close_twice_open_fd.c b/libarchive/test/test_archive_read_close_twice_open_fd.c index 62a6a90df1fa..852038dde3f4 100644 --- a/libarchive/test/test_archive_read_close_twice_open_fd.c +++ b/libarchive/test/test_archive_read_close_twice_open_fd.c @@ -34,11 +34,11 @@ DEFINE_TEST(test_archive_read_close_twice_open_fd) assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); diff --git a/libarchive/test/test_archive_read_close_twice_open_filename.c b/libarchive/test/test_archive_read_close_twice_open_filename.c index 4824319b42bf..0be64091d77d 100644 --- a/libarchive/test/test_archive_read_close_twice_open_filename.c +++ b/libarchive/test/test_archive_read_close_twice_open_filename.c @@ -36,11 +36,11 @@ DEFINE_TEST(test_archive_read_close_twice_open_filename) assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(0, archive_errno(a)); assertEqualString(NULL, archive_error_string(a)); diff --git a/libarchive/test/test_archive_string.c b/libarchive/test/test_archive_string.c index bf822c0d5e82..c9c5c195a9a7 100644 --- a/libarchive/test/test_archive_string.c +++ b/libarchive/test/test_archive_string.c @@ -388,6 +388,7 @@ test_archive_string_dirname(void) archive_string_dirname(&s); assertEqualString(pair->exp, s.s); } + archive_string_free(&s); } DEFINE_TEST(test_archive_string) diff --git a/libarchive/test/test_archive_string_conversion.c b/libarchive/test/test_archive_string_conversion.c index ecc39dffea7f..4bf17185cc01 100644 --- a/libarchive/test/test_archive_string_conversion.c +++ b/libarchive/test/test_archive_string_conversion.c @@ -338,13 +338,13 @@ test_archive_string_normalization_nfc(const char *testdata) nfd[sizeof(nfd)-1] = '\0'; /* - * Get an NFC patterns. + * Get an NFC pattern. */ scan_unicode_pattern(utf8_nfc, wc_nfc, utf16be_nfc, utf16le_nfc, nfc, 0); /* - * Get an NFD patterns. + * Get an NFD pattern. */ scan_unicode_pattern(utf8_nfd, wc_nfd, utf16be_nfd, utf16le_nfd, nfd, 0); @@ -550,7 +550,7 @@ test_archive_string_normalization_mac_nfd(const char *testdata) nfd[sizeof(nfd)-1] = '\0'; /* - * Get an NFC patterns. + * Get an NFC pattern. */ should_be_nfc = scan_unicode_pattern(utf8_nfc, wc_nfc, utf16be_nfc, utf16le_nfc, nfc, 1); @@ -966,6 +966,10 @@ test_archive_string_conversion_fail_utf8_mbs(struct archive *a, DEFINE_TEST(test_archive_string_conversion_fail_c) { struct archive *a; +#if defined(__sun) + skipping("Solaris iconv substitutes unrepresentable UTF-8 characters"); + return; +#endif /* Test the C locale by not calling setlocale. */ @@ -983,6 +987,10 @@ DEFINE_TEST(test_archive_string_conversion_fail_latin1) { struct archive *a; struct archive_string_conv *sconv; +#if defined(__sun) + skipping("Solaris iconv substitutes unrepresentable UTF-8 characters"); + return; +#endif /* Test a Latin-1 locale. */ if ( diff --git a/libarchive/test/test_archive_write_add_filter.c b/libarchive/test/test_archive_write_add_filter.c new file mode 100644 index 000000000000..3a549d57230b --- /dev/null +++ b/libarchive/test/test_archive_write_add_filter.c @@ -0,0 +1,208 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * Copyright (c) 2026 i1011 + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" + +static void +test_add_filter_by_code(int filter_code, + int (*can_filter_prog)(void)) +{ + struct archive_entry *ae; + struct archive *a; + size_t used; + size_t buffsize = 1024 * 128; + char *buff; + int r; + + assert((buff = calloc(buffsize, sizeof(*buff))) != NULL); + if (buff == NULL) + return; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); + r = archive_write_add_filter(a, filter_code); + if (r == ARCHIVE_WARN) { + if (!can_filter_prog()) { + skipping("Filter code \"%d\" not supported on this platform", + filter_code); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } + } else if (r == ARCHIVE_FATAL && + (strcmp(archive_error_string(a), + "lzma compression not supported on this platform") == 0 || + strcmp(archive_error_string(a), + "xz compression not supported on this platform") == 0)) { + skipping("Filter code \"%d\" not supported on this platform", + filter_code); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } else { + if (!assertEqualIntA(a, ARCHIVE_OK, r)) { + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); + return; + } + } + if (filter_code == ARCHIVE_FILTER_LRZIP) + { + /* + * There's a bug in lrzip (as of release 0.612) where 2nd stage + * compression can't be performed on smaller files. Set lrzip to + * use no 2nd stage compression. + */ + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_options(a, "lrzip:compression=none")); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 10)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + /* + * Write a file to it. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 0); + assertEqualInt(1, archive_entry_mtime(ae)); + archive_entry_set_ctime(ae, 1, 0); + assertEqualInt(1, archive_entry_ctime(ae)); + archive_entry_set_atime(ae, 1, 0); + assertEqualInt(1, archive_entry_atime(ae)); + archive_entry_copy_pathname(ae, "file"); + assertEqualString("file", archive_entry_pathname(ae)); + archive_entry_set_mode(ae, AE_IFREG | 0755); + assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); + archive_entry_set_size(ae, 8); + assertEqualInt(0, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualInt(8, archive_write_data(a, "12345678", 8)); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* + * Read and verify the file. + */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_entry_mtime(ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); + assertEqualInt(8, archive_entry_size(ae)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify archive format. */ + assertEqualIntA(a, filter_code, archive_filter_code(a, 0)); + assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(buff); +} + +static int +canAlways(void) +{ + return 1; +} + +DEFINE_TEST(test_archive_write_add_filter_none) +{ + test_add_filter_by_code(ARCHIVE_FILTER_NONE, canAlways); +} + +DEFINE_TEST(test_archive_write_add_filter_gzip) +{ + test_add_filter_by_code(ARCHIVE_FILTER_GZIP, canGzip); +} + +DEFINE_TEST(test_archive_write_add_filter_bzip2) +{ + test_add_filter_by_code(ARCHIVE_FILTER_BZIP2, canBzip2); +} + +DEFINE_TEST(test_archive_write_add_filter_compress) +{ + test_add_filter_by_code(ARCHIVE_FILTER_COMPRESS, canAlways); +} + +DEFINE_TEST(test_archive_write_add_filter_grzip) +{ + test_add_filter_by_code(ARCHIVE_FILTER_GRZIP, canGrzip); +} + +DEFINE_TEST(test_archive_write_add_filter_lrzip) +{ + test_add_filter_by_code(ARCHIVE_FILTER_LRZIP, canLrzip); +} + +DEFINE_TEST(test_archive_write_add_filter_lz4) +{ + test_add_filter_by_code(ARCHIVE_FILTER_LZ4, canLz4); +} + +DEFINE_TEST(test_archive_write_add_filter_lzip) +{ + test_add_filter_by_code(ARCHIVE_FILTER_LZIP, canLzip); +} + +DEFINE_TEST(test_archive_write_add_filter_lzma) +{ + test_add_filter_by_code(ARCHIVE_FILTER_LZMA, canLzma); +} + +DEFINE_TEST(test_archive_write_add_filter_lzop) +{ + test_add_filter_by_code(ARCHIVE_FILTER_LZOP, canLzop); +} + +DEFINE_TEST(test_archive_write_add_filter_uuencode) +{ + test_add_filter_by_code(ARCHIVE_FILTER_UU, canAlways); +} + +DEFINE_TEST(test_archive_write_add_filter_xz) +{ + test_add_filter_by_code(ARCHIVE_FILTER_XZ, canXz); +} + +DEFINE_TEST(test_archive_write_add_filter_zstd) +{ + test_add_filter_by_code(ARCHIVE_FILTER_ZSTD, canZstd); +} diff --git a/libarchive/test/test_archive_write_add_filter_by_name.c b/libarchive/test/test_archive_write_add_filter_by_name.c index 9d7e58d6f635..f0785203039b 100644 --- a/libarchive/test/test_archive_write_add_filter_by_name.c +++ b/libarchive/test/test_archive_write_add_filter_by_name.c @@ -129,7 +129,7 @@ test_filter_by_name(const char *filter_name, int filter_code, assertEqualIntA(a, filter_code, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/libarchive/test/test_archive_write_set_format_by_name.c b/libarchive/test/test_archive_write_set_format_by_name.c index 07942f6bffc8..f8ca04db36e4 100644 --- a/libarchive/test/test_archive_write_set_format_by_name.c +++ b/libarchive/test/test_archive_write_set_format_by_name.c @@ -130,7 +130,7 @@ test_format_by_name(const char *format_name, const char *compression_type, archive_filter_code(a, 0)); assertEqualIntA(a, format_id, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } free(buff); diff --git a/libarchive/test/test_archive_write_set_format_filter_by_ext.c b/libarchive/test/test_archive_write_set_format_filter_by_ext.c index fe6c350e48e7..849a9c5a078d 100644 --- a/libarchive/test/test_archive_write_set_format_filter_by_ext.c +++ b/libarchive/test/test_archive_write_set_format_filter_by_ext.c @@ -137,7 +137,7 @@ test_format_filter_by_ext(const char *output_file, archive_filter_code(a, 0)); assertEqualIntA(a, format_id, archive_format(a) & ARCHIVE_FORMAT_BASE_MASK ); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } free(buff); diff --git a/libarchive/test/test_compat_bzip2.c b/libarchive/test/test_compat_bzip2.c index e126e6f7d329..8fd04a7dad15 100644 --- a/libarchive/test/test_compat_bzip2.c +++ b/libarchive/test/test_compat_bzip2.c @@ -48,6 +48,7 @@ compat_bzip2(const char *name) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("Unsupported bzip2"); + archive_read_free(a); return; } assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); diff --git a/libarchive/test/test_compat_cpio.c b/libarchive/test/test_compat_cpio.c index 12512881112b..1c139c77f955 100644 --- a/libarchive/test/test_compat_cpio.c +++ b/libarchive/test/test_compat_cpio.c @@ -92,7 +92,7 @@ test_compat_cpio_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_NOCRC); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_gtar.c b/libarchive/test/test_compat_gtar.c index ba42e726cf78..fe3cfec9077d 100644 --- a/libarchive/test/test_compat_gtar.c +++ b/libarchive/test/test_compat_gtar.c @@ -101,7 +101,7 @@ test_compat_gtar_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -141,7 +141,7 @@ test_compat_gtar_2(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_gtar_large.c b/libarchive/test/test_compat_gtar_large.c index 633b20c0a9f8..b9a467b1c95f 100644 --- a/libarchive/test/test_compat_gtar_large.c +++ b/libarchive/test/test_compat_gtar_large.c @@ -218,7 +218,7 @@ DEFINE_TEST(test_compat_gtar_large) /* Verify that the reader actually read to the end of data */ assertEqualInt(reader.zero_blocks_remaining, 0); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(reader.zero_block); } diff --git a/libarchive/test/test_compat_gzip.c b/libarchive/test/test_compat_gzip.c index 20fce7af432d..475c13674575 100644 --- a/libarchive/test/test_compat_gzip.c +++ b/libarchive/test/test_compat_gzip.c @@ -77,7 +77,7 @@ verify(const char *name) assertEqualString(archive_filter_name(a, 0), "gzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_lz4.c b/libarchive/test/test_compat_lz4.c index 8ab9208b0918..d053155694d1 100644 --- a/libarchive/test/test_compat_lz4.c +++ b/libarchive/test/test_compat_lz4.c @@ -31,7 +31,7 @@ * In particular: * * lz4 -d will read multiple lz4 streams, concatenating the output * * lz4 -d will stop at the end of a stream if the following data - * doesn't start with a lz4 signature. + * doesn't start with an lz4 signature. */ /* @@ -78,7 +78,7 @@ verify(const char *name, const char *n[]) assertEqualString(archive_filter_name(a, 0), "lz4"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_lzip.c b/libarchive/test/test_compat_lzip.c index cd246b943b22..9a8196f61d49 100644 --- a/libarchive/test/test_compat_lzip.c +++ b/libarchive/test/test_compat_lzip.c @@ -124,7 +124,7 @@ compat_lzip(const char *name) assertEqualString(archive_filter_name(a, 0), "lzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -165,7 +165,7 @@ compat_lzip_3(const char *name) assertEqualString(archive_filter_name(a, 0), "lzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_RAW); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -202,7 +202,7 @@ compat_lzip_4(const char *name) assertEqualString(archive_filter_name(a, 0), "lzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_lzma.c b/libarchive/test/test_compat_lzma.c index b9cad55514a1..af988e1f2b54 100644 --- a/libarchive/test/test_compat_lzma.c +++ b/libarchive/test/test_compat_lzma.c @@ -133,7 +133,7 @@ compat_lzma(const char *name) assertEqualString(archive_filter_name(a, 0), "lzma"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_lzop.c b/libarchive/test/test_compat_lzop.c index 2da4e8eb6dc2..a70d658244c4 100644 --- a/libarchive/test/test_compat_lzop.c +++ b/libarchive/test/test_compat_lzop.c @@ -70,7 +70,7 @@ DEFINE_TEST(test_compat_lzop) assertEqualString(archive_filter_name(a, 0), "lzop"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* @@ -101,7 +101,7 @@ DEFINE_TEST(test_compat_lzop) assertEqualString(archive_filter_name(a, 0), "lzop"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* @@ -125,6 +125,6 @@ DEFINE_TEST(test_compat_lzop) assertEqualString(archive_filter_name(a, 0), "lzop"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_mac.c b/libarchive/test/test_compat_mac.c index 976f04a473f6..9532d079affc 100644 --- a/libarchive/test/test_compat_mac.c +++ b/libarchive/test/test_compat_mac.c @@ -130,7 +130,7 @@ test_compat_mac_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -201,7 +201,7 @@ test_compat_mac_2(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_perl_archive_tar.c b/libarchive/test/test_compat_perl_archive_tar.c index 94abe3f056a3..1574f7bc8ffb 100644 --- a/libarchive/test/test_compat_perl_archive_tar.c +++ b/libarchive/test/test_compat_perl_archive_tar.c @@ -60,6 +60,6 @@ DEFINE_TEST(test_compat_perl_archive_tar) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_plexus_archiver_tar.c b/libarchive/test/test_compat_plexus_archiver_tar.c index 419e84b1c4c9..8346fb555e53 100644 --- a/libarchive/test/test_compat_plexus_archiver_tar.c +++ b/libarchive/test/test_compat_plexus_archiver_tar.c @@ -63,6 +63,6 @@ DEFINE_TEST(test_compat_plexus_archiver_tar) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_solaris_pax_sparse.c b/libarchive/test/test_compat_solaris_pax_sparse.c index 94e3e9189bc2..1d3c2beb5579 100644 --- a/libarchive/test/test_compat_solaris_pax_sparse.c +++ b/libarchive/test/test_compat_solaris_pax_sparse.c @@ -100,7 +100,7 @@ test_compat_solaris_pax_sparse_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -172,7 +172,7 @@ test_compat_solaris_pax_sparse_2(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_tar_directory.c b/libarchive/test/test_compat_tar_directory.c index 3d086f1da7bc..92278fdc6c43 100644 --- a/libarchive/test/test_compat_tar_directory.c +++ b/libarchive/test/test_compat_tar_directory.c @@ -64,7 +64,7 @@ test_compat_tar_directory_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_tar_hardlink.c b/libarchive/test/test_compat_tar_hardlink.c index b8517440aea5..4f4c8904ac5b 100644 --- a/libarchive/test/test_compat_tar_hardlink.c +++ b/libarchive/test/test_compat_tar_hardlink.c @@ -91,7 +91,7 @@ test_compat_tar_hardlink_1(void) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_xz.c b/libarchive/test/test_compat_xz.c index f904583782d2..3170b149c605 100644 --- a/libarchive/test/test_compat_xz.c +++ b/libarchive/test/test_compat_xz.c @@ -72,7 +72,7 @@ compat_xz(const char *name) assertEqualString(archive_filter_name(a, 0), "xz"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_compat_zip.c b/libarchive/test/test_compat_zip.c index e2d41cc9b439..1f120692eccc 100644 --- a/libarchive/test/test_compat_zip.c +++ b/libarchive/test/test_compat_zip.c @@ -58,7 +58,7 @@ DEFINE_TEST(test_compat_zip_1) assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ZIP); finish: - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -89,7 +89,7 @@ DEFINE_TEST(test_compat_zip_2) assertEqualString("file2", archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -140,7 +140,7 @@ DEFINE_TEST(test_compat_zip_3) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } /** @@ -188,7 +188,7 @@ DEFINE_TEST(test_compat_zip_4) assertEqualInt(0644, archive_entry_perm(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* Try reading without seek support and watch it fail. */ assert((a = archive_read_new()) != NULL); @@ -196,7 +196,7 @@ DEFINE_TEST(test_compat_zip_4) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_FATAL, read_open_memory(a, p, s, 3)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } /** @@ -273,7 +273,7 @@ DEFINE_TEST(test_compat_zip_5) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* Try reading without seek support. */ assert((a = archive_read_new()) != NULL); @@ -332,7 +332,7 @@ DEFINE_TEST(test_compat_zip_5) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } @@ -376,14 +376,14 @@ DEFINE_TEST(test_compat_zip_6) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 7)); compat_zip_6_verify(a); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); assert((a = archive_read_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 7)); compat_zip_6_verify(a); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } @@ -417,7 +417,7 @@ DEFINE_TEST(test_compat_zip_7) assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } free(p); } @@ -444,6 +444,6 @@ DEFINE_TEST(test_compat_zip_8) assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); /* This file is in the archive as arc\test */ assertEqualString("arc/test", archive_entry_pathname(ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/libarchive/test/test_compat_zstd.c b/libarchive/test/test_compat_zstd.c index 34b8edeb924d..8785aa39e2c3 100644 --- a/libarchive/test/test_compat_zstd.c +++ b/libarchive/test/test_compat_zstd.c @@ -67,7 +67,7 @@ compat_zstd(const char *name) assertEqualString(archive_filter_name(a, 0), "zstd"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_fuzz_consumer.h b/libarchive/test/test_fuzz_consumer.h new file mode 100644 index 000000000000..4033253e7a84 --- /dev/null +++ b/libarchive/test/test_fuzz_consumer.h @@ -0,0 +1,143 @@ +/*- + * Copyright (c) 2025 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * C99 equivalent of the DataConsumer class used by the C++ fuzzers. + * Consumes bytes sequentially from a buffer, matching the fuzzer protocol. + * Not all consumers use every function, so suppress unused warnings. + */ +#ifndef TEST_FUZZ_CONSUMER_H +#define TEST_FUZZ_CONSUMER_H + +#include <stdint.h> +#include <stddef.h> +#include <string.h> + +#if defined(__GNUC__) || defined(__clang__) +#define FUZZ_UNUSED __attribute__((unused)) +#else +#define FUZZ_UNUSED +#endif + +struct fuzz_consumer { + const uint8_t *data; + size_t size; + size_t pos; + char string_buf[512]; +}; + +FUZZ_UNUSED static void +fuzz_consumer_init(struct fuzz_consumer *c, const uint8_t *data, size_t size) +{ + c->data = data; + c->size = size; + c->pos = 0; +} + +FUZZ_UNUSED static size_t +fuzz_consumer_remaining(const struct fuzz_consumer *c) +{ + return c->size - c->pos; +} + +FUZZ_UNUSED static uint8_t +fuzz_consume_byte(struct fuzz_consumer *c) +{ + if (c->pos >= c->size) + return 0; + return c->data[c->pos++]; +} + +FUZZ_UNUSED static uint16_t +fuzz_consume_u16(struct fuzz_consumer *c) +{ + uint16_t val = 0; + if (c->pos + 2 <= c->size) { + val = (uint16_t)c->data[c->pos] + | ((uint16_t)c->data[c->pos + 1] << 8); + c->pos += 2; + } + return val; +} + +FUZZ_UNUSED static uint32_t +fuzz_consume_u32(struct fuzz_consumer *c) +{ + uint32_t val = 0; + if (c->pos + 4 <= c->size) { + val = (uint32_t)c->data[c->pos] + | ((uint32_t)c->data[c->pos + 1] << 8) + | ((uint32_t)c->data[c->pos + 2] << 16) + | ((uint32_t)c->data[c->pos + 3] << 24); + c->pos += 4; + } + return val; +} + +FUZZ_UNUSED static int64_t +fuzz_consume_i64(struct fuzz_consumer *c) +{ + int64_t val = 0; + if (c->pos + 8 <= c->size) { + int i; + for (i = 0; i < 8; i++) + val |= (int64_t)c->data[c->pos + i] << (8 * i); + c->pos += 8; + } + return val; +} + +FUZZ_UNUSED static const char * +fuzz_consume_string(struct fuzz_consumer *c, size_t max_len) +{ + size_t avail, len, actual_len; + if (max_len > sizeof(c->string_buf) - 1) + max_len = sizeof(c->string_buf) - 1; + avail = c->size - c->pos; + len = (avail < max_len) ? avail : max_len; + actual_len = 0; + while (actual_len < len && c->pos < c->size) { + char ch = (char)c->data[c->pos++]; + if (ch == '\0') + break; + c->string_buf[actual_len++] = ch; + } + c->string_buf[actual_len] = '\0'; + return c->string_buf; +} + +FUZZ_UNUSED static size_t +fuzz_consume_bytes(struct fuzz_consumer *c, void *out, size_t len) +{ + size_t avail = c->size - c->pos; + size_t to_copy = (avail < len) ? avail : len; + if (to_copy > 0) { + memcpy(out, c->data + c->pos, to_copy); + c->pos += to_copy; + } + return to_copy; +} + +#endif /* TEST_FUZZ_CONSUMER_H */ diff --git a/libarchive/test/test_open_filename.c b/libarchive/test/test_open_filename.c index 09a83690be0d..41e0ff0ee3df 100644 --- a/libarchive/test/test_open_filename.c +++ b/libarchive/test/test_open_filename.c @@ -24,6 +24,8 @@ */ #include "test.h" +#include <locale.h> + static void test_open_filename_mbs(void) { @@ -197,3 +199,24 @@ DEFINE_TEST(test_open_filename) test_open_filename_mbs(); test_open_filename_wcs(); } + +DEFINE_TEST(test_open_filename_wcs_oob) +{ + struct archive *a; + + /* Continue even if not available for best test coverage. */ + setlocale(LC_ALL, "en_US.UTF-8"); + + /* + * Try to open file with filename which might use more bytes in + * MBS representation than in wchar_t if platform uses 16 bit wchar_t, + * e.g. Cygwin (3 times a Euro sign, i.e. 3*2+2=8 vs 3*3+1=10 bytes). + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_FATAL, + archive_read_open_filename_w(a, L"\u20AC\u20AC\u20AC", 512)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_pax_xattr_header.c b/libarchive/test/test_pax_xattr_header.c index 8af81079ea7e..ce002b3171bf 100644 --- a/libarchive/test/test_pax_xattr_header.c +++ b/libarchive/test/test_pax_xattr_header.c @@ -67,7 +67,7 @@ DEFINE_TEST(test_pax_xattr_header) assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assertEqualFile("test1.tar","test_pax_xattr_header_all.tar"); @@ -86,7 +86,7 @@ DEFINE_TEST(test_pax_xattr_header) assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assertEqualFile("test2.tar","test_pax_xattr_header_schily.tar"); @@ -105,7 +105,7 @@ DEFINE_TEST(test_pax_xattr_header) assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assertEqualFile("test3.tar","test_pax_xattr_header_libarchive.tar"); @@ -123,7 +123,7 @@ DEFINE_TEST(test_pax_xattr_header) assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assertEqualFile("test4.tar","test_pax_xattr_header_all.tar"); } diff --git a/libarchive/test/test_read_disk_directory_traversals.c b/libarchive/test/test_read_disk_directory_traversals.c index 7597f4b6f6eb..718818c36b53 100644 --- a/libarchive/test/test_read_disk_directory_traversals.c +++ b/libarchive/test/test_read_disk_directory_traversals.c @@ -230,7 +230,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test that call archive_read_disk_open_w, wchar_t version. @@ -358,7 +358,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test that call archive_read_disk_open with a regular file. @@ -381,7 +381,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); #if defined(_WIN32) && !defined(__CYGWIN__) @@ -427,7 +427,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test for a full-path beginning with "//?/" @@ -458,7 +458,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); free(fullpath); /* @@ -515,7 +515,7 @@ test_basic(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); free(fullpath); #endif @@ -658,7 +658,7 @@ test_symlink_hybrid(void) /* There is no entry. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Specified file is a directory and it has symbolic files. @@ -722,7 +722,7 @@ test_symlink_hybrid(void) /* There is no entry. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* Destroy the disk object. */ assertEqualInt(ARCHIVE_OK, archive_read_free(a)); archive_entry_free(ae); @@ -827,7 +827,7 @@ test_symlink_logical(void) /* There is no entry. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Specified file is a directory and it has symbolic files. @@ -953,7 +953,7 @@ test_symlink_logical(void) /* There is no entry. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* Destroy the disk object. */ assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1131,7 +1131,7 @@ test_restore_atime(void) assertFileAtime("at/fe", 886611, 0); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test2: Traversals with archive_read_disk_set_atime_restored(). @@ -1197,7 +1197,7 @@ test_restore_atime(void) assertFileAtime("at/fe", 886611, 0); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test3: Traversals with archive_read_disk_set_atime_restored() but @@ -1254,7 +1254,7 @@ test_restore_atime(void) } /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test4: Traversals with ARCHIVE_READDISK_RESTORE_ATIME and @@ -1406,7 +1406,7 @@ test_callbacks(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* Reset name filter */ assertEqualIntA(a, ARCHIVE_OK, @@ -1539,7 +1539,7 @@ test_nodump(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test2: Traversals with ARCHIVE_READDISK_HONOR_NODUMP @@ -1671,7 +1671,7 @@ test_parent(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertChdir("../.."); @@ -1720,7 +1720,7 @@ test_parent(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test3: Traverse lock/dir1/. @@ -1767,7 +1767,7 @@ test_parent(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); /* * Test4: Traverse lock/lock2/dir1 from inside lock. @@ -1842,7 +1842,7 @@ test_parent(void) archive_read_next_header2(a, ae)); /* Close the disk object. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); } assertChdir(".."); diff --git a/libarchive/test/test_read_files_compressed.c b/libarchive/test/test_read_files_compressed.c new file mode 100644 index 000000000000..4795d750baa3 --- /dev/null +++ b/libarchive/test/test_read_files_compressed.c @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_read_files_compressed) +{ + const char *reffiles[] = + { + "test_read_files_compressed.part01", + "test_read_files_compressed.part02", + NULL + }; + + struct archive *a; + struct archive_entry *entry = NULL; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_all(a)); + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &entry)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_files_compressed.part01.uu b/libarchive/test/test_read_files_compressed.part01.uu new file mode 100644 index 000000000000..346545a0dc8d --- /dev/null +++ b/libarchive/test/test_read_files_compressed.part01.uu @@ -0,0 +1,4 @@ +begin 644 test_read_files_compressed.part01 +"'YT` +` +end diff --git a/libarchive/test/test_read_files_compressed.part02.uu b/libarchive/test/test_read_files_compressed.part02.uu new file mode 100644 index 000000000000..41e440391ae8 --- /dev/null +++ b/libarchive/test/test_read_files_compressed.part02.uu @@ -0,0 +1,4 @@ +begin 644 test_read_files_compressed.part02 +!```` +` +end diff --git a/libarchive/test/test_read_filter_compress.c b/libarchive/test/test_read_filter_compress.c index 03a1d5fbe9c0..d03fdc9d6344 100644 --- a/libarchive/test/test_read_filter_compress.c +++ b/libarchive/test/test_read_filter_compress.c @@ -35,7 +35,7 @@ DEFINE_TEST(test_read_filter_compress_truncated) assertEqualIntA(a, ARCHIVE_FATAL, archive_read_open_memory(a, data, sizeof(data))); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -59,7 +59,7 @@ DEFINE_TEST(test_read_filter_compress_empty2) assertEqualString(archive_filter_name(a, 0), "compress (.Z)"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_EMPTY); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -75,6 +75,6 @@ DEFINE_TEST(test_read_filter_compress_invalid) assertEqualIntA(a, ARCHIVE_FATAL, archive_read_open_memory(a, data, sizeof(data))); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_filter_grzip.c b/libarchive/test/test_read_filter_grzip.c index 43bd5bca2658..7e58a621007f 100644 --- a/libarchive/test/test_read_filter_grzip.c +++ b/libarchive/test/test_read_filter_grzip.c @@ -62,6 +62,6 @@ DEFINE_TEST(test_read_filter_grzip) assertEqualString(archive_filter_name(a, 0), "grzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_filter_gzip_recursive.c b/libarchive/test/test_read_filter_gzip_recursive.c index 51b614b6c023..56889820e666 100644 --- a/libarchive/test/test_read_filter_gzip_recursive.c +++ b/libarchive/test/test_read_filter_gzip_recursive.c @@ -45,6 +45,6 @@ DEFINE_TEST(test_read_filter_gzip_recursive) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_GZIP); assertEqualString(archive_filter_name(a, 0), "gzip"); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_filter_lrzip.c b/libarchive/test/test_read_filter_lrzip.c index 47388da0fb89..5caeb0fe5781 100644 --- a/libarchive/test/test_read_filter_lrzip.c +++ b/libarchive/test/test_read_filter_lrzip.c @@ -62,6 +62,6 @@ DEFINE_TEST(test_read_filter_lrzip) assertEqualString(archive_filter_name(a, 0), "lrzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_filter_lz4_raw.c b/libarchive/test/test_read_filter_lz4_raw.c new file mode 100644 index 000000000000..9cbb561e570d --- /dev/null +++ b/libarchive/test/test_read_filter_lz4_raw.c @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_read_filter_lz4_raw_skip) +{ + struct archive *a; + + const char *name = "test_read_filter_lz4_raw_skip"; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_FATAL, + archive_read_open_filename(a, name, 200)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_filter_lz4_raw_skip.uu b/libarchive/test/test_read_filter_lz4_raw_skip.uu new file mode 100644 index 000000000000..aaff306b80bf --- /dev/null +++ b/libarchive/test/test_read_filter_lz4_raw_skip.uu @@ -0,0 +1,4 @@ +begin 644 test_read_filter_lz4_raw_skip.uu +<!")-&&1`IP$``(`*`````%+3R8%0*DT8_/___P`` +` +end diff --git a/libarchive/test/test_read_filter_lzop.c b/libarchive/test/test_read_filter_lzop.c index acce6a4c2052..1d4d4f9352a5 100644 --- a/libarchive/test/test_read_filter_lzop.c +++ b/libarchive/test/test_read_filter_lzop.c @@ -72,6 +72,6 @@ DEFINE_TEST(test_read_filter_lzop) assertEqualString(archive_filter_name(a, 0), "lzop"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_filter_lzop_multiple_parts.c b/libarchive/test/test_read_filter_lzop_multiple_parts.c index 82eaf3539473..677f729a7133 100644 --- a/libarchive/test/test_read_filter_lzop_multiple_parts.c +++ b/libarchive/test/test_read_filter_lzop_multiple_parts.c @@ -71,6 +71,6 @@ DEFINE_TEST(test_read_filter_lzop_multiple_parts) assertEqualString(archive_filter_name(a, 0), "lzop"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_filter_uudecode_raw.c b/libarchive/test/test_read_filter_uudecode_raw.c index 6f02dc5de147..99f5b43f60cb 100644 --- a/libarchive/test/test_read_filter_uudecode_raw.c +++ b/libarchive/test/test_read_filter_uudecode_raw.c @@ -41,7 +41,7 @@ DEFINE_TEST(test_read_filter_uudecode_raw) assertEqualInt((AE_IFREG | 0755), archive_entry_mode(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -62,6 +62,6 @@ DEFINE_TEST(test_read_filter_uudecode_base64_raw) assertEqualInt((AE_IFREG | 0600), archive_entry_mode(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_filter_zstd_raw.c b/libarchive/test/test_read_filter_zstd_raw.c new file mode 100644 index 000000000000..5a4ea91c6e1f --- /dev/null +++ b/libarchive/test/test_read_filter_zstd_raw.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_read_filter_zstd_raw_loop) +{ + struct archive *a; + + const char *name = "test_read_filter_zstd_raw_loop"; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_raw(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, name, 200)); + + /* Verify that the filter detection did NOT work. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); + assertEqualString(archive_filter_name(a, 0), "none"); + + assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_filter_zstd_raw_loop.uu b/libarchive/test/test_read_filter_zstd_raw_loop.uu new file mode 100644 index 000000000000..932715669aa7 --- /dev/null +++ b/libarchive/test/test_read_filter_zstd_raw_loop.uu @@ -0,0 +1,4 @@ +begin 644 test_read_filter_zstd_raw_loop +,4"I-&/C___\HM2_] +` +end diff --git a/libarchive/test/test_read_format_7zip.c b/libarchive/test/test_read_format_7zip.c index 6d71f80d12ed..6f5ae3671a8c 100644 --- a/libarchive/test/test_read_format_7zip.c +++ b/libarchive/test/test_read_format_7zip.c @@ -82,7 +82,7 @@ test_copy(int use_open_fd) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); if (fd != -1) close(fd); @@ -115,7 +115,7 @@ test_empty_archive(void) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -156,7 +156,7 @@ test_empty_file(void) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -199,7 +199,7 @@ test_plain_header(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -284,7 +284,7 @@ test_extract_all_files(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -369,7 +369,7 @@ test_extract_all_files_zstd(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -419,7 +419,7 @@ test_extract_file_zstd_bcj_nobjc(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -498,7 +498,7 @@ test_extract_last_file(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -629,7 +629,7 @@ test_extract_all_files2(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -685,7 +685,7 @@ test_delta_lzma(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -741,7 +741,7 @@ test_bcj(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -798,7 +798,7 @@ test_ppmd(void) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -847,7 +847,7 @@ test_symname(void) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1081,7 +1081,7 @@ test_arm_filter(const char *refname) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1155,7 +1155,7 @@ test_arm64_filter(const char *refname) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1404,7 +1404,7 @@ DEFINE_TEST(test_read_format_7zip_sfx_elf64trunc) assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); assertEqualInt(0, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1476,8 +1476,8 @@ test_riscv_filter(const char *refname) assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt((AE_IFREG | 0775), archive_entry_mode(ae)); assertEqualString("hw-riscv64", archive_entry_pathname(ae)); - assertEqualInt(sizeof(buff), archive_entry_size(ae)); - assertEqualInt(sizeof(buff), archive_read_data(a, buff, sizeof(buff))); + assertEqualIntA(a, sizeof(buff), archive_entry_size(ae)); + assertEqualIntA(a, sizeof(buff), archive_read_data(a, buff, sizeof(buff))); computed_crc = bitcrc32(computed_crc, buff, sizeof(buff)); assertEqualInt(computed_crc, expected_crc); @@ -1486,7 +1486,7 @@ test_riscv_filter(const char *refname) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } #endif @@ -1500,9 +1500,12 @@ DEFINE_TEST(test_read_format_7zip_lzma2_riscv) if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { skipping("7zip:lzma decoding is not supported on this platform"); + } else if (!lzma_filter_decoder_is_supported(LZMA_FILTER_RISCV)) { + skipping("liblzma does not support RISC-V BCJ filter at runtime"); } else { test_riscv_filter("test_read_format_7zip_lzma2_riscv.7z"); } + archive_read_free(a); #else skipping("This version of liblzma does not support LZMA_FILTER_RISCV"); #endif @@ -1543,7 +1546,7 @@ test_sparc_filter(const char *refname) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); @@ -1616,7 +1619,7 @@ test_powerpc_filter(const char *refname) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); diff --git a/libarchive/test/test_read_format_7zip_encryption_data.c b/libarchive/test/test_read_format_7zip_encryption_data.c index 653044a46317..c8c8ff06b153 100644 --- a/libarchive/test/test_read_format_7zip_encryption_data.c +++ b/libarchive/test/test_read_format_7zip_encryption_data.c @@ -51,7 +51,7 @@ DEFINE_TEST(test_read_format_7zip_encryption_data) assertEqualInt(1, archive_entry_is_data_encrypted(ae)); assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); assertEqualInt(1, archive_file_count(a)); @@ -63,7 +63,7 @@ DEFINE_TEST(test_read_format_7zip_encryption_data) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_7zip_encryption_header.c b/libarchive/test/test_read_format_7zip_encryption_header.c index d0c48044ea5e..409c11e1aae0 100644 --- a/libarchive/test/test_read_format_7zip_encryption_header.c +++ b/libarchive/test/test_read_format_7zip_encryption_header.c @@ -65,7 +65,7 @@ DEFINE_TEST(test_read_format_7zip_encryption_header) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_7zip_encryption_partially.c b/libarchive/test/test_read_format_7zip_encryption_partially.c index 51a6c06116d7..ac168a35343b 100644 --- a/libarchive/test/test_read_format_7zip_encryption_partially.c +++ b/libarchive/test/test_read_format_7zip_encryption_partially.c @@ -63,12 +63,12 @@ DEFINE_TEST(test_read_format_7zip_encryption_partially) assertEqualInt(1, archive_entry_is_data_encrypted(ae)); assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); assertEqualInt(2, archive_file_count(a)); /* End of archive. */ - assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); } /* Verify archive format. */ @@ -76,6 +76,6 @@ DEFINE_TEST(test_read_format_7zip_encryption_partially) assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_7zip_entries_oom.7z.uu b/libarchive/test/test_read_format_7zip_entries_oom.7z.uu new file mode 100644 index 000000000000..3339d0367c31 --- /dev/null +++ b/libarchive/test/test_read_format_7zip_entries_oom.7z.uu @@ -0,0 +1,8 @@ +begin 644 test_read_format_7zip_entries_oom.7z +M-WJ\KR<<``,%;\HA```````````N`````````,Z^!W,!!>'AX>'AX>'AX>'A +MX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'A +MX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'AX>'A +MX>'AX>'AX>'AX0$.`8`/`8`1#0!E`&T`<`!T`'D````4"@$`@-9``*BRG0$5 +)!@$`(("D@0`` +` +end diff --git a/libarchive/test/test_read_format_7zip_entries_oom.c b/libarchive/test/test_read_format_7zip_entries_oom.c new file mode 100644 index 000000000000..8c7a77992469 --- /dev/null +++ b/libarchive/test/test_read_format_7zip_entries_oom.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * A 7z archive whose FilesInfo section declares far more files than the + * remaining header bytes can structurally support previously caused + * libarchive to attempt a ~2.5 GiB calloc(). The fix rejects the file + * count before allocating: empty-file entries require a kEmptyStream + * bitmap of ceil(numFiles/8) bytes, so numFiles beyond the known stream + * count cannot exceed 8 * header_bytes_remaining. + */ +DEFINE_TEST(test_read_format_7zip_entries_oom) +{ + const char *refname = "test_read_format_7zip_entries_oom.7z"; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* + * Header parsing must fail gracefully rather than attempting a + * multi-gigabyte allocation for the entry array. + */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_7zip_issue2765.c b/libarchive/test/test_read_format_7zip_issue2765.c index 7c45c313b315..3232a87ef9f2 100644 --- a/libarchive/test/test_read_format_7zip_issue2765.c +++ b/libarchive/test/test_read_format_7zip_issue2765.c @@ -46,6 +46,6 @@ DEFINE_TEST(test_read_format_7zip_issue2765) assertEqualInt(0, archive_file_count(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_7zip_malformed.c b/libarchive/test/test_read_format_7zip_malformed.c index bd3452c00aad..22c258fd03c7 100644 --- a/libarchive/test/test_read_format_7zip_malformed.c +++ b/libarchive/test/test_read_format_7zip_malformed.c @@ -39,7 +39,7 @@ test_malformed1(void) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } static void @@ -56,7 +56,7 @@ test_malformed2(void) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -72,7 +72,42 @@ test_malformed3(void) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_FATAL, archive_read_open_filename(a, refname, 10240)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + + +static void +test_malformed4(void) +{ + const char *refname = "test_read_format_7zip_malformed4.7z"; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +static void +test_malformed_numfiles_oom(void) +{ + const char *refname = "test_read_format_7zip_malformed_numfiles_oom.7z"; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_7zip_malformed) @@ -80,4 +115,6 @@ DEFINE_TEST(test_read_format_7zip_malformed) test_malformed1(); test_malformed2(); test_malformed3(); + test_malformed4(); + test_malformed_numfiles_oom(); } diff --git a/libarchive/test/test_read_format_7zip_malformed4.7z.uu b/libarchive/test/test_read_format_7zip_malformed4.7z.uu new file mode 100644 index 000000000000..45597aa13ac4 --- /dev/null +++ b/libarchive/test/test_read_format_7zip_malformed4.7z.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_7zip_malformed4.7z +M-WJ\KR<<``0N^]EU```````````9`````````&WKXL4!!`8``0D```<+`0`! +,`0`,```(#0(````` +` +end diff --git a/libarchive/test/test_read_format_7zip_malformed_numfiles_oom.7z.uu b/libarchive/test/test_read_format_7zip_malformed_numfiles_oom.7z.uu new file mode 100644 index 000000000000..bb1f75efa163 --- /dev/null +++ b/libarchive/test/test_read_format_7zip_malformed_numfiles_oom.7z.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_7zip_malformed_numfiles_oom.7z +M-WJ\KR<<``,%;\HA```````````N`````````,Z^!W,!!>,.`8`/`8`1#0!E +A`&T`<`!T`'D````4"@$`@-9``*BRG0$5!@$`(("D@0`` +` +end diff --git a/libarchive/test/test_read_format_7zip_packinfo_digests.c b/libarchive/test/test_read_format_7zip_packinfo_digests.c index e46a17b3b1da..75f90f2df899 100644 --- a/libarchive/test/test_read_format_7zip_packinfo_digests.c +++ b/libarchive/test/test_read_format_7zip_packinfo_digests.c @@ -82,7 +82,7 @@ DEFINE_TEST(test_read_format_7zip_packinfo_digests) archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); } assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_cab.c b/libarchive/test/test_read_format_cab.c index f5ce21cbf19b..0adf24c7c67f 100644 --- a/libarchive/test/test_read_format_cab.c +++ b/libarchive/test/test_read_format_cab.c @@ -266,7 +266,7 @@ verify(const char *refname, enum comp_type comp) /* Close the archive. */ finish: - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -332,7 +332,7 @@ verify2(const char *refname, enum comp_type comp) assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -387,7 +387,7 @@ verify3(const char *refname, enum comp_type comp) assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_cab_filename.c b/libarchive/test/test_read_format_cab_filename.c index efab3ccd69f1..8c0d17042896 100644 --- a/libarchive/test/test_read_format_cab_filename.c +++ b/libarchive/test/test_read_format_cab_filename.c @@ -79,7 +79,7 @@ test_read_format_cab_filename_CP932_eucJP(const char *refname) /* Close the archive. */ cleanup: - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -157,7 +157,7 @@ test_read_format_cab_filename_CP932_UTF8(const char *refname) /* Close the archive. */ cleanup: - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_cab_mszip_oob.c b/libarchive/test/test_read_format_cab_mszip_oob.c new file mode 100644 index 000000000000..da98a96b2f56 --- /dev/null +++ b/libarchive/test/test_read_format_cab_mszip_oob.c @@ -0,0 +1,93 @@ +#include "test.h" + +/* + * Regression test for OOB read/write in the CAB MSZIP decoder. + * + * A crafted CFDATA block carries a stored-block deflate header whose LEN + * field (0x9000) is larger than the actual compressed payload. Without the + * fix, the decoder reads one byte past the end of the input buffer on the + * second archive_read_next_header() call (after the first call returns + * ARCHIVE_FATAL due to the truncated payload). + */ +DEFINE_TEST(test_read_format_cab_mszip_oob) +{ + const uint16_t LEN = 0x9000; + const uint16_t NLEN = (uint16_t)~LEN; + const uint8_t first = 0xFF; + + /* + * cbData and cbUncomp are chosen so that the two-byte sequences they + * occupy inside the CFDATA header also form a valid deflate stored-block + * length / complement pair when the decoder's read pointer is positioned + * one field early. + */ + const uint16_t cbData = (LEN >> 8) | ((NLEN & 0xff) << 8); + const uint16_t cbUncomp = (NLEN >> 8) | ((uint16_t)first << 8); + + const size_t payload = (size_t)LEN - 1; /* one byte short of LEN */ + const size_t total = 36 + 8 + 18 + 8 + payload; + + uint8_t *b = (uint8_t *)calloc(1, total); + assert(b != NULL); + + /* CFHEADER (36 bytes) */ + memcpy(b, "MSCF", 4); + b[8] = (uint8_t)(total); + b[9] = (uint8_t)(total >> 8); + b[10] = (uint8_t)(total >> 16); + b[11] = (uint8_t)(total >> 24); + b[16] = 44; /* coffFiles: first CFFILE at offset 44 */ + b[24] = 3; b[25] = 1; /* version 1.3 */ + b[26] = 1; /* cFolders = 1 */ + b[28] = 1; /* cFiles = 1 */ + + /* CFFOLDER (8 bytes at offset 36) */ + b[36] = 62; /* coffCabStart: first CFDATA at offset 62 */ + b[40] = 1; /* cCFData = 1 */ + b[42] = 0x01; /* typeCompress = MSZIP */ + + /* CFFILE (18 bytes at offset 44) */ + b[44] = 0x00; b[45] = 0x01; /* cbFile = 0x100 */ + b[54] = 0x21; /* date low */ + b[58] = 0x20; /* attribs low */ + b[60] = 'a'; b[61] = 0; /* szName "a" */ + + /* CFDATA header (8 bytes at offset 62) */ + b[62] = 0x43; b[63] = 0x4B; /* checksum bytes (also MSZIP "CK" marker) */ + b[64] = 0x01; + b[65] = (uint8_t)(LEN & 0xff); + b[66] = (uint8_t)(cbData); + b[67] = (uint8_t)(cbData >> 8); + b[68] = (uint8_t)(cbUncomp); + b[69] = (uint8_t)(cbUncomp >> 8); + + /* Compressed payload: one byte short of what the stored-block LEN claims */ + memset(b + 70, first, payload); + + /* Open the crafted archive from memory */ + struct archive *a = archive_read_new(); + assert(a != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_cab(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, b, total)); + + struct archive_entry *ae; + char buf[4096]; + + /* The single CFFILE header is well-formed and should read cleanly. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("a", archive_entry_pathname(ae)); + + /* + * Reading data must fail: cbUncomp (0xFF6F) exceeds the decoder's + * uncompressed buffer (0x8000), so the bounds check returns FATAL + * rather than writing past the buffer end. + */ + assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buf, sizeof(buf))); + + /* The archive is in FATAL state and should remain that way. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(b); +} diff --git a/libarchive/test/test_read_format_cab_multi.c b/libarchive/test/test_read_format_cab_multi.c new file mode 100644 index 000000000000..f911f2187a9b --- /dev/null +++ b/libarchive/test/test_read_format_cab_multi.c @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_read_format_cab_multi) +{ + /* Reference to multi volume CAB files */ + const char *refname1 = "test_read_format_cab_multi.p1.cab"; + const char *refname2 = "test_read_format_cab_multi.p2.cab"; + struct archive *a; + struct archive_entry *ae; + + /* Extract the reference files into the test sandbox */ + extract_reference_file(refname1); + extract_reference_file(refname2); + + /* Initialize the archive reader for first part */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname1, 10)); + + /* Read entry */ + assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "ones"); + assertEqualInt(archive_entry_size(ae), 512); + + /* Clean up reader */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* Initialize the archive reader for second part */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname2, 10)); + + /* Read entry */ + assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "ones"); + assertEqualInt(archive_entry_size(ae), 512); + + /* Clean up reader */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +}
\ No newline at end of file diff --git a/libarchive/test/test_read_format_cab_multi.p1.cab.uu b/libarchive/test/test_read_format_cab_multi.p1.cab.uu new file mode 100644 index 000000000000..babd7a330dca --- /dev/null +++ b/libarchive/test/test_read_format_cab_multi.p1.cab.uu @@ -0,0 +1,15 @@ +begin 644 test_read_format_cab_multi.p1.cab +M35-#1@```````@```````$\``````````P$!``$``@"U`0``=&5S=%]R96%D +M7V9O<FUA=%]C86)?;75L=&DN<#(N8V%B``!D`````0`````"````````_O_0 +M7(6J(`!O;F5S`)4``0&4`0```0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +M`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +M`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +M`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +M`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +M`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +M`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +M`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +M`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +1`0$!`0$!`0$!`0$!`0$!`0$` +` +end diff --git a/libarchive/test/test_read_format_cab_multi.p2.cab.uu b/libarchive/test/test_read_format_cab_multi.p2.cab.uu new file mode 100644 index 000000000000..8361c3d68435 --- /dev/null +++ b/libarchive/test/test_read_format_cab_multi.p2.cab.uu @@ -0,0 +1,8 @@ +begin 644 test_read_format_cab_multi.p2.cab +M35-#1@````#8`````````$\``````````P$!``$``0"U`0$`=&5S=%]R96%D +M7V9O<FUA=%]C86)?;75L=&DN<#$N8V%B``!D`````0`````"````````_?_0 +M7(6J(`!O;F5S`&T!`0-L```"`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +M`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +D`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$!`0$! +` +end diff --git a/libarchive/test/test_read_format_cpio_afio.c b/libarchive/test/test_read_format_cpio_afio.c index 5d2b4b4c8134..a1fb683e38d4 100644 --- a/libarchive/test/test_read_format_cpio_afio.c +++ b/libarchive/test/test_read_format_cpio_afio.c @@ -102,7 +102,7 @@ DEFINE_TEST(test_read_format_cpio_afio) assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); assertA(archive_filter_code(a, 0) == ARCHIVE_FILTER_NONE); assertA(archive_format(a) == ARCHIVE_FORMAT_CPIO_AFIO_LARGE); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); @@ -125,3 +125,27 @@ DEFINE_TEST(test_read_format_cpio_afio_broken) assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_AFIO_LARGE); archive_read_free(a); } + +DEFINE_TEST(test_read_format_cpio_afio_header) +{ + const char *reffiles[] = + { + "test_read_format_cpio_afio_header.part1.cpio", + "test_read_format_cpio_afio_header.part2.cpio", + NULL + }; + struct archive_entry *ae; + struct archive *a; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_format_cpio(a)); + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + /* File "a" */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("a", archive_entry_pathname(ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_cpio_afio_header.part1.cpio.uu b/libarchive/test/test_read_format_cpio_afio_header.part1.cpio.uu new file mode 100644 index 000000000000..0d06cb299948 --- /dev/null +++ b/libarchive/test/test_read_format_cpio_afio_header.part1.cpio.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_cpio_afio_header.part1.cpio +M,#<P-S(W,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P;3`P,#`P,#`P,#`P,#`P +?,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,#`P,``` +` +end diff --git a/libarchive/test/test_read_format_cpio_afio_header.part2.cpio.uu b/libarchive/test/test_read_format_cpio_afio_header.part2.cpio.uu new file mode 100644 index 000000000000..0a3d59597641 --- /dev/null +++ b/libarchive/test/test_read_format_cpio_afio_header.part2.cpio.uu @@ -0,0 +1,4 @@ +begin 644 test_read_format_cpio_afio_header.part2.cpio +I,#`P,#`P,#`P;C`P,#$P,#`P,#`P,',P,#`P,#`P,#`P,#`P,#`P.F$` +` +end diff --git a/libarchive/test/test_read_format_cpio_bin_bz2.c b/libarchive/test/test_read_format_cpio_bin_bz2.c index b1a994bc5359..c34ed8b67a31 100644 --- a/libarchive/test/test_read_format_cpio_bin_bz2.c +++ b/libarchive/test/test_read_format_cpio_bin_bz2.c @@ -41,7 +41,7 @@ DEFINE_TEST(test_read_format_cpio_bin_bz2) r = archive_read_support_filter_bzip2(a); if (r != ARCHIVE_OK) { skipping("bzip2 support unavailable"); - archive_read_close(a); + archive_read_free(a); return; } assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); diff --git a/libarchive/test/test_read_format_cpio_bin_gz.c b/libarchive/test/test_read_format_cpio_bin_gz.c index 47545f913248..1372a7b5111c 100644 --- a/libarchive/test/test_read_format_cpio_bin_gz.c +++ b/libarchive/test/test_read_format_cpio_bin_gz.c @@ -55,7 +55,7 @@ DEFINE_TEST(test_read_format_cpio_bin_gz) assertEqualInt(archive_entry_is_encrypted(ae), 0); assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_BIN_LE); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_cpio_filename.c b/libarchive/test/test_read_format_cpio_filename.c index c5aa9a7f52a0..011fdf0027d3 100644 --- a/libarchive/test/test_read_format_cpio_filename.c +++ b/libarchive/test/test_read_format_cpio_filename.c @@ -76,11 +76,64 @@ DEFINE_TEST(test_read_format_cpio_filename_eucJP_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } +DEFINE_TEST(test_read_format_cpio_newc_large_pathname) +{ + const size_t namesize = 1024 * 1024 + 1; + const size_t name_pad = (2 - namesize) & 3; + char header[111]; + const size_t header_size = sizeof(header) - 1; + const size_t buffsize = header_size + namesize + name_pad; + char *buff; + struct archive *a; + struct archive_entry *ae; + int header_len; + + assert((buff = calloc(1, buffsize)) != NULL); + if (buff == NULL) + return; + + header_len = snprintf(header, sizeof(header), + "070701" /* magic */ + "%08x" /* c_ino */ + "%08x" /* c_mode */ + "%08x" /* c_uid */ + "%08x" /* c_gid */ + "%08x" /* c_nlink */ + "%08x" /* c_mtime */ + "%08x" /* c_filesize */ + "%08x" /* c_devmajor */ + "%08x" /* c_devminor */ + "%08x" /* c_rdevmajor */ + "%08x" /* c_rdevminor */ + "%08x" /* c_namesize */ + "%08x", /* c_check */ + 1, 0100644, 0, 0, 1, 0, 0, 0, 0, 0, 0, + (unsigned int)namesize, 0); + assertEqualInt((int)header_size, header_len); + + memcpy(buff, header, header_size); + memset(buff + header_size, 'a', namesize); + buff[header_size + namesize - 1] = '\0'; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, buffsize)); + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + assertEqualInt(ENOMEM, archive_errno(a)); + assertEqualString("Rejecting malformed cpio archive: " + "pathname exceeds 1 megabyte", archive_error_string(a)); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(buff); +} + DEFINE_TEST(test_read_format_cpio_filename_UTF8_eucJP) { const char *refname = "test_read_format_cpio_filename_utf8_jp.cpio"; @@ -129,7 +182,7 @@ DEFINE_TEST(test_read_format_cpio_filename_UTF8_eucJP) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -182,7 +235,7 @@ DEFINE_TEST(test_read_format_cpio_filename_UTF8_UTF8_jp) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); #endif } @@ -235,7 +288,7 @@ DEFINE_TEST(test_read_format_cpio_filename_CP866_KOI8R) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -287,7 +340,7 @@ DEFINE_TEST(test_read_format_cpio_filename_CP866_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -340,7 +393,7 @@ DEFINE_TEST(test_read_format_cpio_filename_KOI8R_CP866) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -392,7 +445,7 @@ DEFINE_TEST(test_read_format_cpio_filename_KOI8R_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -445,7 +498,7 @@ DEFINE_TEST(test_read_format_cpio_filename_UTF8_KOI8R) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -498,7 +551,7 @@ DEFINE_TEST(test_read_format_cpio_filename_UTF8_CP866) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -550,7 +603,7 @@ DEFINE_TEST(test_read_format_cpio_filename_UTF8_UTF8_ru) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); #endif } @@ -601,7 +654,7 @@ DEFINE_TEST(test_read_format_cpio_filename_eucJP_CP932) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -653,7 +706,7 @@ DEFINE_TEST(test_read_format_cpio_filename_UTF8_CP932) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -706,7 +759,7 @@ DEFINE_TEST(test_read_format_cpio_filename_CP866_CP1251) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -759,7 +812,7 @@ DEFINE_TEST(test_read_format_cpio_filename_CP866_CP1251_win) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -811,7 +864,7 @@ DEFINE_TEST(test_read_format_cpio_filename_KOI8R_CP1251) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -864,8 +917,7 @@ DEFINE_TEST(test_read_format_cpio_filename_UTF8_CP1251) assertEqualIntA(a, ARCHIVE_FORMAT_CPIO_POSIX, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } - diff --git a/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c b/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c index cff64d72c1ed..1c421df1e329 100644 --- a/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c +++ b/libarchive/test/test_read_format_cpio_svr4_bzip2_rpm.c @@ -123,7 +123,7 @@ DEFINE_TEST(test_read_format_cpio_svr4_bzip2_rpm) assertEqualString(archive_filter_name(a, 0), "bzip2"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_NOCRC); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_cpio_svr4_gzip.c b/libarchive/test/test_read_format_cpio_svr4_gzip.c index ae201de00f68..7fa22611e5e9 100644 --- a/libarchive/test/test_read_format_cpio_svr4_gzip.c +++ b/libarchive/test/test_read_format_cpio_svr4_gzip.c @@ -55,7 +55,7 @@ DEFINE_TEST(test_read_format_cpio_svr4_gzip) ARCHIVE_FORMAT_CPIO_SVR4_NOCRC); assertEqualInt(archive_entry_is_encrypted(ae), 0); assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c b/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c index 345760c1014f..6062c48cd127 100644 --- a/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c +++ b/libarchive/test/test_read_format_cpio_svr4_gzip_rpm.c @@ -123,7 +123,7 @@ DEFINE_TEST(test_read_format_cpio_svr4_gzip_rpm) assertEqualString(archive_filter_name(a, 0), "gzip"); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_SVR4_NOCRC); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_gtar_filename.c b/libarchive/test/test_read_format_gtar_filename.c index cf9c30991b28..75cc2b6af237 100644 --- a/libarchive/test/test_read_format_gtar_filename.c +++ b/libarchive/test/test_read_format_gtar_filename.c @@ -74,7 +74,7 @@ DEFINE_TEST(test_read_format_gtar_filename_eucJP_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -127,7 +127,7 @@ DEFINE_TEST(test_read_format_gtar_filename_CP866_KOI8R) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -179,7 +179,7 @@ DEFINE_TEST(test_read_format_gtar_filename_CP866_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -232,7 +232,7 @@ DEFINE_TEST(test_read_format_gtar_filename_KOI8R_CP866) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -284,7 +284,7 @@ DEFINE_TEST(test_read_format_gtar_filename_KOI8R_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -335,7 +335,7 @@ DEFINE_TEST(test_read_format_gtar_filename_eucJP_CP932) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -388,7 +388,7 @@ DEFINE_TEST(test_read_format_gtar_filename_CP866_CP1251) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -441,7 +441,7 @@ DEFINE_TEST(test_read_format_gtar_filename_CP866_CP1251_win) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -493,7 +493,7 @@ DEFINE_TEST(test_read_format_gtar_filename_KOI8R_CP1251) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_gtar_gz.c b/libarchive/test/test_read_format_gtar_gz.c index bc712b9e6e44..8d99e493b0ca 100644 --- a/libarchive/test/test_read_format_gtar_gz.c +++ b/libarchive/test/test_read_format_gtar_gz.c @@ -55,7 +55,7 @@ DEFINE_TEST(test_read_format_gtar_gz) assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); assertEqualInt(archive_entry_is_encrypted(ae), 0); assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_gtar_redundant_L.c b/libarchive/test/test_read_format_gtar_redundant_L.c index 167445c074f3..24bdead35230 100644 --- a/libarchive/test/test_read_format_gtar_redundant_L.c +++ b/libarchive/test/test_read_format_gtar_redundant_L.c @@ -35,6 +35,6 @@ DEFINE_TEST(test_read_format_gtar_redundant_L) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_GNUTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_gtar_sparse_skip_entry.c b/libarchive/test/test_read_format_gtar_sparse_skip_entry.c index 6b1d6556aa64..eaf015be2d37 100644 --- a/libarchive/test/test_read_format_gtar_sparse_skip_entry.c +++ b/libarchive/test/test_read_format_gtar_sparse_skip_entry.c @@ -74,7 +74,7 @@ DEFINE_TEST(test_read_format_gtar_sparse_skip_entry) archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); @@ -117,7 +117,7 @@ DEFINE_TEST(test_read_format_gtar_sparse_skip_entry) archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_huge_rpm.c b/libarchive/test/test_read_format_huge_rpm.c index 729c1e188d28..51208c7caea2 100644 --- a/libarchive/test/test_read_format_huge_rpm.c +++ b/libarchive/test/test_read_format_huge_rpm.c @@ -26,7 +26,6 @@ DEFINE_TEST(test_read_format_huge_rpm) { - struct archive_entry *ae; struct archive *a; const char *name = "test_read_format_huge_rpm.rpm"; @@ -34,17 +33,13 @@ DEFINE_TEST(test_read_format_huge_rpm) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); extract_reference_file(name); - assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2)); + /* This archive is truncated -- if it has data, the bid has screwed up */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_open_filename(a, name, 2)); + assertEqualStringA(a, "Truncated input file " + "(needed 34359738384 bytes, only 10256 available)", + archive_error_string(a)); - /* This archive should have no entries -- if it has entries, the bid has screwed up */ - assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - - /* Verify that the format detection worked. */ - assertEqualInt(ARCHIVE_FILTER_RPM, archive_filter_code(a, 0)); - assertEqualString("rpm", archive_filter_name(a, 0)); - assertEqualInt(ARCHIVE_FORMAT_EMPTY, archive_format(a)); - - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_iso_joliet_utf16be_overflow.c b/libarchive/test/test_read_format_iso_joliet_utf16be_overflow.c new file mode 100644 index 000000000000..6635fbefeef4 --- /dev/null +++ b/libarchive/test/test_read_format_iso_joliet_utf16be_overflow.c @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * A Joliet ISO with deeply nested directories whose UTF-16BE path + * exactly fills the 1024-byte buffer in build_pathname_utf16be(). + * The next recursive call then writes a 2-byte separator past the + * end of the allocation (heap-buffer-overflow). + * + * Under AddressSanitizer the unfixed code crashes at + * archive_read_support_format_iso9660.c:3496; with the fix the + * bounds check before the separator write causes + * archive_read_next_header() to return ARCHIVE_FATAL. + */ +DEFINE_TEST(test_read_format_iso_joliet_utf16be_overflow) +{ + const char *refname = "test_read_format_iso_joliet_utf16be_overflow.iso"; + struct archive *a; + struct archive_entry *ae; + int r; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Read through entries until the overflow path is reached. + * With the fix this returns ARCHIVE_FATAL ("Pathname is too long") + * instead of writing two bytes past the end of the path buffer. */ + while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) + archive_read_data_skip(a); + assertEqualInt(ARCHIVE_FATAL, r); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_iso_joliet_utf16be_overflow.iso.uu b/libarchive/test/test_read_format_iso_joliet_utf16be_overflow.iso.uu new file mode 100644 index 000000000000..92dd832bfe41 --- /dev/null +++ b/libarchive/test/test_read_format_iso_joliet_utf16be_overflow.iso.uu @@ -0,0 +1,1278 @@ +begin 644 test_read_format_iso_joliet_utf16be_overflow.iso +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````!0T0P,#$!`"`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("```````````!P` +M```````<```````````````````````````````````````````!```!`0`` +M`0`("``*````````"A,````````````````````B`!4````````5``@````` +M"`!\`0$``````@```0```0$`("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@ +M("`@("`@("`@("`P,#`P,#`P,#`P,#`P,#`P`#`P,#`P,#`P,#`P,#`P,#`` +M,#`P,#`P,#`P,#`P,#`P,``P,#`P,#`P,#`P,#`P,#`P``$````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````)#1#`P,0$````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````'````````!PE+T4````````````````` +M``````````````````````````````````@(````````````$P`````````` +M`````````"(`%````````!0`"``````(`'P!`0`````"```!```!`0`````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````0`````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````_T-$,#`Q`0`````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````"(`%````````!0`"``````(`'P!`0`````"```!```!`0`B +M`!0````````4``@`````"`!\`0$``````@```0```0$!\``6````````%@`( +M``````@`?`$!``````(```$```'.`$$`00!!`$$`00!!`$$`00!!`$$`00!! +M`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$` +M00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!! +M`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$` +M00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!!`$$`00!! +M`$$````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````````````(@`5````````%0`( +M``````@`?`$!``````(```$```$!`"(`%0```````!4`"``````(`'P!`0`` +M```"```!```!`0$````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````B`!8````````6``@`````"`!\`0$``````@```0```0$` +M(@`4````````%``(``````@`?`$!``````(```$```$!`?``%P```````!<` +M"``````(`'P!`0`````"```!```!S@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(` +M0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!" +M`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(` +M0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!" +M`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(`0@!"`$(` +M0@!"```````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````"(`%P```````!<` +M"``````(`'P!`0`````"```!```!`0`B`!8````````6``@`````"`!\`0$` +M`````@```0```0$!\``8````````&``(``````@`?`$!``````(```$```'. +M`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,` +M0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!# +M`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,` +M0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!# +M`$,`0P!#`$,`0P!#`$,`0P!#`$,`0P!#`$,````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````(@`8````````&``(``````@`?`$!``````(```$```$! +M`"(`%P```````!<`"``````(`'P!`0`````"```!```!`0'P`!D````````9 +M``@`````"`!\`0$``````@```0```<X`1`!$`$0`1`!$`$0`1`!$`$0`1`!$ +M`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0` +M1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$ +M`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0` +M1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$`$0`1`!$ +M`$0`1``````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````B`!D````````9 +M``@`````"`!\`0$``````@```0```0$`(@`8````````&``(``````@`?`$! +M``````(```$```$!`>(`&@```````!H`"``````(`'P!`0`````"```!```! +MP`!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!% +M`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4` +M10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!% +M`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4`10!%`$4` +M10!%`$4`10!%`$4`10`````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````"(`&@```````!H`"``````(`'P!`0`````"```!```! +M`0`B`!D````````9``@`````"`!\`0$``````@```0```0$!)``````````` +M````````````?`$!``````````$```$"`$8````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +.```````````````````` +` +end diff --git a/libarchive/test/test_read_format_iso_rockridge_ce_loop.iso.Z.uu b/libarchive/test/test_read_format_iso_rockridge_ce_loop.iso.Z.uu new file mode 100644 index 000000000000..20e08d3569fe --- /dev/null +++ b/libarchive/test/test_read_format_iso_rockridge_ce_loop.iso.Z.uu @@ -0,0 +1,61 @@ +begin 644 test_read_format_iso_rockridge_ce_loop.iso.Z +M'YV0``(*'$BPH,&#"!,J7,BPH<.'$"-*G$BQHL6+&#-JW,BQH\>/($.*'$FR +MI,F3*%.J7,FRI<N7,&/*G$FSILV;.'/JW,FSI\^?0(,*'4JTJ-&C2),J7<JT +MJ=.G4*-*G4JUJM6K6+-JW<JUJ]>O8,.*'4NVK-FS:-.J7<NVK=NW<./*G4NW +MKMV[>//JW<NWK]^_@`,+'DRXL.'#B!,K7LRXL>/'D"-+GDRYLN7+F#-KWLRY +ML^?/H$.+'DVZM.G3J%.K7LVZM>O7L&/+GDV[MNW;N'/KWLV[M^_?P(,+'TZ\ +MN/'CR),K7\Z\N?/GT*-+GTZ]NO7KV+-KW\Z]N_?OX,.+'T^^O/GSZ-.K7\^^ +MO?OW\./+GT^_OOW[^//KW\^_O_^_`0Q!!`PPQ!```$;(44890DQ!!`@01BCA +MA!1***`43S11X88<1GC0+06!Z-&!``1`XH$((`"`!059,$%"%0PD`@`7%%2C +MB@*I:$0``B10(@D"!'3B@1T6:>212":IY)),-NGDDU!&*>645%9I991-+)'$ +M%$\8,04(6SX!0@XVV`##"TAX"8(123!1Q!193$%%$1H*446;1!0A!0@F@'!A +M$4,\(<6#`K8@Q0M$6$&H%$4$086@(*`P1`H@Q)!##C.`4(0+63Q1A1-'$!&$ +MFY%.6NFE-X"@A`M0-"H%ETZ\L.H40R#1)A-)@'KEKKSN*@.!.<10H`PQR%## +MKV;"0,*O,`0[;+''PI`L"016:^VU!`+`K+/%0HLL@200V>NXY)9K[KGHIJON +MNNRVZ^Z2_\6[V#\"$FB@O/CFJ^^^_/9;799)@-#$&VZ`\,08=%0J@\(Z'*N# +MM"!LJX`,+A18<0QAV)"IH2"T4$<:9%3:\1D@1PR""RB_D,8<;_CK\LLPQRSS +MS&G=0L^!-0HIT```9"#0@40D(07-1!=M]-%()ZWTTDPW[?334+]&8D`UDLBS +M0#X'$/3047?M]==@ARWVV&27;?;9:"<-"8TV`H!C0#KRZ&,`0.I<XH%30'%` +M`+Z\`X`44A000"!08,%"`.T$,5`0[5P]T`!3_QPD00+D/-`%5!BA00`.[-CC +MCVTHP``#-!A`0NBCET["$$5P$(`&!<%N4#L%M>,&VP3=.%#<G],]^9`!`"XX +MX88CKKA`C#N^<^1"3CY0Y39FOGGG<H,N.NFFHXX]"0"0`\`&!6V@SP,#/:"/ +MYW-S;W<`"P3AOOO5NK!##,('D(@335QB8AC\]^___P`,H``'2,`"&O"`"$R@ +M`@G(.M=AH"`/-`@*"H("[W6@(!T87_G.5SVZ_4Q([7M?$.PE/_H%SG[XTU\` +M%LC"%KKPA3",(0`;&(`(#@0#7!N(%*)0D"AX[P,%^8`&!6(^]/WH@R4*H0C= +M5\+ZW2]_^Y.A%*=(Q2HFD(8V%`@&2%$04D"A(%#`0\\*XK.WN0U!':Q;B80T +M@*TY$7\(.!`9TB"'PATN<8MKA_,$(@#FE6B/`1&`SPB2`>EQSHAT0^3IKJ<Z +M`(`#`/#XAR0G"8^#*!*)`3@`G)H0@R:>L!'X2\"!YI"'-L3`CH@+Q4!"T0X_ +MFJ@@/"J(`"(Y24G"8PI,$(.)`K`%*_KREV'`(@3I41!Z=*$@77CD.VHI2;\9 +MY)+KTV06FD"Q^=4/E$T0)0!(V089H+(=JA0(*UWI2D`"0`#+9.8[<*E+$_42 +MF/"4HC`)@L/(!<\+!?'"(]W!S'^XPY)IQ*0TFS`#3PH.F]KDY@R^&<Z`C!.6 +MY90E/YGI#G;N\IWQS*@+YWE#6-@3%E\H2$C3%A'\,2"*_^.H%@\R08*@P)P" +M`!]!-F!(ZO6.!(K4GNKPMX`#`1"5I`C$0`)!"G+"$J87)$@':JK(G#+2=`#` +MGP)\ZC^@"E4@1#4J06)).2`2Y`-,3:-34V<Z7`Z!1#S0J`S#.@`?"6"19(7K +M]@"`2R*0J`=J7:OF#AF`MIY3KJK3:5G=1"(?Y%6OT]N17]\J6,!"E:20C:QD +M)YN0VPUR(&7<'1IO^CLA':A^Q+OC\0+".)A&E'*7Q5I8;]K8Q@+@=I83B.YR +MM-GT=?9NP3MA:(V71^4%!')'E65LJ;;:]+7VJ>JCK'*7R]SFBDU/K50`%0Z1 +MVR1`X0N6"I:CD%`$$&!H"$OP;A*(<(3NYFI.4JA5$$#572A@Z%&!8@((W/L$ +M*XSW32"80A6@``5!46%-D.KO%)*`A36UJ;MPDA.=\DNG]5(A"4/(FYN",(7N +M!LH)5`C"$/X;-%K-MPI"P-44N+LG(T`J;X!*`IN&X*@D/,$)^?54>C<%H0JW +M%\0B)C&8\H1A%2=!3V""L7N3T(0@2"$+(+#"$YA0A29T-T^TDH)U'U5B2%TX +MPQL.LHFE4.0'O]@%S@VSF,=,9OV@H0QL8,,;*E6#&2B@S'".LYSG3.<ZV_G. +M>,ZSGM]SYC2O.0;'>O.>!TWH0AOZT(A.M*(7S>A&>Z7/:F9S#`3MZ$I;^M*8 +MSK2F-\WI3GOZTZ`.M:A'3>I2F_K4J$ZUJE?-ZE:[^M6PCK6L9TWK6MOZUKC. +MM:YWS>M>^_K7P`ZVL(=-[&(;^]C(3K:RE\WL9CO[V=".MK2G3>UJ6_O:V,ZV +MMK?-[6Y[^]O@#K>XQTWN<IO[W.A.M[K7S>YVN_O=\(ZWO.=-[WK;^][XSK>^ +M]\WO?OO[WP`/N,`'3O""&_S@"$^XPA?.\(8[_.$0C[C$)T[QBEO\XAC/N,8W +MSO&.>_SC(`^YR$=.\I*;_.0H3[G*5\[REKO\Y3"/N<QG3O.:V_SF.,^YSG?. +M\Y[[_.=`#[K0AT[THAO]Z$A/NM*7SO2F._WI4(^ZU*=.]:I;_>I8S[K6M\[U +MKGO]ZV`/N]C'3O:RF_WL:$^[VM?.]K:[_>UPC[O<YT[WNMO][GC/N][WSO>^ +M^_WO@`^\X`=/^,(;_O"(3[SB%\_XQCO^\9"/O.0G3_G*6_[RF,^\YC?/^<Y[ +M_O.@#[WH1T_ZTIO^]*A/O>I7S_K6N_[UL(^][&=/^]K;_O:XS[WN=\_[WOO^ +M]\`/OO"'3_SB&__XR$^^\I?/_.8[__G0C[[TIT_]ZEO_^MC/OO:WS_WN>__[ +MX`^_^,=/_O*;__SH3[_ZU\_^]KO__?"/O_SG3__ZV__^^,^__O?/__[[__\` +M&(`".(`$6(`&>(`(F(`*N(`,V(`.^(`0&($2.($46($6>($8F($:N($<V($> +M^($@&((B.((D6((F>((HF((JN((LV((N^((P&(,R.(,T6(,V>(,XF(,ZN(,\ +MV(,^^(-`&(1".(1$6(1&>(1(F(1*N(1,V(1.^(10&(52.(546(56>(58F(5: +MN(5<V(5>^(5@&(9B.(9D6(9F>(9HF(9JN(9LV(9N^(9P&(=R.(=T6(=V>(=X +MF(=ZN(=\V(=^^(>`&(B".(B$6(B&>(B(F(B*N(B,V(B.^(B0&(F2.(F46(F6 +*>(F8F(F:N(D_`0`` +` +end diff --git a/libarchive/test/test_read_format_isorr_ce_loop.c b/libarchive/test/test_read_format_isorr_ce_loop.c new file mode 100644 index 000000000000..b1cdd6e82aa8 --- /dev/null +++ b/libarchive/test/test_read_format_isorr_ce_loop.c @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2026 Zhihan Zheng + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * A malformed Rock Ridge ISO whose first CE continuation area contains + * another CE entry that points back to the same area. The parser should + * reject this self-referential continuation chain with ARCHIVE_FATAL + * instead of looping while reading headers. + */ + +DEFINE_TEST(test_read_format_isorr_ce_loop) +{ + const char *refname = "test_read_format_iso_rockridge_ce_loop.iso.Z"; + struct archive *a; + struct archive_entry *ae; + int r; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); + + /* Read entries until the self-referential CE is reached. */ + while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) + archive_read_data_skip(a); + + /* The parser should reject the self-referential CE with ARCHIVE_FATAL. */ + assertEqualIntA(a, ARCHIVE_FATAL, r); + assert(archive_errno(a) != 0); + assert(archive_error_string(a) != NULL); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_lha.c b/libarchive/test/test_read_format_lha.c index 93e79183e5c3..b323cb3c86a5 100644 --- a/libarchive/test/test_read_format_lha.c +++ b/libarchive/test/test_read_format_lha.c @@ -266,7 +266,7 @@ verify(const char *refname, int posix) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_lha_bugfix_0.c b/libarchive/test/test_read_format_lha_bugfix_0.c index bbdcb81569b6..342dd1ef3c70 100644 --- a/libarchive/test/test_read_format_lha_bugfix_0.c +++ b/libarchive/test/test_read_format_lha_bugfix_0.c @@ -69,7 +69,7 @@ DEFINE_TEST(test_read_format_lha_bugfix_0) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_lha_filename.c b/libarchive/test/test_read_format_lha_filename.c index d726f6245d7d..22c303aa4b3e 100644 --- a/libarchive/test/test_read_format_lha_filename.c +++ b/libarchive/test/test_read_format_lha_filename.c @@ -85,7 +85,7 @@ test_read_format_lha_filename_CP932_eucJP(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -145,7 +145,7 @@ test_read_format_lha_filename_CP932_UTF8(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -195,7 +195,7 @@ test_read_format_lha_filename_CP932_Windows(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } #else diff --git a/libarchive/test/test_read_format_lha_filename_utf16.c b/libarchive/test/test_read_format_lha_filename_utf16.c index d0710799bba4..f700ec3c3ebb 100644 --- a/libarchive/test/test_read_format_lha_filename_utf16.c +++ b/libarchive/test/test_read_format_lha_filename_utf16.c @@ -127,7 +127,7 @@ test_read_format_lha_filename_UTF16_UTF8(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_LHA, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_mtree.c b/libarchive/test/test_read_format_mtree.c index b4463298dde2..e95bdabc3923 100644 --- a/libarchive/test/test_read_format_mtree.c +++ b/libarchive/test/test_read_format_mtree.c @@ -269,7 +269,7 @@ test_read_format_mtree1(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(30, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -299,7 +299,7 @@ test_read_format_mtree2(void) assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -348,7 +348,7 @@ test_read_format_mtree3(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(3, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); assertChdir(".."); @@ -418,7 +418,7 @@ DEFINE_TEST(test_read_format_mtree_filenames_only) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(6, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -477,7 +477,7 @@ DEFINE_TEST(test_read_format_mtree_nochange) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(3, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* @@ -518,7 +518,7 @@ DEFINE_TEST(test_read_format_mtree_nochange) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(3, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -620,7 +620,7 @@ DEFINE_TEST(test_read_format_mtree_nomagic_v1_form) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(12, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -687,7 +687,7 @@ DEFINE_TEST(test_read_format_mtree_nomagic_v2_form) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(6, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -754,7 +754,7 @@ DEFINE_TEST(test_read_format_mtree_nomagic_v2_netbsd_form) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(6, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -785,7 +785,7 @@ DEFINE_TEST(test_read_format_mtree_nonexistent_contents_file) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -811,7 +811,7 @@ DEFINE_TEST(test_read_format_mtree_noprint) assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); assertEqualString("Can't parse line 3", archive_error_string(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -840,6 +840,41 @@ DEFINE_TEST(test_read_format_mtree_tab) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualInt(1, archive_file_count(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_mtree_nano) +{ + static char archive[] = + "#mtree\n" + "a type=file time=1234567890.1000000000000 contents=nonexistent_file\n" + "b type=file time=1234567899.-1000000000000 contents=nonexistent_file\n"; + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, archive, sizeof(archive))); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "a"); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualIntA(a, archive_entry_mtime(ae), 1234567890); + assertEqualIntA(a, archive_entry_mtime_nsec(ae), 999999999); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString(archive_entry_pathname(ae), "b"); + assertEqualInt(archive_entry_filetype(ae), AE_IFREG); + assertEqualIntA(a, archive_entry_mtime(ae), 1234567899); + assertEqualIntA(a, archive_entry_mtime_nsec(ae), 0); + + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualInt(2, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_pax_bz2.c b/libarchive/test/test_read_format_pax_bz2.c index 4f11137b9c6f..1e3cb07919a8 100644 --- a/libarchive/test/test_read_format_pax_bz2.c +++ b/libarchive/test/test_read_format_pax_bz2.c @@ -48,8 +48,8 @@ DEFINE_TEST(test_read_format_pax_bz2) assert((a = archive_read_new()) != NULL); r = archive_read_support_filter_bzip2(a); if (r != ARCHIVE_OK) { - archive_read_close(a); skipping("Bzip2 unavailable"); + archive_read_free(a); return; } assertEqualIntA(a,ARCHIVE_OK, archive_read_support_format_all(a)); diff --git a/libarchive/test/test_read_format_rar.c b/libarchive/test/test_read_format_rar.c index 59e83846c863..f8e4b324fcb9 100644 --- a/libarchive/test/test_read_format_rar.c +++ b/libarchive/test/test_read_format_rar.c @@ -592,6 +592,42 @@ DEFINE_TEST(test_read_format_rar_multi_lzss_blocks) assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } +DEFINE_TEST(test_read_format_rar3_lowdist_reset) +{ + const char reffile[] = "test_read_format_rar3_lowdist_reset.rar"; + const unsigned char expected[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x0d, 0x0e, + 0x0f, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 + }; + unsigned char buff[sizeof(expected)]; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_rar(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("lowdist-reset.bin", archive_entry_pathname(ae)); + assertEqualInt(sizeof(expected), archive_entry_size(ae)); + assertEqualIntA(a, sizeof(expected), + archive_read_data(a, buff, sizeof(buff))); + assertEqualMem(buff, expected, sizeof(expected)); + + assertA(1 == archive_read_next_header(a, &ae)); + assertEqualInt(1, archive_file_count(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + DEFINE_TEST(test_read_format_rar_compress_best) { const char reffile[] = "test_read_format_rar_compress_best.rar"; @@ -3807,7 +3843,7 @@ DEFINE_TEST(test_read_format_rar_multivolume_uncompressed_files) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, 16, archive_file_count(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_rar_endarc_huge) @@ -3906,6 +3942,54 @@ DEFINE_TEST(test_read_format_rar_newsub_huge) #endif } +DEFINE_TEST(test_read_format_rar_newsub_rr_over_1m) +{ + const char* reffile = "test_read_format_rar_newsub_rr_over_1m.rar"; + struct archive_entry *ae; + struct archive *a; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_rar(a)); + assertA(0 == archive_read_open_filename(a, reffile, 10240)); + + failure("RAR NEWSUB RR records larger than 1 MiB should be skipped"); + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_format_rar_newsub_huge64) +{ + static const unsigned char archive[] = { + 'R', 'a', 'r', '!', 0x1a, 0x07, 0x00, + 0x23, 0x25, 0x7a, 0x00, 0x01, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00 + }; + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + assertA(0 == archive_read_support_format_rar(a)); + assertA(0 == archive_read_open_memory(a, archive, sizeof(archive))); + + failure("Malformed RAR NEWSUB header should be rejected if its " + "extended data is missing"); + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae)); + assertEqualString("Invalid RAR file: Cannot read extended header data", + archive_error_string(a)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + DEFINE_TEST(test_read_format_rar_symlink_huge) { #if SIZE_MAX == UINT64_MAX @@ -3929,3 +4013,24 @@ DEFINE_TEST(test_read_format_rar_symlink_huge) assertEqualInt(ARCHIVE_OK, archive_read_free(a)); #endif } + +DEFINE_TEST(test_read_format_rar_unbound_staticdata) +{ + const char* reffile = "test_read_format_rar_unbound_staticdata.rar"; + + struct archive_entry *ae; + struct archive *a; + char buf[64]; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, reffile, 1024)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_FAILED, archive_read_data(a, buf, 64)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_rar3_lowdist_reset.rar.uu b/libarchive/test/test_read_format_rar3_lowdist_reset.rar.uu new file mode 100644 index 000000000000..3bb7ed9cbfb9 --- /dev/null +++ b/libarchive/test/test_read_format_rar3_lowdist_reset.rar.uu @@ -0,0 +1,16 @@ +begin 644 test_read_format_rar3_lowdist_reset.rar +M4F%R(1H' ,^0<P #0 !J470 @#$ Z@$ $ #W#CX;P = +M-1$ ( &QO=V1I<W0M<F5S970N8FEN$1$1$1$1%55556(B(B(B(B(B(B(B +M(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B +M(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B +M(B(B(B(B9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F +M9F9F9555F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F1$1$1$1$1$541$5 +M555555555555555 $" P0%!@<("0H+# T.#Q 1$A,4%187&!D:&QP='A\@( +M2(C)"4F)_(<OD._U8!$1$1$1$155555B(B(B(B(B(B(B(B(B(B(B(B(B(B(B +M(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B +M(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(F9F9F9F +M9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F5559F9F9F9 +MF9F9F9F9F9F9F9F9F9F9F9F9F9F9F9D1$1$1$1$1%5$1%555555555555555 +:?(<!04E166%I<7F!B9&9H:FW5,0]>P! !P + +end diff --git a/libarchive/test/test_read_format_rar5.c b/libarchive/test/test_read_format_rar5.c index 6ab0d236a1ed..57d49ad2fb54 100644 --- a/libarchive/test/test_read_format_rar5.c +++ b/libarchive/test/test_read_format_rar5.c @@ -1452,7 +1452,7 @@ DEFINE_TEST(test_read_format_rar5_only_crypt_exfld) during data extraction. */ assertA(archive_read_next_header(a, &ae) == ARCHIVE_OK); - assertA(archive_read_data(a, buf, sizeof(buf)) == ARCHIVE_FATAL); + assertA(archive_read_data(a, buf, sizeof(buf)) == ARCHIVE_FAILED); /* The reader should also provide a valid error message. */ assertA(archive_error_string(a) != NULL); @@ -1494,3 +1494,81 @@ DEFINE_TEST(test_read_format_rar5_invalidhash_and_validhtime_exfld) EPILOGUE(); } + +/* + * Regression tests for the RAR5 base-block parser leaving unconsumed body + * bytes before returning ARCHIVE_RETRY (GHSA-9h2c-464f-j3hj). Each archive is + * the test_read_format_rar5_stored archive with extra, unread bytes appended + * to a no-data block's body. Before the fix the reader did not skip those + * bytes, so the stream misaligned and the following file entry was lost; with + * the fix the trailing bytes are skipped and helloworld.txt is read normally. + */ +DEFINE_TEST(test_read_format_rar5_main_block_extra_bytes) +{ + const char helloworld_txt[] = "hello libarchive test suite!\n"; + la_ssize_t file_size = sizeof(helloworld_txt) - 1; + char buff[64]; + + /* HEAD_MAIN block padded with trailing bytes the parser does not read. */ + PROLOGUE("test_read_format_rar5_main_block_extra_bytes.rar"); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("helloworld.txt", archive_entry_pathname(ae)); + assertEqualInt(file_size, archive_entry_size(ae)); + assertA(file_size == archive_read_data(a, buff, file_size)); + assertEqualMem(buff, helloworld_txt, file_size); + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_skip_block_extra_bytes) +{ + const char helloworld_txt[] = "hello libarchive test suite!\n"; + la_ssize_t file_size = sizeof(helloworld_txt) - 1; + char buff[64]; + + /* An unknown HFL_SKIP_IF_UNKNOWN block carrying trailing bytes is inserted + * before the file entry; the parser must skip the entire block. */ + PROLOGUE("test_read_format_rar5_skip_block_extra_bytes.rar"); + + assertA(0 == archive_read_next_header(a, &ae)); + assertEqualString("helloworld.txt", archive_entry_pathname(ae)); + assertEqualInt(file_size, archive_entry_size(ae)); + assertA(file_size == archive_read_data(a, buff, file_size)); + assertEqualMem(buff, helloworld_txt, file_size); + + assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae)); + + EPILOGUE(); +} + +DEFINE_TEST(test_read_format_rar5_bytes_remaining_underflow) +{ + /* GH #2986 — CWE-191 signed integer underflow on + * rar->file.bytes_remaining in process_block(). A malformed RAR5 + * archive whose compressed-block to_skip value exceeds the declared + * remaining file data drives bytes_remaining negative; the negative + * ssize_t later reaches read_ahead() and is implicitly converted to + * a near-SIZE_MAX malloc request (CWE-122). + * + * The patched reader must reject the malformed archive with + * ARCHIVE_FATAL before the negative value is reached. */ + + char buf[4096]; + la_ssize_t r; + PROLOGUE("test_read_format_rar5_bytes_remaining_underflow.rar"); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("poc.txt", archive_entry_pathname(ae)); + + do { + r = archive_read_data(a, buf, sizeof(buf)); + } while (r > 0); + + assertEqualIntA(a, ARCHIVE_FATAL, r); + assertA(archive_error_string(a) != NULL); + + EPILOGUE(); +} diff --git a/libarchive/test/test_read_format_rar5_bad_filter.c b/libarchive/test/test_read_format_rar5_bad_filter.c new file mode 100644 index 000000000000..6f24bc7436c0 --- /dev/null +++ b/libarchive/test/test_read_format_rar5_bad_filter.c @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 2025 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Two-entry RAR5 archive. Entry 1 ("bad.txt") is compressed with a filter + * of unsupported type 4 (FILTER_AUDIO). Entry 2 ("ok.txt") is stored. + * + * Tests that an unsupported filter type in do_uncompress_file returns + * ARCHIVE_FAILED (not ARCHIVE_FATAL), so the archive is not aborted and + * the second entry is still readable. + * + * RAR5 outer block format: 4-byte LE CRC32 of (vint(hdr_size)+hdr_body), + * then vint(hdr_size), then hdr_body, then optional data area. + * Integers are vint: 7 bits per byte, LSB first, high bit = more follows. + */ +DEFINE_TEST(test_read_format_rar5_bad_filter) +{ + static const uint8_t data[] = { + /* RAR5 signature */ + 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00, + + /* Main archive header block (type=1): + * CRC32, vint(body_size=3), type=1, block_flags=0, + * archive_flags=0 */ + 0xC5, 0x1A, 0x33, 0x32, 0x03, 0x01, 0x00, 0x00, + + /* File header block for "bad.txt" (type=2, HFL_DATA flag set): + * CRC32, vint(body_size=17), type=2, HFL_DATA, + * packed_size=23, file_flags=0, unpacked_size=4, + * file_attr=0, compression_info=512 (method=GOOD, + * version=0, window_factor=0), host_os=1, + * name_len=7, "bad.txt" */ + 0x88, 0xEC, 0xB0, 0x99, 0x11, 0x02, 0x02, 0x17, + 0x00, 0x04, 0x00, 0x80, 0x04, 0x01, 0x07, 0x62, + 0x61, 0x64, 0x2E, 0x74, 0x78, 0x74, + + /* Compressed data block for "bad.txt" (23 bytes): + * + * Compressed block header (3 bytes): + * block_flags=0xC2: is_table_present, is_last_block, + * bf_bit_size=2 (block ends when + * in_addr==last_byte && bit_addr>=3) + * checksum=0x8C, block_size=20 */ + 0xC2, 0x8C, 0x14, + + /* Huffman meta-table (20 nibbles packed in 10 bytes): + * nibble[2]=1, nibble[19]=1, all others 0. + * Two 1-bit meta-symbols: + * code 0 -> sym 2 (store bit-length 2 for next entry) + * code 1 -> sym 19 (fill N+11 zeros, N in next 7 bits) */ + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + + /* Huffman main table + compressed data (MSB-first bitstream): + * + * Main table (ld[], 430 entries, 42 bits total): + * skip 97 zeros (sym19, n=86), ld[97]=2 (sym2, 'a'), + * skip 138 zeros, skip 20 zeros, + * ld[256]=2 (sym2, filter token), skip 138+35 zeros. + * Canonical codes: 00->sym97('a'), 01->sym256(filter). + * + * Compressed data (33 bits): + * 01 filter token (sym 256) + * 00,00000000 block_start: count=0->1 byte, value=0 + * 00,00000100 block_length: count=0->1 byte, value=4 + * 100 filter_type=4 (FILTER_AUDIO, unsupported; + * top 3 bits of a 16-bit read, 3 bits consumed) + * 00,00,00,00 four 'a' literals (sym 97, code 00 each) */ + 0xD6, 0x7F, 0xC4, 0xBF, 0xE6, 0x10, 0x00, 0x04, + 0x80, 0x00, + + /* File header block for "ok.txt" (type=2, HFL_DATA flag set): + * CRC32, vint(body_size=15), type=2, HFL_DATA, + * packed_size=3, file_flags=0, unpacked_size=3, + * file_attr=0, compression_info=0 (STORE), + * host_os=1, name_len=6, "ok.txt", data "ok\n" */ + 0xB1, 0xC3, 0x30, 0x14, 0x0F, 0x02, 0x02, 0x03, + 0x00, 0x03, 0x00, 0x00, 0x01, 0x06, 0x6F, 0x6B, + 0x2E, 0x74, 0x78, 0x74, 0x6F, 0x6B, 0x0A, + + /* End of archive block (type=5): + * CRC32, vint(body_size=2), type=5, block_flags=0 */ + 0x39, 0xF9, 0xB2, 0x81, 0x02, 0x05, 0x00, + }; + + struct archive_entry *ae; + struct archive *a; + char buf[256]; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_rar5(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, data, sizeof(data))); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("bad.txt", archive_entry_pathname(ae)); + assertA(archive_read_data(a, buf, sizeof(buf)) < 0); + assertA(archive_error_string(a) != NULL && + strstr(archive_error_string(a), "Unsupported filter type") != NULL); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("ok.txt", archive_entry_pathname(ae)); + assertEqualIntA(a, 3, archive_read_data(a, buf, sizeof(buf))); + assertEqualMem(buf, "ok\n", 3); + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_rar5_bad_tables.c b/libarchive/test/test_read_format_rar5_bad_tables.c new file mode 100644 index 000000000000..cb64face6376 --- /dev/null +++ b/libarchive/test/test_read_format_rar5_bad_tables.c @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * The reference archive contains one compressed entry whose HUFF_BC + * meta-table has all 20 nibbles set to bit-length 1. This is an + * over-subscribed Huffman table (Kraft sum = 10 >> 1), which + * create_decode_tables() must reject. Reading the entry data must + * therefore fail, not succeed. + */ +DEFINE_TEST(test_read_format_rar5_bad_tables) +{ + const char *reffile = "test_read_format_rar5_bad_tables.rar"; + struct archive_entry *ae; + struct archive *a; + const void *buf; + size_t size; + la_int64_t offset; + + extract_reference_file(reffile); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, reffile, 10240)); + + /* The file header is valid; the bad data is in the compressed block. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* Reading must fail because the meta-table is over-subscribed. */ + assertEqualIntA(a, ARCHIVE_FAILED, + archive_read_data_block(a, &buf, &size, &offset)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_free(a)); +} diff --git a/libarchive/test/test_read_format_rar5_bad_tables.rar.uu b/libarchive/test/test_read_format_rar5_bad_tables.rar.uu new file mode 100644 index 000000000000..eca915f7533b --- /dev/null +++ b/libarchive/test/test_read_format_rar5_bad_tables.rar.uu @@ -0,0 +1,8 @@ +begin 644 test_read_format_rar5_bad_tables.rar +M4F%R(1H'`0#%&C,R`P$``(C&P1@9`@*$`0!``(`$`0YB861?=&%B;&5S+G1X +M=,@2@``1$1$1$1$1$1$1```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````````#GY +%LH$"!0`` +` +end diff --git a/libarchive/test/test_read_format_rar5_block_hdr_fail_loop.c b/libarchive/test/test_read_format_rar5_block_hdr_fail_loop.c new file mode 100644 index 000000000000..e447a2a8bcef --- /dev/null +++ b/libarchive/test/test_read_format_rar5_block_hdr_fail_loop.c @@ -0,0 +1,37 @@ +#include "test.h" + +/* + * Regression test for infinite loop when parse_block_header() returns + * ARCHIVE_FAILED inside do_uncompress_file()'s while(1) loop. + * + * The loop only exited on ARCHIVE_EOF or ARCHIVE_FATAL. After converting + * per-entry block header errors from ARCHIVE_FATAL to ARCHIVE_FAILED, a + * malformed block header caused the loop to spin forever. + * + * Fuzzer-generated reproducer (37 bytes). + */ +DEFINE_TEST(test_read_format_rar5_block_hdr_fail_loop) +{ + /* RAR5 archive with a malformed compressed block header */ + static const uint8_t data[] = { + 0x52,0x61,0x72,0x21,0x1a,0x07,0x01,0x00, + 0x86,0x7e,0xfa,0xe7,0x03,0x02,0x56,0x20, + 0x00,0x20,0x15,0xae,0x21,0x00,0x01,0x08, + 0x00,0x00,0x01,0x00,0x00,0x15,0x00,0xbe, + 0xc0,0x80,0x00,0xff,0xf4 + }; + + struct archive *a = archive_read_new(); + assert(a != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_rar5(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, + data, sizeof(data))); + + struct archive_entry *ae; + char buf[4096]; + while (archive_read_next_header(a, &ae) == ARCHIVE_OK) + while (archive_read_data(a, buf, sizeof(buf)) > 0) + ; + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_rar5_bytes_remaining_underflow.rar.uu b/libarchive/test/test_read_format_rar5_bytes_remaining_underflow.rar.uu new file mode 100644 index 000000000000..2ea589d33874 --- /dev/null +++ b/libarchive/test/test_read_format_rar5_bytes_remaining_underflow.rar.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_rar5_bytes_remaining_underflow.rar +M4F%R(1H' 0!3*C1% P$ =ANJWT1 A(! H @ $!!W!O8RYT>'1 '@0Y^;*! +# @4 + +end diff --git a/libarchive/test/test_read_format_rar5_main_block_extra_bytes.rar.uu b/libarchive/test/test_read_format_rar5_main_block_extra_bytes.rar.uu new file mode 100644 index 000000000000..81533e4fd6e5 --- /dev/null +++ b/libarchive/test/test_read_format_rar5_main_block_extra_bytes.rar.uu @@ -0,0 +1,6 @@ +begin 644 test_read_format_rar5_main_block_extra_bytes.rar +M4F%R(1H' 0 $ .>F$@$%!@ % 0& @ #@P!F,L @,+G0 $G0"D +M@P*T0Z"5@ !#FAE;&QO=V]R;&0N='AT"@,3?@ZK6U;I#AIH96QL;R!L:6)A +;<F-H:79E('1E<W0@<W5I=&4A"AUW5E$#!00 +` +end diff --git a/libarchive/test/test_read_format_rar5_skip_block_extra_bytes.rar.uu b/libarchive/test/test_read_format_rar5_skip_block_extra_bytes.rar.uu new file mode 100644 index 000000000000..1b60edd9988e --- /dev/null +++ b/libarchive/test/test_read_format_rar5_skip_block_extra_bytes.rar.uu @@ -0,0 +1,6 @@ +begin 644 test_read_format_rar5_skip_block_extra_bytes.rar +M4F%R(1H' 0 SDK7E"@$%!@ % 0& @ ",.6KS"A $ X, 9C+ (# +M"YT !)T I(,"M$.@E8 0YH96QL;W=O<FQD+G1X= H#$WX.JUM6Z0X::&5L +B;&\@;&EB87)C:&EV92!T97-T('-U:71E(0H==U91 P4$ +` +end diff --git a/libarchive/test/test_read_format_rar_encryption.c b/libarchive/test/test_read_format_rar_encryption.c index 2355468be809..ae2d6141d17f 100644 --- a/libarchive/test/test_read_format_rar_encryption.c +++ b/libarchive/test/test_read_format_rar_encryption.c @@ -47,7 +47,7 @@ static void test_encrypted_rar_archive(const char *filename, int filenamesEncryp /* We should only ever fail to read the data for "a.txt" and "c.txt" if they are encrypted */ /* NOTE: We'll never attempt this when filenames are encrypted, so we only check for solid here */ - expected_read_data_result = solid ? ARCHIVE_FATAL : expected_file_size; + expected_read_data_result = solid ? ARCHIVE_FAILED : expected_file_size; extract_reference_file(filename); assert((a = archive_read_new()) != NULL); @@ -81,7 +81,7 @@ static void test_encrypted_rar_archive(const char *filename, int filenamesEncryp assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); /* Additional attempts to read headers are futile */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); return; } @@ -96,7 +96,7 @@ static void test_encrypted_rar_archive(const char *filename, int filenamesEncryp assertEqualInt(1, archive_entry_is_data_encrypted(ae)); assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); assertEqualInt(1, archive_read_has_encrypted_entries(a)); - assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + assertEqualIntA(a, ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); /* Read the header for "c.txt" */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); @@ -120,13 +120,13 @@ static void test_encrypted_rar_archive(const char *filename, int filenamesEncryp assertEqualInt(1, archive_entry_is_data_encrypted(ae)); assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); assertEqualInt(1, archive_read_has_encrypted_entries(a)); - assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + assertEqualIntA(a, ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); /* End of archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_rar_encryption_data.c b/libarchive/test/test_read_format_rar_encryption_data.c index 540546a8dd8a..6bfcadabe331 100644 --- a/libarchive/test/test_read_format_rar_encryption_data.c +++ b/libarchive/test/test_read_format_rar_encryption_data.c @@ -50,7 +50,7 @@ DEFINE_TEST(test_read_format_rar_encryption_data) assertEqualInt(1, archive_entry_is_data_encrypted(ae)); assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); /* Verify encrypted file "bar.txt" */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); @@ -60,7 +60,7 @@ DEFINE_TEST(test_read_format_rar_encryption_data) assertEqualInt(1, archive_entry_is_data_encrypted(ae)); assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); assertEqualInt(2, archive_file_count(a)); @@ -72,7 +72,7 @@ DEFINE_TEST(test_read_format_rar_encryption_data) assertEqualIntA(a, ARCHIVE_FORMAT_RAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_rar_encryption_header.c b/libarchive/test/test_read_format_rar_encryption_header.c index e54db5152383..17444a2e2b7c 100644 --- a/libarchive/test/test_read_format_rar_encryption_header.c +++ b/libarchive/test/test_read_format_rar_encryption_header.c @@ -65,6 +65,6 @@ DEFINE_TEST(test_read_format_rar_encryption_header) assertEqualIntA(a, ARCHIVE_FORMAT_RAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_rar_encryption_partially.c b/libarchive/test/test_read_format_rar_encryption_partially.c index e68e78831b37..d117258169e5 100644 --- a/libarchive/test/test_read_format_rar_encryption_partially.c +++ b/libarchive/test/test_read_format_rar_encryption_partially.c @@ -51,7 +51,7 @@ DEFINE_TEST(test_read_format_rar_encryption_partially) assertEqualInt(1, archive_entry_is_data_encrypted(ae)); assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - assertEqualInt(ARCHIVE_FATAL, archive_read_data(a, buff, sizeof(buff))); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); /* Verify unencrypted file "bar.txt". */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); @@ -73,6 +73,6 @@ DEFINE_TEST(test_read_format_rar_encryption_partially) assertEqualIntA(a, ARCHIVE_FORMAT_RAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_rar_invalid1.c b/libarchive/test/test_read_format_rar_invalid1.c index cac58688ce21..c99201763d4e 100644 --- a/libarchive/test/test_read_format_rar_invalid1.c +++ b/libarchive/test/test_read_format_rar_invalid1.c @@ -37,7 +37,7 @@ DEFINE_TEST(test_read_format_rar_invalid1) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buff, 99)); + assertEqualIntA(a, ARCHIVE_FAILED, archive_read_data(a, buff, 99)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_rar_newsub_rr_over_1m.rar.uu b/libarchive/test/test_read_format_rar_newsub_rr_over_1m.rar.uu new file mode 100644 index 000000000000..7df22b4d84aa --- /dev/null +++ b/libarchive/test/test_read_format_rar_newsub_rr_over_1m.rar.uu @@ -0,0 +1,23307 @@ +begin 644 test_read_format_rar_newsub_rr_over_1m.rar +M4F%R(1H' &^7<T #0 !^^WH P"( 0 0 $ $ " 4 +M, ( %)2 +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M +M #$/7L +#0 < + +end diff --git a/libarchive/test/test_read_format_rar_overflow.c b/libarchive/test/test_read_format_rar_overflow.c index b39ed6b2ba67..1f5c63dae75b 100644 --- a/libarchive/test/test_read_format_rar_overflow.c +++ b/libarchive/test/test_read_format_rar_overflow.c @@ -41,7 +41,7 @@ DEFINE_TEST(test_read_format_rar_overflow) assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); assertEqualInt(48, archive_entry_size(ae)); /* The next call should reproduce Issue #2565 */ - assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data_block(a, &buff, &size, &offset)); + assertEqualIntA(a, ARCHIVE_FAILED, archive_read_data_block(a, &buff, &size, &offset)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); diff --git a/libarchive/test/test_read_format_rar_unbound_staticdata.rar.uu b/libarchive/test/test_read_format_rar_unbound_staticdata.rar.uu new file mode 100644 index 000000000000..d95708e7a50b --- /dev/null +++ b/libarchive/test/test_read_format_rar_unbound_staticdata.rar.uu @@ -0,0 +1,6 @@ +begin 644 test_read_format_rar_unbound_staticdata.rar +M4F%R(1H'`,^0<P``#0`````````D>W0@`"L`-P````0````#'-]$(0`````= +M,0L`I($``'!O8U]B-S8N='AT`$```````````&V?]4_(#3#0``B.IW.YK)_P +C`````````````````````````)5`M\R`2$`0``2P>P``!P`` +` +end diff --git a/libarchive/test/test_read_format_tar_acl_oob_read.c b/libarchive/test/test_read_format_tar_acl_oob_read.c new file mode 100644 index 000000000000..13c2bb78b046 --- /dev/null +++ b/libarchive/test/test_read_format_tar_acl_oob_read.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2025 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Regression test: a crafted TAR file with malformed PAX ACL attributes + * triggered an out-of-bounds read in next_field() when the remaining + * length was zero. + */ +DEFINE_TEST(test_read_format_tar_acl_oob_read) +{ + const char *refname = "test_read_format_tar_acl_oob_read.tar"; + struct archive *a; + struct archive_entry *ae; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + + /* Read all headers; must not crash on ACL parsing. */ + while (archive_read_next_header(a, &ae) == ARCHIVE_OK) { + /* Just iterate through entries. */ + } + + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_tar_acl_oob_read.tar.uu b/libarchive/test/test_read_format_tar_acl_oob_read.tar.uu new file mode 100644 index 000000000000..bbf9511aa87e --- /dev/null +++ b/libarchive/test/test_read_format_tar_acl_oob_read.tar.uu @@ -0,0 +1,129 @@ +begin 644 test_read_format_tar_acl_oob_read.tar +M4&%X2&5A9&5R+V9I;&4````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#<W-R``,#`P,#`P(``P,#`P,#`@`#`P,#`P,#`P,3,R +M(#`P,#`P,#`P,#`P(#`Q,C`P,P`@>``````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U<W1A<@`P,``````` +M```````````````````````````````````````````````````````````` +M```````````````````P,#`P,#`@`#`P,#`P,"`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````Y,"!30TA)3%DN86-L+F%C93UO=VYE<D`Z<G=X +M<&%!4E=C0V]S.CIA;&QO=RQG<F]U<$`Z<G=P85)C<SHZ86QL;W<L979E<GEO +M;F5`.G)A4F-S.CIA;&QO=PH````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````&9I;&4````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````P +M,#`W-S<@`#`P,#`P,"``,#`P,#`P(``P,#`P,#`P,#`P,"`P,#`P,#`P,#`P +M,"`P,3`P,C0`(#`````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````=7-T87(`,#`````````````````````` +M```````````````````````````````````````````````````````````` +M````,#`P,#`P(``P,#`P,#`@```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````4&%X2&5A9&5R+V9I;&4````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````#`P,#<W-R``,#`P,#`P(``P,#`P,#`@`#`P,#`P +M,#`P,C4V(#`P,#`P,#`P,#`P(#`Q,C`Q,@`@>``````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!U<W1A<@`P +M,``````````````````````````````````````````````````````````` +M```````````````````````````P,#`P,#`@`#`P,#`P,"`````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````Q-S0@4T-(24Q9+F%C;"YA8V4];W=N +M97)`.G)W<&%!4E=C0V]S.CIA;&QO=RQU<V5R.G5S97(W-SIR85)C<SI).F%L +M;&]W.C<W+'5S97(Z=7-E<C<X.G)W>#HZ9&5N>3HW."QG<F]U<$`Z<G=P85)C +M<SHZ86QL;W<L9W)O=7`Z9W)O=7`W.#IW<``````````````````````````` +M````````05=#;SHZ9&5N>3HW."QE=F5R>6]N94`Z<F%28W,Z.F%L;&]W"@`` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````9FEL90`````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````#`P,#<W-R``,#`P,#`P +M(``P,#`P,#`@`#`P,#`P,#`P,#`P(#`P,#`P,#`P,#`P(#`Q,#`R-``@,``` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````!U<W1A<@`P,``````````````````````````````````````` +M```````````````````````````````````````````````P,#`P,#`@`#`P +M,#`P,"`````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````!087A(96%D +M97(O9FEL90`````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````,#`P-S<W(``P,#`P,#`@`#`P,#`P,"``,#`P,#`P,#`R-C(@,#`P,#`P +M,#`P,#`@,#$R,#`W`"!X```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````'5S=&%R`#`P```````````````` +M```````````````````````````````````````````````````````````` +M`````````#`P,#`P,"``,#`P,#`P(``````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#$W."!30TA)3%DN86-L+F%C93UO=VYE<D`Z<G=X<&%!4E=C +M0V]S.CIA;&QO=RQU<V5R.G5S97(W-SIR=W!A4F-O<SHZ86QL;W<Z-S<L=7-E +M<CIU<V5R-S<Z=W`Z4SIA=61I=#HW-RQG<F]U<$`Z<G=P85)C<SHZ86QL;W<L +M9W)O=7`Z9W)O=7`W.#IR85)C.D8Z86QA<FTZ-S@L979E<GEO;F5`.G)A4F-S +M.CIA;&QO=PH````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````````9FEL90`````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````#`P,#<W-R`` +M,#`P,#`P(``P,#`P,#`@`#`P,#`P,#`P,#`P(#`P,#`P,#`P,#`P(#`Q,#`R +M-``@,``````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````!U<W1A<@`P,``````````````````````````````` +M```````````````````````````````````````````````````````P,#`P +M,#`@`#`P,#`P,"`````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +A```````````````````````````````````````````` +` +end diff --git a/libarchive/test/test_read_format_tar_concatenated.c b/libarchive/test/test_read_format_tar_concatenated.c index f6ed03a4404b..b7726b34a45e 100644 --- a/libarchive/test/test_read_format_tar_concatenated.c +++ b/libarchive/test/test_read_format_tar_concatenated.c @@ -54,7 +54,7 @@ DEFINE_TEST(test_read_format_tar_concatenated) /* Verify the end-of-archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); @@ -80,6 +80,6 @@ DEFINE_TEST(test_read_format_tar_concatenated) /* Verify the end-of-archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_tar_empty_filename.c b/libarchive/test/test_read_format_tar_empty_filename.c index 310d260bb4d6..b9c03f572fae 100644 --- a/libarchive/test/test_read_format_tar_empty_filename.c +++ b/libarchive/test/test_read_format_tar_empty_filename.c @@ -58,6 +58,6 @@ DEFINE_TEST(test_read_format_tar_empty_filename) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_tar_empty_with_gnulabel.c b/libarchive/test/test_read_format_tar_empty_with_gnulabel.c index a86bb287bf4e..43db2037562a 100644 --- a/libarchive/test/test_read_format_tar_empty_with_gnulabel.c +++ b/libarchive/test/test_read_format_tar_empty_with_gnulabel.c @@ -47,6 +47,6 @@ DEFINE_TEST(test_read_format_tar_empty_with_gnulabel) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_GNUTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_tar_filename.c b/libarchive/test/test_read_format_tar_filename.c index 5da94967ddf8..42081ef1935d 100644 --- a/libarchive/test/test_read_format_tar_filename.c +++ b/libarchive/test/test_read_format_tar_filename.c @@ -100,7 +100,7 @@ test_read_format_tar_filename_KOI8R_CP866(const char *refname) archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); next_test: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); @@ -150,7 +150,7 @@ next_test: archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -214,7 +214,7 @@ test_read_format_tar_filename_KOI8R_UTF8(const char *refname) assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* @@ -261,7 +261,7 @@ test_read_format_tar_filename_KOI8R_UTF8(const char *refname) archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -329,7 +329,7 @@ test_read_format_tar_filename_KOI8R_CP1251(const char *refname) archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); next_test: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); @@ -377,7 +377,7 @@ next_test: archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_tar_mac_metadata.c b/libarchive/test/test_read_format_tar_mac_metadata.c index b4745a22ee3b..f5eb5c9bde3f 100644 --- a/libarchive/test/test_read_format_tar_mac_metadata.c +++ b/libarchive/test/test_read_format_tar_mac_metadata.c @@ -79,7 +79,7 @@ DEFINE_TEST(test_read_format_tar_mac_metadata) /* ... and nothing else */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/libarchive/test/test_read_format_tar_pax_g_large.c b/libarchive/test/test_read_format_tar_pax_g_large.c index c4771e699777..092cf33a7d5d 100644 --- a/libarchive/test/test_read_format_tar_pax_g_large.c +++ b/libarchive/test/test_read_format_tar_pax_g_large.c @@ -48,6 +48,6 @@ DEFINE_TEST(test_read_format_tar_pax_g_large) assertEqualInt(ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualInt(ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_tar_pax_large_attr.c b/libarchive/test/test_read_format_tar_pax_large_attr.c index 1c2b55f9c6fb..024df41e090c 100644 --- a/libarchive/test/test_read_format_tar_pax_large_attr.c +++ b/libarchive/test/test_read_format_tar_pax_large_attr.c @@ -60,6 +60,6 @@ DEFINE_TEST(test_read_format_tar_pax_large_attr) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_tar_pax_negative_time.c b/libarchive/test/test_read_format_tar_pax_negative_time.c index b4edc3c2d951..cdcba03262c1 100644 --- a/libarchive/test/test_read_format_tar_pax_negative_time.c +++ b/libarchive/test/test_read_format_tar_pax_negative_time.c @@ -63,6 +63,6 @@ DEFINE_TEST(test_read_format_tar_pax_negative_time) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_tar_pax_timestamps.c b/libarchive/test/test_read_format_tar_pax_timestamps.c new file mode 100644 index 000000000000..9e416049c9ef --- /dev/null +++ b/libarchive/test/test_read_format_tar_pax_timestamps.c @@ -0,0 +1,64 @@ +/*- + * Copyright (c) 2025 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Read a pax formatted tar archive that has a negative modification time. + */ +DEFINE_TEST(test_read_format_tar_pax_timestamps) +{ + char name[] = "test_read_format_tar_pax_timestamps.tar"; + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); + + /* Read first entry. */ + assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae)); + assertEqualString("empty", archive_entry_pathname(ae)); + assertEqualInt(224165920, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualString("root", archive_entry_uname(ae)); + assertEqualInt(0, archive_entry_gid(ae)); + assertEqualString("root", archive_entry_gname(ae)); + assertEqualInt(0100644, archive_entry_mode(ae)); + assertEqualInt(archive_entry_is_encrypted(ae), 0); + assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + /* Verify that the format detection worked. */ + assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); + assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_tar_pax_timestamps.tar.uu b/libarchive/test/test_read_format_tar_pax_timestamps.tar.uu new file mode 100644 index 000000000000..089705c230a7 --- /dev/null +++ b/libarchive/test/test_read_format_tar_pax_timestamps.tar.uu @@ -0,0 +1,60 @@ +begin 644 test_read_format_tar_pax_timestamps.tar +M4&%X2&5A9&5R+V5M<'1Y```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#8T-"``,#`P,#`P(``P,#`P,#`@`#`P,#`P,#`P,#,W +M(#`P,#`P,#`P,#`P(#`Q-#(P-0`@>`````````````````````````!N```` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````!U<W1A<@`P,')O;W0` +M````````````````````````````````````<F]O=``````````````````` +M```````````````````P,#`P,#`@`#`P,#`P,"`````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````S,2!M=&EM93TQ-S0X,#@Y-#8T+CDU,3DR.#0V +M-V$*```````````````````````````````````````````````````````` +M````````````````````````````````````````````````````;@`````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````&5M<'1Y```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````P +M,#`V-#0@`#`P,#`P,"``,#`P,#`P(``P,#`P,#`P,#`P,""```````````U< +M@"`P,3$U-S4`(#`````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````=7-T87(`,#!R;V]T```````````````` +M`````````````````````')O;W0````````````````````````````````` +M````,#`P,#`P(``P,#`P,#`@```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +H```````````````````````````````````````````````````````` +` +end diff --git a/libarchive/test/test_read_format_tar_timestamp_overflow.c b/libarchive/test/test_read_format_tar_timestamp_overflow.c new file mode 100644 index 000000000000..0bb1101fcb5e --- /dev/null +++ b/libarchive/test/test_read_format_tar_timestamp_overflow.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Read a tar archive that has an oversized timestamp value. + * This should not cause an infinite loop. + */ +DEFINE_TEST(test_read_format_tar_timestamp_overflow) +{ + char name[] = "test_read_format_tar_timestamp_overflow.tar"; + struct archive_entry *ae; + struct archive *a; + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + extract_reference_file(name); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); + + /* Read first entry. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("tmp/f.txt", archive_entry_pathname(ae)); + /* 15155542402 should be parsed correctly if time_t is 64-bit, + * or handled gracefully if not. */ + (void)archive_entry_mtime(ae); + + /* Verify the end-of-archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_tar_timestamp_overflow.tar.uu b/libarchive/test/test_read_format_tar_timestamp_overflow.tar.uu new file mode 100644 index 000000000000..b5520ff44eda --- /dev/null +++ b/libarchive/test/test_read_format_tar_timestamp_overflow.tar.uu @@ -0,0 +1,38 @@ +begin 600 test_read_format_tar_timestamp_overflow.tar +M=&UP+V8N='AT```````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````#`P,#`V-``````````````````````````````````P,#$V +M`#$U,34U-30R-#`R`#`Q,C8Q-``@,``````````````````````````````` +M``````````````````````````````#_```````````````````````````` +M``````````````````````````````````````````!U<W1A<B`@`&UA<W1E +M<@``````````````````````````````````;6%S=&5R```````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````!`````````````````````#0` +M,#`P,3<U,``P,#`Q-S4P`#`P,#`P,#`````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +&```````` +` +end diff --git a/libarchive/test/test_read_format_tgz.c b/libarchive/test/test_read_format_tgz.c index 5bb5e02be4f4..6f9a8eb1909d 100644 --- a/libarchive/test/test_read_format_tgz.c +++ b/libarchive/test/test_read_format_tgz.c @@ -55,7 +55,7 @@ DEFINE_TEST(test_read_format_tgz) assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); assertEqualInt(archive_entry_is_encrypted(ae), 0); assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK,archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_ustar_filename.c b/libarchive/test/test_read_format_ustar_filename.c index 0c7e8a3c8070..7896ff4ec9ff 100644 --- a/libarchive/test/test_read_format_ustar_filename.c +++ b/libarchive/test/test_read_format_ustar_filename.c @@ -75,7 +75,7 @@ test_read_format_ustar_filename_eucJP_UTF8(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -130,7 +130,7 @@ test_read_format_ustar_filename_CP866_KOI8R(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -185,7 +185,7 @@ test_read_format_ustar_filename_CP866_UTF8(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -241,7 +241,7 @@ test_read_format_ustar_filename_KOI8R_CP866(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -296,7 +296,7 @@ test_read_format_ustar_filename_KOI8R_UTF8(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -350,7 +350,7 @@ test_read_format_ustar_filename_eucJP_CP932(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -406,7 +406,7 @@ test_read_format_ustar_filename_CP866_CP1251(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -462,7 +462,7 @@ test_read_format_ustar_filename_CP866_CP1251_win(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -517,7 +517,7 @@ test_read_format_ustar_filename_KOI8R_CP1251(const char *refname) assertEqualIntA(a, ARCHIVE_FORMAT_TAR_USTAR, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_xar.c b/libarchive/test/test_read_format_xar.c index 5c306e58522e..d70282778869 100644 --- a/libarchive/test/test_read_format_xar.c +++ b/libarchive/test/test_read_format_xar.c @@ -724,6 +724,24 @@ static unsigned char archive13[] = { 0xce,0xac,0xe0,0x02,0x00,0x20,0xfa,0x04,0xc5 }; +static unsigned char archive14_xattr_fstype[] = { +0x78,0x61,0x72,0x21,0x00,0x1c,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc2, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x22,0x00,0x00,0x00,0x00,0x78,0x9c,0x3d,0x8f, +0x41,0x8e,0xc2,0x30,0x0c,0x45,0xf7,0x3d,0x45,0x94,0x3d,0x75,0x47,0x42,0x68,0x16, +0xbf,0x61,0x37,0x27,0x18,0x0e,0x10,0xb5,0x4e,0x89,0x94,0x26,0x55,0xe3,0x41,0xc0, +0xe9,0x49,0x4a,0x99,0xd5,0x7f,0x96,0x6d,0xe9,0x7d,0x9c,0xef,0x73,0x50,0x37,0x5e, +0xb3,0x4f,0xb1,0xd7,0x5f,0x6d,0xa7,0x15,0xc7,0x21,0x8d,0x3e,0x4e,0xbd,0xbe,0xfc, +0xfe,0x1c,0xbe,0xf5,0xd9,0x34,0xb8,0xdb,0xd5,0x40,0xd2,0x50,0xd0,0xf9,0xc0,0xca, +0x8f,0xe5,0x58,0x1b,0x44,0x3b,0xb3,0x71,0xa0,0x2d,0x21,0x8f,0xa5,0x4c,0x65,0x0f, +0xda,0x10,0x73,0x1a,0xd9,0x74,0xa7,0xe3,0x11,0xb4,0x61,0xa3,0x14,0xd8,0xfe,0x7f, +0x07,0x8e,0x93,0x5c,0x4d,0xd9,0xee,0x84,0xe4,0x5c,0x66,0x31,0x1d,0x68,0x27,0x64, +0xff,0xe4,0x7a,0xb1,0x25,0x3e,0x6e,0x2a,0xcb,0x23,0x70,0xaf,0xed,0xb2,0x04,0x3f, +0x58,0x29,0xf6,0x94,0x06,0x61,0x39,0x64,0x59,0xd9,0xce,0x9a,0x76,0xb7,0xbf,0xcc, +0x6b,0xeb,0x72,0xd5,0xf9,0x58,0xbe,0x27,0x73,0x75,0x19,0xb4,0x33,0x88,0x6d,0xa9, +0x46,0xd5,0xbd,0x66,0x6d,0x0a,0xaa,0xa5,0x9b,0x17,0xc3,0xba,0x60,0xaa,0x44,0x41, +0x54,0x41 +}; + enum enc { GZIP, BZIP2 @@ -844,6 +862,30 @@ static void verifyB(unsigned char *d, size_t s) { assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } +static void verify_xattr_fstype_cleanup(unsigned char *d, size_t s) +{ + struct archive_entry *ae; + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + r = archive_read_support_format_xar(a); + if (r == ARCHIVE_WARN) { + skipping("xar reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, d, s)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("f", archive_entry_pathname(ae)); + assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + DEFINE_TEST(test_read_format_xar) { verify(archive1, sizeof(archive1), verify0, verify1, GZIP); @@ -861,6 +903,12 @@ DEFINE_TEST(test_read_format_xar) verifyB(archive13, sizeof(archive13)); } +DEFINE_TEST(test_read_format_xar_xattr_fstype_cleanup) +{ + verify_xattr_fstype_cleanup(archive14_xattr_fstype, + sizeof(archive14_xattr_fstype)); +} + DEFINE_TEST(test_read_format_xar_duplicate_filename_node) { static const char *reffiles[] = @@ -891,3 +939,33 @@ DEFINE_TEST(test_read_format_xar_duplicate_filename_node) assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } + +DEFINE_TEST(test_read_format_xar_large_mode) +{ + static const char *reffiles[] = + { + "test_read_format_xar_large_mode.xar", + NULL + }; + struct archive_entry *ae; + struct archive *a; + int r; + + extract_reference_files(reffiles); + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_support_filter_all(a)); + + r = archive_read_support_format_xar(a); + if (r == ARCHIVE_WARN) { + skipping("xar reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + + assertA(0 == archive_read_open_filenames(a, reffiles, 10240)); + + assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_xar_large_mode.xar.uu b/libarchive/test/test_read_format_xar_large_mode.xar.uu new file mode 100644 index 000000000000..c606cbdcdb32 --- /dev/null +++ b/libarchive/test/test_read_format_xar_large_mode.xar.uu @@ -0,0 +1,11 @@ +begin 644 test_read_format_xar_large_mode.xar.uu +M>&%R(0`<``$````````!'`````````(E`````7B<?5'+;H,P$+SG*RSNU(8` +MI<@XMWY!>ND-P4*L8HRPB4*_OO;RJ"I5\65G9V<?WN67A^K)'28C]5`&T0L+ +M"`RU;N30E<'']3W,@XLX\4<UB1/A5M?.$%Y/4%F7$5JI0,0LSD*6AM'Y&N7% +M.2Y8PNE?"2;=H/XRLR+&+CV4@;E54>`CA.NV-6`%XW1#R!KY[8MSBL"7H'L- +M]%K9`Y&-&WLK,U2N%:C1+IPB1M8N(PBOY10ADG+0#8@HR5C*7CE=78PT<)<U +M#-IU3EWOP\6@PBQVO"QQ7U5'[BP;_PEO5M_`)":MK>,\1+);1=TNZB8]CYMJ +MQ4C7_^PV?BO2_-.M85^JF^B)3/W*JB>RZC@1]6ORAZ9X:4[Q[C\>T9S6NQCE +E6U?LW?LN'2[LH:]/A`0)%$!XG'U1RVZ#,!"\YRLL[M2&`*7(.``` +` +end diff --git a/libarchive/test/test_read_format_zip.c b/libarchive/test/test_read_format_zip.c index 90d00474ba11..2c18387bd459 100644 --- a/libarchive/test/test_read_format_zip.c +++ b/libarchive/test/test_read_format_zip.c @@ -305,7 +305,7 @@ verify_extract_length_at_end(struct archive *a, int seek_checks) } assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } static void @@ -368,7 +368,7 @@ test_symlink(void) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } @@ -398,7 +398,7 @@ DEFINE_TEST(test_read_format_zip_ppmd_one_file) assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_ppmd_one_file_blockread) @@ -418,7 +418,7 @@ DEFINE_TEST(test_read_format_zip_ppmd_one_file_blockread) assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_ppmd_multi) @@ -450,7 +450,7 @@ DEFINE_TEST(test_read_format_zip_ppmd_multi) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_ppmd_multi_blockread) @@ -482,7 +482,7 @@ DEFINE_TEST(test_read_format_zip_ppmd_multi_blockread) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_one_file) @@ -507,7 +507,7 @@ DEFINE_TEST(test_read_format_zip_lzma_one_file) assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_one_file_blockread) @@ -532,7 +532,7 @@ DEFINE_TEST(test_read_format_zip_lzma_one_file_blockread) assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_multi) @@ -569,7 +569,7 @@ DEFINE_TEST(test_read_format_zip_lzma_multi) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_multi_blockread) @@ -606,7 +606,7 @@ DEFINE_TEST(test_read_format_zip_lzma_multi_blockread) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -619,7 +619,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_one_file) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("bzip2 is not fully supported on this platform"); - archive_read_close(a); + archive_read_free(a); return; } extract_reference_file(refname); @@ -632,7 +632,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_one_file) assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_bzip2_one_file_blockread) @@ -644,7 +644,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_one_file_blockread) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("bzip2 is not fully supported on this platform"); - archive_read_close(a); + archive_read_free(a); return; } extract_reference_file(refname); @@ -657,7 +657,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_one_file_blockread) assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_bzip2_multi) @@ -669,7 +669,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_multi) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("bzip2 is not fully supported on this platform"); - archive_read_close(a); + archive_read_free(a); return; } extract_reference_file(refname); @@ -694,7 +694,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_multi) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_bzip2_multi_blockread) @@ -706,7 +706,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_multi_blockread) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("bzip2 is not fully supported on this platform"); - archive_read_close(a); + archive_read_free(a); return; } extract_reference_file(refname); @@ -731,7 +731,7 @@ DEFINE_TEST(test_read_format_zip_bzip2_multi_blockread) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_zstd_one_file) @@ -757,7 +757,7 @@ DEFINE_TEST(test_read_format_zip_zstd_one_file) assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_zstd_one_file_blockread) @@ -783,7 +783,7 @@ DEFINE_TEST(test_read_format_zip_zstd_one_file_blockread) assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_zstd_multi) @@ -821,7 +821,7 @@ DEFINE_TEST(test_read_format_zip_zstd_multi) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_zstd_multi_blockread) @@ -859,7 +859,7 @@ DEFINE_TEST(test_read_format_zip_zstd_multi_blockread) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_xz_multi) @@ -896,7 +896,7 @@ DEFINE_TEST(test_read_format_zip_xz_multi) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_xz_multi_blockread) @@ -933,7 +933,7 @@ DEFINE_TEST(test_read_format_zip_xz_multi_blockread) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_ppmd8_crash_1) @@ -955,7 +955,7 @@ DEFINE_TEST(test_read_format_zip_ppmd8_crash_1) * proper fix, the unpacker was entering an unlimited loop. */ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, 1)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_bz2_hang_on_invalid) @@ -968,7 +968,7 @@ DEFINE_TEST(test_read_format_zip_bz2_hang_on_invalid) assert((a = archive_read_new()) != NULL); if (ARCHIVE_OK != archive_read_support_filter_bzip2(a)) { skipping("bzip2 is not fully supported on this platform"); - archive_read_close(a); + archive_read_free(a); return; } extract_reference_file(refname); @@ -981,7 +981,7 @@ DEFINE_TEST(test_read_format_zip_bz2_hang_on_invalid) * But it shouldn't crash. */ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, 64)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_ppmd8_crash_2) @@ -1002,7 +1002,7 @@ DEFINE_TEST(test_read_format_zip_ppmd8_crash_2) * But it shouldn't crash. */ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, 64)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_alone_leak) @@ -1037,7 +1037,7 @@ DEFINE_TEST(test_read_format_zip_lzma_alone_leak) assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, sizeof(buf))); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* This testcase shouldn't produce any memory leaks. When running test * suite under Valgrind or ASan, the test runner won't return with @@ -1066,7 +1066,7 @@ DEFINE_TEST(test_read_format_zip_lzma_stream_end) assertEqualIntA(a, 0, extract_one(a, ae, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_lzma_stream_end_blockread) @@ -1091,7 +1091,7 @@ DEFINE_TEST(test_read_format_zip_lzma_stream_end_blockread) assertEqualIntA(a, 0, extract_one_using_blocks(a, 13, 0xBA8E3BAA)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_7z_lzma) @@ -1123,7 +1123,7 @@ DEFINE_TEST(test_read_format_zip_7z_lzma) "/src/abc_measurement_analysis_sample.py", archive_entry_symlink(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_7z_deflate) @@ -1169,5 +1169,5 @@ DEFINE_TEST(test_read_format_zip_7z_deflate) } assertEqualInt(AE_IFLNK, archive_entry_filetype(ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_zip_7075_utf8_paths.c b/libarchive/test/test_read_format_zip_7075_utf8_paths.c index fefcc82881f8..66650030e449 100644 --- a/libarchive/test/test_read_format_zip_7075_utf8_paths.c +++ b/libarchive/test/test_read_format_zip_7075_utf8_paths.c @@ -86,7 +86,7 @@ DEFINE_TEST(test_read_format_zip_utf8_paths) assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); verify(a); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* Verify with streaming reader. */ p = slurpfile(&s, "%s", refname); diff --git a/libarchive/test/test_read_format_zip_comment_stored.c b/libarchive/test/test_read_format_zip_comment_stored.c index 39f83a821006..feab4b5ee2df 100644 --- a/libarchive/test/test_read_format_zip_comment_stored.c +++ b/libarchive/test/test_read_format_zip_comment_stored.c @@ -61,7 +61,7 @@ verify(const char *refname) assertEqualIntA(a, archive_read_has_encrypted_entries(a), 0); assertEqualInt(archive_entry_is_encrypted(ae), 0); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/libarchive/test/test_read_format_zip_encryption_data.c b/libarchive/test/test_read_format_zip_encryption_data.c index 4a6502b9bf2d..2a94b2cd3d54 100644 --- a/libarchive/test/test_read_format_zip_encryption_data.c +++ b/libarchive/test/test_read_format_zip_encryption_data.c @@ -72,7 +72,7 @@ DEFINE_TEST(test_read_format_zip_encryption_data) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_zip_encryption_header.c b/libarchive/test/test_read_format_zip_encryption_header.c index fb19c1421946..6c190c435d59 100644 --- a/libarchive/test/test_read_format_zip_encryption_header.c +++ b/libarchive/test/test_read_format_zip_encryption_header.c @@ -65,6 +65,6 @@ DEFINE_TEST(test_read_format_zip_encryption_header) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_zip_encryption_partially.c b/libarchive/test/test_read_format_zip_encryption_partially.c index cd5d2103ea6a..70241aed178b 100644 --- a/libarchive/test/test_read_format_zip_encryption_partially.c +++ b/libarchive/test/test_read_format_zip_encryption_partially.c @@ -73,6 +73,6 @@ DEFINE_TEST(test_read_format_zip_encryption_partially) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_zip_filename.c b/libarchive/test/test_read_format_zip_filename.c index b673344738be..21702d2f62f3 100644 --- a/libarchive/test/test_read_format_zip_filename.c +++ b/libarchive/test/test_read_format_zip_filename.c @@ -81,7 +81,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP932_eucJP) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -159,7 +159,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP932_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -234,7 +234,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_eucJP) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -329,7 +329,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -385,7 +385,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP866_KOI8R) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -441,7 +441,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP866_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -498,7 +498,7 @@ DEFINE_TEST(test_read_format_zip_filename_KOI8R_CP866) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -554,7 +554,7 @@ DEFINE_TEST(test_read_format_zip_filename_KOI8R_UTF8) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -616,7 +616,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_KOI8R) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -681,7 +681,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_CP866) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -734,7 +734,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_UTF8_ru) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -792,7 +792,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP932_CP932) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -869,7 +869,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_CP932) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -926,7 +926,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP866_CP1251) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -983,7 +983,7 @@ DEFINE_TEST(test_read_format_zip_filename_CP866_CP1251_win) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1039,7 +1039,7 @@ DEFINE_TEST(test_read_format_zip_filename_KOI8R_CP1251) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1103,7 +1103,7 @@ DEFINE_TEST(test_read_format_zip_filename_UTF8_CP1251) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); cleanup: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } @@ -1173,7 +1173,7 @@ DEFINE_TEST(test_read_format_zip_filename_KOI8R_UTF8_2) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); next_test: assertEqualInt(ARCHIVE_OK, archive_read_free(a)); @@ -1223,7 +1223,7 @@ next_test: assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); #endif } diff --git a/libarchive/test/test_read_format_zip_jar.c b/libarchive/test/test_read_format_zip_jar.c index 75ea3eb9b868..0b18e3175aa7 100644 --- a/libarchive/test/test_read_format_zip_jar.c +++ b/libarchive/test/test_read_format_zip_jar.c @@ -53,6 +53,6 @@ DEFINE_TEST(test_read_format_zip_jar) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/libarchive/test/test_read_format_zip_mac_metadata.c b/libarchive/test/test_read_format_zip_mac_metadata.c index 9f7c35e1df85..dea5df9c64de 100644 --- a/libarchive/test/test_read_format_zip_mac_metadata.c +++ b/libarchive/test/test_read_format_zip_mac_metadata.c @@ -110,7 +110,7 @@ DEFINE_TEST(test_read_format_zip_mac_metadata) } assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/libarchive/test/test_read_format_zip_malformed.c b/libarchive/test/test_read_format_zip_malformed.c index 7e46abd8a4c1..4f3b0e182a33 100644 --- a/libarchive/test/test_read_format_zip_malformed.c +++ b/libarchive/test/test_read_format_zip_malformed.c @@ -42,7 +42,7 @@ test_malformed1(void) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* Verify with streaming reader. */ p = slurpfile(&s, "%s", refname); @@ -51,7 +51,7 @@ test_malformed1(void) assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 31)); assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/libarchive/test/test_read_format_zip_nested.c b/libarchive/test/test_read_format_zip_nested.c index b32e4bb94211..73222f9e6088 100644 --- a/libarchive/test/test_read_format_zip_nested.c +++ b/libarchive/test/test_read_format_zip_nested.c @@ -62,7 +62,7 @@ DEFINE_TEST(test_read_format_zip_nested) /* Close outer Zip */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); @@ -80,7 +80,7 @@ DEFINE_TEST(test_read_format_zip_nested) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(inner); } diff --git a/libarchive/test/test_read_format_zip_nofiletype.c b/libarchive/test/test_read_format_zip_nofiletype.c index d2798b283185..04728d25ef09 100644 --- a/libarchive/test/test_read_format_zip_nofiletype.c +++ b/libarchive/test/test_read_format_zip_nofiletype.c @@ -60,6 +60,6 @@ DEFINE_TEST(test_read_format_zip_nofiletype) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/libarchive/test/test_read_format_zip_padded.c b/libarchive/test/test_read_format_zip_padded.c index dcbf3406e867..af996a7314f4 100644 --- a/libarchive/test/test_read_format_zip_padded.c +++ b/libarchive/test/test_read_format_zip_padded.c @@ -51,7 +51,7 @@ verify_padded_archive(const char *refname) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/libarchive/test/test_read_format_zip_sfx.c b/libarchive/test/test_read_format_zip_sfx.c index dad0a270d7bc..7b672fe0791c 100644 --- a/libarchive/test/test_read_format_zip_sfx.c +++ b/libarchive/test/test_read_format_zip_sfx.c @@ -58,7 +58,7 @@ DEFINE_TEST(test_read_format_zip_sfx) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/libarchive/test/test_read_format_zip_traditional_encryption_data.c b/libarchive/test/test_read_format_zip_traditional_encryption_data.c index 0cf2d0a1576d..423197032f35 100644 --- a/libarchive/test/test_read_format_zip_traditional_encryption_data.c +++ b/libarchive/test/test_read_format_zip_traditional_encryption_data.c @@ -92,7 +92,7 @@ DEFINE_TEST(test_read_format_zip_traditional_encryption_data) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); @@ -161,7 +161,7 @@ DEFINE_TEST(test_read_format_zip_traditional_encryption_data) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_zip_winzip_aes.c b/libarchive/test/test_read_format_zip_winzip_aes.c index 9b609b4f29ff..064244395a6b 100644 --- a/libarchive/test/test_read_format_zip_winzip_aes.c +++ b/libarchive/test/test_read_format_zip_winzip_aes.c @@ -78,7 +78,7 @@ test_winzip_aes(const char *refname, int need_libz) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); @@ -128,7 +128,7 @@ test_winzip_aes(const char *refname, int need_libz) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_format_zip_winzip_aes256_large_bzip2.zip.uu b/libarchive/test/test_read_format_zip_winzip_aes256_large_bzip2.zip.uu new file mode 100644 index 000000000000..f7f3cedb7b0b --- /dev/null +++ b/libarchive/test/test_read_format_zip_winzip_aes256_large_bzip2.zip.uu @@ -0,0 +1,1616 @@ +begin 644 test_read_format_zip_winzip_aes256_large_bzip2.zip +M4$L#!#,``0!C`/BN(T4`````A]0``&LZ%@`(``L`36%K969I;&4!F0<``@!! +M10,,`':3MFR@Z]K3DUA%-ZAA0_^+)`=$&R=!5HZ/@!8[87</X`D"+1_`NP<J +MR:D$T!W'/(BNZ%AQ-!ZC!P/?H-@TT]RM1\\P@]ASO+R9QZV16"Y)P6VX=B$Q +M+-\71/`I/,^HDM5AGC7>=`V;"!#=6&?I64.;Y5PIANF#>Z6QD],#@+_>R:,H +M:0N3:0@(8?"!H8,5NZ(WC\+@_*&N<,;?0[[\N%J3,9TCSKNJ4!(M:[92ZJ;N +M+Z1%@4@YNB.[>Y'YW+)G_A3/S[213^U4>QL;)S>DA^"HXI;Y7"T=0583XP(S +M7$/9>(*U)O2&!`^YF,)NGJZ`<M/ZJ^:AVXZYZ$:=QM./$:PM"B(O,H8?4)QI +M#/4_67`$?I`SD!ORO\;%U^1&*KL))L_:4K\/"AEM0!S7>>#WR&"7OMI+LEUS +M?#]SL8I*WTDE9+-,>^8O#0/'=O[?^ZT;C!=LH"K".&OZ@.HEBKP'-0_Z<(UG +M@V2[R7VXTLS0H5+SN.`YK9I\ME:LGA?VQ[>`!8%?&))P`]S;"'HM9E"Q/O#P +MVU0\,`CM$\U`)*-MW=I+,>_S.N+GG5R'?"R"Q,ID$4]1GL*V1.[.V#`6D\\6 +MIEIGQO3.76/'MJG@QQ,W.]H1XP\T6&-RM02FFRI?_\N\_G\P];2VT@3!&=%\ +M,.DL:W*'`50!67KRMR)<U>BRSJ(Y3RU/@\Y^DV1WL4-)Y?M8P<F>)J(D&(@^ +M`9XR%/9E[LR3J%.LM*(E`!PA_^DA7&V5`[`V"-MOZ,1,MN@6B9Z3RB&F4(SW +M3O;^-'[B'(8[^QA_@^OJA-Y>@<_C0<J&L%#]$^]5Q),2R+"RH;=RG+Z?`-:H +MS$?J[=*24B*7TK9T=[-Z&Z(FS@^9].6I##2YH:"'W'DE8NX"/0(.?(6P2PL; +MH,P^M(#4GW2!33+40@[[",0AF.,6W>;CCKO<K(`,."+D,HLNLS"(\D1JL>=Q +MX.2MQQ()4O66^K:7)(&M'=,T4O#3^9][`9XA"T7JOUJ^0:TC;3N71H:U+->J +ME%8*Y]?G!MPO>T(R56B4(9_)$AZ*M:=!W^,(8PT<>F_+[M&CR)4RW^B\>9BV +MP?"3SH2'%))D#:3Y[,6\'$6T6I^:[D+!HXCI<:$[WC&S(JD@2M('O1S>ZZB6 +MZ($P-071RDT*:@K(V[;/H-@4[_\SH!:^-EK-/*N8%'._@")>VWQ6]A._#Y>3 +M]RP8DAA>YZR[<(+NPESZFDY71+?:QN'&[NN1^XY@+R&XWE(I40)%X#XL!9@- +M['Q@7=ZY@6)@M7GBQOF%M-W3*/L4.A^_S`=C2P')IVT/P;.M^W\$B0P7E#1` +MLU)S$,EMG<04"43BQI)P)!$ZW\,<(U)RGMOC-6U*=+3*HB:!DSH(5W`BL(!Y +M<CBNEE]IA&IN.OW?>`<)8%9E3$^/)ZXP&#^?L9T16%[:O<WPZE([7*;8'VR` +M[T]Q8$1].LH<2H$&S+AYT]H1ZF<?P]'`NLP>T@&<WGZ51T`W:#V*]&4(9A.< +M3?4T^5VL;`70"*RM9Z_)SCZ5X%G^RE8NDUH#%U$D4'CV1"O'1F-;2'Z0ZGN\ +MT)S;&45_L>SA4YF[#QPT2(C@NI;G-.K0];OI(?WK@=HS*=FBCES]Z%GP/C15 +M>_-YH+VIW"DP;CV+_'7`P=+6*U)P^]5+WJ9JQ(!DQ#1%O?('#MCJE]BS1L'C +M)Y&T'H]>\KTU.\*YL'M#XX>(,TM='%\IUV1(PK_1QF"!C;)F\4,1(GBSGR3^ +M(#Z8#4_)MY(1*JYV"@[]8I<S@JO2&TG`HFMYL=*XA+!S0)K^">YEYM#ZR`IB +M6KF]D!-8?<OHETS2@_)Q">`Q$.^]`.]0Y#@YE!5-WZU#O7JU`@+[$,/_A*89 +M>K)9%+_,]"9"IJA*)KJY&$Z^7XQY(H'[>N)B>DMV52_/YC'L^KTHA]AUX-VU +MQ_[']ZVL$%=DBG_:[QXNO[(:1\5Y3R@6Q%PI#N,25?L'[E3.:65/%9W2`&H` +MV>B3.IC#BYGF1K,_ZVXY>S20:W!]`AR=W]NU[4MG?V4.CDQ-F=<<(,>I<>V1 +MA%)_`ZXI=!J?CM[GT%D`6.%LEHR&!QV;"@E_)DX5$.,/0#D'D%DFF@T\O?Y> +M@R2F$VH)&>3\+=RLP]+P45V;BTO+CKN1SI0M3B&TK;F/AN@:_*X9:F)'Z<9W +M-#[BY)KJ-GXDD*I_H\LM"!/4W<<3-@8S/).7',;+!5<CA3;7;9<<PA$TH"3- +M^P0W\>OT>GDR%W<9K"/HTV.Z&7$_VHHO'X'VBVQ^]'[3N,!0JNUX^:NWZDFY +MB2$%\ILORV#UL*`UB-)K932CO"0RO\/\E8Y1(UK>A`=ZW2NSRK,D#'RSYLPE +ME\,7E^HHE^Q<3\H?Z@@0[+1'LM0"$>1_W/%AGT@6IN=CCTGBUV*7L82U9N+, +M=J>N#Y<A^SG*;5"'\MC3[0T^5MLP->\Q_O<*!:X"D!(`_IO0"<U<9=?0$`FN +MM*2ET.TH%]T\0#]ZJ,@1)J`A9\"$-A_62E0D6I2W/5!71>$PN-*F`J!"2L!8 +M[9W4FC5C]VQ]AXL\A3NA\#4K#;F#X'5F86$I+U.O=/:50NEQ1LNK8#_G5=X) +M\U*0]4EBG2E_\`S+GQUGMJL7UCK;0`Y;((D:NAP)*S;BP(S@.91]PREZ&8J1 +M:A0Y<PUA7*I3$S-YEBR(R4=N/L2EVR_P;?>(*HBQY73L8SKB=L4GR;5[Q:-) +M'88!SRCH'@QZTM$"]$ZBX1AB3I9F3R#()8:I)(MUDGQ&QFL4S'J])[,.9"B% +MGA%4=PK735<>%VLYO5(S4'0<Z+%ME[<3B)HQ24Z[=>5">JU07+F9!=/X]_/Y +M#1S].KLZXE9[?&<['#IGWA_0R1E@+VMASTJP1_^M-9KV12E,(+'G9P$,_;^@ +MD`[>J2LT(HNWN'72WM=*M9<DJ7U-PI>,7F%2HDO%;,%FWQ2Y,(%PU=+<:N[Z +M#>X!WG/]&6%,K'VF3#V@(;S>QPQ;A9\EJ=`BP.>4>1"RN\\IZQ4$ME),.RM_ +M")"76&'@.BXR_/@-D.#;X=@\Z%P<\-"=M0T75QW'T>\#)0&S;@HONG.8X]^3 +M=(!*R%-7!>&:/RI==UZ9]7D9<Z75G.,YT>K[*E$E,PV1*GJ0FF=A["XKLG)5 +M8?:<^]1A?^>E"MIP^;WY:W^#)I*(@<-C`"@]P^2W[$97#KFT::.8E#14Q#WM +M.FS5?8@QQ@9H\.2LH$QYA/<0)S4!W:F?#Z0;[)2?1P,Y@9U("&J$M[?2GW\X +M;[K!Q+FELD437Y._`R=BS-8K!N2;.`R))`?-FDZ'3AS?Y/2*=F!BWUF^`X3- +M1P3#908PCJJ,Y!=QZL@UQ@Q*G3M0`;.(^^^`'T5HCN9QM\F%?VV;#B=;-/.' +M-T#+6`:*@[U>L:[5/M-S$O#5QGF:*B-C->/,M2WPQJ<BCF_H@^JH_.H=9%)6 +ME9/[P.$F=GH%`VS"GHZS6VD.""JG:'N,?0+^[)(^QY4##1V:FA(E8'B](<IV +MREE@GZ6LD:)M>_BQ2:_@H\[-@8^0K/UKHWD6I8#U_;CW8.#CHH[MM[:$0;Y1 +MQ%*#;WCT4COOJ3`:DUEE)CK+WW8[,I*G0[*7#%%C<6]![:+V_:S"WW%=AT_N +M.XNP8$+Y-9/S?/3V*$M[$K4H!%F915$J]`WE^OGF<M\_4*S^$5QW>1?-[ZC" +MO-JK`80-E$6F.&_I=KZY[CXU%[^\:V\P8,B^!K"MK\LI>&M)*]Z^([*G8.S" +M(S13FCP<%.';8T??Y"RX_N^3W;N+1I(5@^>:9D\,A?(7$[G\\"]XTXDZD+RE +MWZCJ$Q7..KO9AY"0*SU>-E:/]TZRN+_G=O*FBM6>3G'+Z37\6-E7KB9%VZZ' +MFZMA):1@*C5D/US6,`,L\'098G@*)-)%%3=9@.9O:Z*9""*DP93J9^A3O[S` +MAK#B5(F*865TS@,S30!:^+Z6R3R_>KS-!,R%22?6O2L2T5[DO@G6;E#QB5>C +MNA(4#*[9!<OQVO65LTEJXLN0LNI9YS-D1BHLS97J1>X"0L^M,Q^^7K+VE'`2 +MF-(PPV)H58+TD)U)`V2QNSGLHQ?OBB4#LX<??V6>?!*>1-G=]?..?<&UJVB8 +M7<R7M]\J%<$^I48#I.;5PPB3EM_Z((J_,@?I*XI\PH#X(GL<##''DK"YH;E6 +MAJQ(D!TT&<4]@K:!S`/TATJ8C(CB0?83BH'<4JCQ82^TMM;_YBT-R*VZ<FCB +MWC)N_?+(>0,=2QA'K:__LM/-2[B%VD`/<G6=\FF04(%#(II[-3<`,,1053:2 +M$>PL/M>")GD17*`BQR+:#60Y1;>_D7"O+E[\O0N?#S2Q/8&6&SD(_QR24.KL +M&Y?1[F&DP`C,AM=M:PDYM_`#_,-SD7C8W7H"DE!BG]F%DS2[\H$/S]/G=&!F +M+D[`&(9&N^!@HIQBY6=.''YC?0*?Y8?8<*+_H^'0;UL174A<\"\=*DIK][@V +M>_ELS=`+DU=MWR?Z'+F>F-1<[(S9Z.-&6;/D$-`&-I"^SI>+P:0QQ+:8[O;; +ME2LB;L,3'Q+6@"\S:F/;#_=E?ZV:KM`NQ!!6VH-N6PK>AI'6:]G)\Y@CF8L( +M?*2*84XE[3N["]:H&)<4BR>$"->5>Y5A56P/Y_)\QT=WWZ^`P>XK\![E"*4/ +M.:=[JT,I:W]A/@@=1@E_E(8LY$*N%'4+:`#&TS5Z#$>,(5M;2TTR^2WQ,%@5 +M;53)-%G7F/+?O4J:0[X10UR^'_!@ARTB]2&!"Z5,8A4#[42FZ\CW?_5=N,P. +M,@YQ3V_&UY)M`VOEV:W'4,1C#/N63J(Q4:XKM"68HR]9'^3;:`L1M3:ID49% +M-&E(L:DNS!QG"19C_TJA7CPGI"ZWK6!:OD=EV-:Q',AM4ADJ90-X^O:+OOEI +M@_#QQRNPO#<7;SX7N^%$EDDM+:ZA7ESC!#KN7F@EWWW1QCLUA9%S'?,S5H,K +MF$-+'(?L/!:%X44#"BL<K\<!'HSG^]],OTO@F!+U!9>%S=`&.=]/4N%8XBQD +M"SSV#Y#/-"O]M@8#II^JYI_-#E$$"_!N+4QH6B*I@[8KV(ABUF#!UIU3N2+7 +M5%0194!(QB6DK!`W"@Z+D!AD7\TV;!CVY+;@YKU\BQ;.S+_XBON5#%6D:/&, +M%Z!@@JE+(A8^>"BJPE'M1'N__A3\?RXKU%X''S9OTEGHJU@38TK0]6<=BYGV +M8M(H(CL&:8T/H(7;'\R#'P;2Z-6!T]_=-P^5UK]+U?X[N2_+Y1@FBO]+'&CB +M\7S_]-I:#37!N\%+0U!PJ>XM1#G#L-#3X&0<.5B`?8D[5P9-4&Y:303"K<(! +M1+^G\B/=$H1]S7'=E-J#!`@1'V]**KIV:'D0<#!=Y5*'ZNN"/J07,%/GZE/N +MM;H9\;3)3+1V]R83*$LFK9`?O)Z#GP9C1$%Q#7G/`J<"M>GIP9Z;[(BET=I4 +M`GVP90^$8$[Z\!!_D9K_.B?T^_#7,U#94(F3:K_B.=^>]V)'(&B-#I,>EPA2 +MY)2(?]H[QF;;V+O-<SFTE=$D8-BS`??Z,DS"L"SW>>C\/QK0&3IR1+SZ`-+: +M3A`%&V4.]R.A5&.N_P=TQW*TRVH%]3TR#=Q*;U5DPI:9W\4?@[)MJA>8\`=E +MND[M/Z8BV1.[L!^K]G[Q]X%<_/<[Z=QY<Y]7T!4<BN!"!4XZ]]L_+&0Z@A0/ +M-?Z=[G(^8$!GHYO2@!I\S-^!/E%*+P1&@#2V_+Q`4<G"@'4;02P<%FE;@*U? +MR^2E&?8BM(='JD""/2;<4R%J29-E!R:\#N_X"YC$^Y@=W"$3F!PTG1]H%T8Z +MIP'U+2X3#-WO@24R)2T0.'G^_,YI<>K%4+0<>%E@B9MQP8L9+.OUJO]=]P^E +MX9-<B"09B5]$42TO7V6@ZG.[4+^TE$?A6JJF=M<KSFJ2A5(O\S:!^)0%P.I, +MR+_$:>[@>Y$]1G%P:YI$.]T4_LP<HY=)R!*HB<Q%WT(HY2'_>/\ZP3Q'G,$Z +M.1"+N)2C#(F%Q3SF&6A8$IU,:>BD!XR9T]LWT6_W)P81YO"QT_&/_CP^_QQ3 +M*(OPXNWL"#0-Z(:1=U)&1G3MJBO&S*+*+=>33U+Q'U$^1F),K+*_7SA8=C03 +M<Z-WLW??>2=58-H?R6>1)Y'H$"^3?:/D.5]>6&DY&;Q?,#,+70[(6%3.Y7#E +MM8JLMU</;J,LOESVNE*P<,I/>8MP/!G7*VV*HSZLDU:(,8/<<*TCJ^">,ARS +M(WI@LHW29%=3*=GHKUZVD*:ZP<EF/XM83R#IPLSR1]9A$\J9G?5B`A;QC(2Q +M`G'W8V64**82I^J=9W>Z!J/./:]I#_QKU+GX%87+8%R$DT]C#J/:W04LLNX^ +M$YG4$@L\:82/(TH?KIX`E3Y"4N@P%(YA)B]I0#;ZV^K/TRX(LTW'2I5H-FZZ +M.9*<"<=Z,^F$8K2(0.C8=Q6(D^,V%@H8BX[)"<JW@$_0!(B9870'!'+"%N*` +M9X!0U\+BK-M-K2O+A2@83OLKG38Z5I0&RWJ]04F(M\:#H/!NS\C8J_8I7MR" +M_A2PEOG9-,7&$#JO]ZC=L\\4(>5^&\J^WHB!\D1O%FXWW8H*G$5P0&J]&"K_ +M(@[EL.P6R9#,;W8(R;XF3#N=PK<CB@U\@,A1(`[$@>?@NB/C:,G6-30$)68: +MORF/F\+,3X%Q?O)&D`4H3`Q]'<_-(GXQST9,R(-PFTL^-'+5W<G1G7"*P_3< +M=4.8Q@[#GS3GSDH\U:*0E]0$*S6W)*#09MZZ>,WKF&:15%^.5'R%<G3\IG3Q +M_.9T*."1ZT[01>S3K7_'#:[A6]PA]G1T'%6M[(NBWF1H[MLFA+2'</UQ.8!; +MLGS=J1DD"X(3OWW1EJR(:C<-*)X_])[L`$*(BX57'($&)6'&%SVN9<._NCZ\ +MC7I2YE*5K&0$GZ4:Z;?@RR7Q`.1@!**QK?&`:E"0E4PQQZ:<&+(@\\8I99%Y +M$^@X$':3VV3V_349ONEQ)ZOZ:(XU2=8_.\`/B^9<%&I6`=<,,QP_@M$-!:\. +MZ/89'6:5ZE]6"RE64S4IK"KXR2+"&$DFYRXN&>2KIWC4TZ_KWG:+S@HFRQ27 +M'`CPRAN"<O428+"3/J(]SYS4S42<$]A90Y#B7'FSL/J>B/8O&OQ#"T1"_DLE +MS<FL:;;A1ZU.UX+6F^F-N::60-B/`@7YK(+S<=>AD10[J@,20<F.;MZ?!Q$_ +ME!1D6Y*R#&^":WE*(AB8DCGA5<FA(+IFF((<E7'<HL+3X4C7M5--P,72*'%B +MTT[?!7O"-<'*O*D^,GF4:7$NJZ:OS)<&)X#SG/DVQW=UR"),!#9K@<=&;I(` +M<\`(PJ[_F0,9NZLD9V!Z>*N(2&?/9Y?@PN*AD2Q[=4>`2I'@Q0EF6SRQO15, +MHW46@"?]<8#D^O@0OH`_@..X1?)PAH;W6RJ,=NQMBMW!OUCQ=D#7F<=;/.MX +MGL:'2==R*T0MQIO^SF<#*?@!O=%62:/^(I#JDJO>BF&7<YB!@O?2#V/=YH#M +MU^$D@:"<N0-08?*;F!#5`US8B@V<C4&Z18K%I%PX>^'RX7GS+/V&I!=.K^D< +M'/&SPU%;9*?%8,7M.=2O5ZWO?80223=U&RJQ#^Y&"W$'AS1[FC)\&"(P2X=F +MT[)US;8Q\77ZMQ147EC%<0#Y3`%,_LTDWE8(YDM)I0MJZND\OT`G=W6$ZMBT +MFGA$V'23<:C!\B,#,-)]AH3A+#D_G)O->=\V<2Q*8#%1*U%M)@U/6WN=%ZN! +M[>81\K)=A4BP4>V)YB\@!IS&,0XQ/1!_MJ`^]TU.T'(I!WM/Q&A5_H-OF)?A +MEOPN[W<SK'5-\Q-WA;CNF]#5(T?Q?EW9%ZQE$,X2A`/K/<]B$'"A:B*0^Z/N +M"8L%@GO+X,V&JDH4:OC5W=-3LTU_YT+94%.HKAT.*UG5[SJ&L7HI+5`#=R'> +M=Z<+\?15=8F\TW(,HI.NG=5$V<1+[.VQ7WUGK46C6Q$LJ_@'QIL>"CS&:8#' +M9]'3GQM$31NUQ0(4QJ\=G6V&`%N//TG5J85W+I&M>QK<V7[1=*)#JLI4CGP& +MPOUC0:^ERUL"H+*1DQ0>"Y00%4,73D@S('UZ=,EXST4/2HG/S`N$?:IBFOZP +M2YH<C8ESPJ<GP-Q/E&OUHL,G8T4P+);Q)`ZR@/2$:<D<EB"WL);[6"QV)+7) +MM!$"&_B<$94JT3/N`E"@2W66KKX+>G"K7`N5M[O@B<0\@+`Y20V=V%Y4*C!B +M_STU6`JZ.+UOD7JV1P,120_U?;:UYOUV99/_+Z5H9G3EP#>7;]GZ>A>E#(-" +MU`C#%*[DA=L=B7.I)<&B>^UD2&;]9BT/]8AS3)'OBSH*SF83>JS^4<WBO>S@ +MZ>R+W&%IMUO&7ODG`F.R^3IY,U+(=Y]XHT?$];.,J6C4@@J!$8DPZ14EX)<H +M+;0WP!Y&82:;>>RRS&W/5!V=!7FV!LKUL/^2*[[G44?1$A9O>5(VHMBN-3#N +M*@<?_#&H5R;2I1Q%Z2XKFP(]2\(O6%WZIX;'#PJH.QX;U^^RWMD>'I<J";OY +M%4@>/X1Q-C1$Y!QR`7[7'4`BX.O@%F)!_WGTNH8`A#W2O#\_\=^3'PSV,@<0 +MX.DRG_,C^?'BVZ*6WBFL?W'HI^^R:%J5T`4-QZH+PN*MXTI$JA9G.)D>Z0Z+ +M2ARWVGPZF-O+!*9[5I-:#3#MMIQ4Z%N35VR\A.76#N8.F-KRZ@?7:U#-V$[! +M-87`1]D"'_(G"?K#!\O18C;-TY[QX.G_D>ZP^L/`!ZTBV03[9Z\[)OOI9IC6 +M@QI%V'5)#1[^KD>GKS0UFYDT+@:QX`QFG5*_=0ES5?RBC!K;9I[D099$M$X0 +M$;L6+[=LM8!':,>`'I29.Q\GVVS-M,]^:P%MT_;!AJG@PCZR,02E[N/[`^%D +MIS\#W2%.4AG:E0;_.1-?3^J<JE4$#>A6XJF,_))\S>OXC`STOFMT6@3TRF)3 +M?/5/<`&VZNU'21_<5AS5N=P7RSL'EDN9!K;>=E:(=CVRZ=SR2GT-4P/^`'1' +MN\3)5G-@O5$8;ME[2S0\_G`/SUG7QY5=NU;GGT#3S(H\$\NPM*D"X(4ZXPS2 +MXN&$Z+D*'7!SF.S!J7GO6A-A#05Y$__'#<LWOZGEU/U<F!3Y8Q1+T;=]4J8` +MK-#0_60#''"F^Y)MI@`KO-;?<&Q],OQ047@BG'8]>H36KI1YC]9W`MLGWI2S +M#68V"4!Z\3C70:#"*;>OY.?.49SS'L)QL>W%08'XT'3-WJG+=E><([7\^7'Z +M]20]9+1H;7=!X(`$.R+/HU.3YJ/:`EG\60-/(*7B7ATZE%V4!WN++5D:X<*Q +M?ST^*$:!,6.]1)3SB%LA\!U94D&=1Y"2SP#4J;\@C@#79#A6PIN[I7FBT4`' +MN@#A=X>Z[ML=&6:/_!W-XC.&$Q'DS!YX<B\6\<'K(OPD%>@J:4="7=A^LJ!, +M;DDQPO9>%OT<'J24L(NC4F?%E][E.NQ+&5ISE'?'I>H'T(NFKZ^CAO`[65U2 +MVUTYRTNRNU!=BK?[VM\&[V@%,N'-7E=MYJM,PV=%#WTR_.#Y%3L>Z2R%7W]G +M16X6_4'1.S*3`)3></$^X6S'_;,BR6BBOT?64.)0O*;9X0\`H9(K.71.M^FM +M#@(*`O3BO-`J\(O%)*8N8:4B!3SX0L@(3#'PHJV]Y:*\2E+"%<680<BK`&5V +M*/WE_^!JJQE18WV(@R[YND]LQ2K).+F\$H>[=B@J,K<?AFN*0A/X7"%KZK9G +M;J5*Z*-$,%X="BR24^+Z`56@.3(6S^^TG(\:_AEF(D#BCZ442B)!I&017+F/ +MVL?B58?-05`3N@]@RFKH;E#X9MR/KB-F'>-/'SH^?Y8EN/-0DWP*JB.QD +M);N8_:LB/=6Q#E'8\-P!7;\V%%4ZC>14G_Q>>A6,Z*EH4`?L(2[_=>&A8M&> +M^V7\"!U"!7;VSP-,8XZX]J08'IH;]:F`*-KMJN>U?J:+?X]_USF[V<T@_B+C +M5!GCQ[N2S^%06*.$F`"P:C5T:)3"P:`XAM5#.?(Q<8C#PI,#2?.4I%RD*ALQ +MI!>72F7Y\!IF5W&&OYMX06,J7)9$UVC..!/.6$6C9RG(!+5VS&V,(X;5H1D, +M>W&ZS+M_M>RVK?.5\"QB3`Q$=19)&2GCXJJ9FXJPN>WN1HB+!8A0DG(M4_(2 +M`(*BF0B]]A58';K?.,C00S"6L0;TC'0?&E_OQG:'ANJ.9MW@9X@UM/QL?E.1 +M)%!>![/VJLP:)CN!]S$,PC)H"`4-[O)O5?=%LKU54-/[B?\S]XM/`UR:VK:@ +M"=$XMAP`(V;;CM@`\5/G#4W87$LNO.9DLQEO0+:R2H!`7,%J]CN*Z#J+Y>`. +M5J.ZYD%!8"'H'^(`X:N>^RJCN/RI&EW7EU..?-@?PHV-^?[2T$2;N_*V_X&@ +M;AK:,B++.+<;AM*CEE0F:-*KW817/ZE`:P50]>4$JYZCNG>OY^:5;'?,WQ'H +MQ8S]K"2V?YVT?0(MAK^-AROUC/P&-%4`=OK&MBJG>4*>@W7&2/O46)T]6B^V +M^W1X%P-.M-W`4GS<-;459Z&*X5[=.I(,TGI/;?1B?@P0VQ'11MN#_BG[P;") +M%=GM*TWA-5,NSN=7A/^6P^7T<B>W1C\;;-G>)I]7^3TS,6)]\O?@)-W&3A3F +MOL"Z[7PL$,:^U"V0Y9]U6ES)4$GSU?,[R,-C;H%QSRNZ5!SP;7Y"AZR>G2[1 +M2P8(UQ2V"8^9.]<5$>G11"8E(G,>L+2)JO5A>EYK`_`5R'B$&[)Z-RD7Z>J: +MSC0?S`F\V59ICW1'FZJ#[8T_#*GG%[>#.XLDA.$%II-@,9?>S.!15!?7F]:^ +MQHKJ&*W_F*S+HA/*#J7-`"F@N]?[@B>I&V?E(JO??B7WTU*.,FT]UZW6J-0* +M"`QIFBGS;++0O[G"-/HMBP%LFL?>ZPBQZ%)_:S^T"$E$/P^![:`ICT42$;FK +M]&HN\[<6J"QSJ#J6&W/RKV:SB2":W5?B%).1U[S/H6?)=S"X7`V'%V.,I"<? +MF@>!;EA;-NKG#L_FFR(84E\><?R(,J\HX(+L<&Q0$*"B^X5W4_S&Y#;8OIVX +MDE0"'9)X:0('1W9N#>$JIQGF?E<A-I/4\XWOI"7Q<DB%RB[^!L.W,LVUO>A5 +M#&K*VUEKCWIWF!SLK;),[!L3\XUI'3@XA7-H.%H0T?7.CS$@E0PZ(`&]DK<M +M$,+IXO&905;W8)<H=]Q)&\@88*:P@+&:__V&(\GRU>GI]X\W5V\0\F/,8%EN +M-[:4_=``BY_RZ4<9;8`3`(0B;[*,K?R-V7L74U<I/I*5H*.QO"JU0:TP$+"J +MVO^O,UIVRNR5?!FKJCV9H!3VB&BP8;J%^$/R6LL#EZQ*VGE-O2JBX>=E95'7 +M_4[L`98.M3>?JL-C(B%(.>P:N$3#9`$`S7U!M26NHLX*\!&X<@-WPP'6%($R +MZ8SYP<NX(N!T1I307/!-]1AV$.)*F'^`A<"4;$I,Y-[@#B*&>XJY;)SI1Z#& +M1H/-U*8EP"/FY:E^`^]_Z*G>1`WY*Q7[A#5.&0!NB4>WT&CS_FH.MK`<WFX% +M.3AX\7X6[9ZG:4ZX`(<F*9AH??-!8FJ!MNAJ-FS$FMY,H490A6=`&U+]89F^ +MXUPH]RIQ1J/.M"@:O9LYMJ1N+E<VKU0C(UDEJ)!D_$[]M&8K6D22_DBR5&%3 +MF``[3P(*%&3FP\0Z<Y_9;ATUFO(#*?53$P1\4BI,ZW$74S12%D]G</'[]MJ( +MMMG*W#>/C"-![E(DNSUJERU;Y<>/Q">X1@5"U2TM1-8HS*(+Y8>'P0N"VA<H +MYYG"WDL1.8I1J497-:AP:&Y>9*I<`UZU9%#-VGIHT$))#^D#`4,#')Q7_$@` +M"C2]DB6(DP]<&B/GXM(R_CQQAM=!-;)V.?T@7+D[27;NUQIR+,WW4#^*XD#L +M^YDD?%5!FYGD^&D!>B.RY=!R>2_U?[QE%EZ%-Q+0ET\WV@?Q:X$8\IMTU>[H +MO75@<AI9&4Z]GT3P)15%_K:WE/9,2Q)=*../;HHO@K_HGW;[#>(,'6&)?L(" +MK5287(#EQM.IGY[\DK/&&]P-%-L&!$!_(W>FRJ_XX"KL@/E%8%MR<V=F'-QR +MU1E,Y!I_`_4;FP6;Q,HC&N[XC)*YHKP-604+B:%\26"H#\:O<<'P%>MD9Z*J +M6`5<R#"WX?7UV$LH`C_1^A'1)17_Q/)W7/L'?-=%ROEF#^8Y2+XJ^&8OY&LB +MX@V[%8/P6R9J==E#Q4Q0@2FYILK-"@I0]*WRW9$7QZY]O%FB0@P;`Q0E(5YB +M(8(6JD-MO0N(K$UT6^Y.GJ;C\SD2D[17LF#$>0LIYF^[UOF8`/FP_K(^*25( +MD3?_]JBL>17<$__A]G?);TT38I,O6U:5LGG6!-*`%ML3&*06%!F-::F8&J6T +MK:-16C%7Z<H5?,7KEKS\`>QX&N008$6N.CV-3^CC)+YC\$9H!LH9*:0_WL@L +MN5C2T0W2"^%OC7;=D;$98[G1/=15I<PW*+::C$]YVR52B6&:<&`$4A3B+#O0 +M\T5J#H!K9<7;W#3*,`<Y;2V3])5TJ(67[=R34=V8352?6H&$+Q4]S+@$P+GO +MM2^2'W3E/,5-&3`1?O%U,"/K!NQU10XK&''^=>A-ONG8?H?^PD@CKY1+C:,. +MET=^P<B4$ITU^KMEE0A6HO5:K).[6LX$"VUN39Q\$.Z@$9R:@4N?,FPUD,1% +M\;R\^T!K]ITGB66D+"L=Z0-Y1ZQR_GKJI,@*.,)*1!">;?`%6+5^P2PV9,V> +MOM5*Z`Z>I<1D*=[$1W&T:\6TZ@8F<%+V.H?D7;M)XQV9Q1%$?),#^#Z'@KSU +MJ;[XE#3#&`L;W-(S5'=3$]-BM,D.NDL2;4JL;=&*:!SPK2BB*,=HAAABCW/8 +M;&!LMI\ETDC=GY&`I2OW9`O]?!G;4!\*#W(1LMY&XQE5DB\8?/D/,%7:F4[W +M02VG844X%#\;:G`&PJ#K1I*ZEQ3,Z8'2?1-TME=V:9'76#%TNC9OLD;.A<HG +M=$P/):(4:<WW6RFQ<%N";/9VGHJ'V>DM(&-@:`,%/YUN3I&_:@#<;61O53$" +M%Z>YDFT3&JV157BO=JPJUXI8;0Y:/^5^*E,,1YK@T]]Y1E6L`3:Q6-<-[VA+ +MQKD/WM3I?+H<#PP^?7L"T2#WXO6`I`/.BY2^\OPJ7YQ&2TBK^7VP$#BZ+V8^ +MKZ[V/,6T"R?,?06V1+\,MJYQ@B>-.3<!NJ<Y_U[0Y'2K(`@B[`.<#D7EO`]0 +M9='O7A+338=83J`\98F+W@H]B.@$>D":3->PM[A3?GW7V<_3>M_DM;2"G53C +MBB/4?52[*Q^7?1)?`>MS,4\2A185?%7#D27$$+`K2V'Y@[\#Y:,3ZA"'_B!9 +M*N');/[*3!*#MKX=VK_%PZW+.LCI:YPK+Q2@6OHKBCJ?!O9*2CYT&5RE;7ZP +M=H-&-L?#,A<ASV+Z)5S6-:37NQ'ZI%0.!W8!;NB2![U]/Y^,K28P.GJF;RBB +MQHM(Z4FM.`SVECSHWS;V<,-)Z/PA3U,Q<_QCK#N`#W;:;*:TU?PHI&01V-<U +M&;+ZNI^_FD,LV;5^WE[7(W5X'6+W]2PJ@9SE7*'(8K]7PK/X3,+<*O-ED*AU +M%%8$GC1P-\^!(M)SZK'#&'!KYPZG&5N7"B-P"!4S`NL@)I9I.$^@(EL\_7$Y +M`^O365R*DD%%/H9>TOJ@,:RKR3@'6YJP3WU_:TMBF-\YM`?CJN]S*8Z&XHB4 +MWO;EK5S0-H+M0A>IWT$G+@F/QJ[9W*[=2*2G"A1<%E&S%M`GELZ`-`G+A*;7 +M/G&VVT_P6?OQJW^)`V;-K,CE&<5:O9FST!>N/'W?A%$;.,JJJ``&$ZWV2!0Q +M[^7`58JC'5Z+R8^0ZO0`7?V%7S+-4T(,N\5.87ZQ]9&>%O2DA<%7@%'OQWOS +M^>M+4N#"(18L1@@X4[D6MO`KB:<V.+!,^H^RZ0YC;8E@8*11Q[%VO5VU"\'V +MQ9[BMIN>,`P^AKL-JW;R\OPZ\@H:,4@A6%3%GJOL,FI:&%J"80`>2HX#,II* +MG!V1ZG``Z1`#D?<MF@>ONX.=P/W*;PY-9E>OX^"\[)[(RZGSS]%68E`7[8`9 +MEWWCL=CO4[2&'71MH+@$(9?"M144)^LTG$<RZ-(W)J/I"GWY>8-B`:Y#L55< +MC>N3)E1ZN1M8>J6["ZX4[F%&=&AKR4QVR$6$SU3YS!]S*[(98Z(VLH7G0ON, +M.&<RGBY!/RZH*KVV'`#M>STB2U-J5@)`=QM]_!Y'R>:`0/*8=_)4R[/C2U4[ +MI2&)4[R$].*ESBX_OJ:]!7\U<1VL8P5M'H=9^3*$ZNEO,TK>9V.,=6$1J.!* +M9"`%9GV2;=Y)8VH!Z.B%4(ROR)<DN]9!GH0&PK?>^P#C<2I]27L9B-*;"C1& +M5]Q@&@#4;OV3*5L=E:6@=BG'EB`+LI&[5[=D`U/W8-O=LF_[.\35_\M<U*JF +M$G&;&;"-JN:OZG1W%9S,Q"'_*QM\6O;KF/\F[_F3G/"[],SO.VW;F\:2VR`L +M3LBZ-.-1:]J=WND[_'A]T7([UWBIX/O8\&M-%0^BV"/&BWG<3-FDQUG`XP%1 +M]JE$I#&+]2$7\"/7I-L'2-:U4..S$WK'.B.<)6,_HZYK'HP2'M"9IUC]N[F/ +M/>$-%N]-2H.H5"<H09*'VE_;I2?/7Q53FD*X0E8EP%<AP[MM=?*?!Z!E>YUX +M0LZ2L%34#B='"LO)I_<X'F.8M@L*!8[T>_3XF_\;U3&"!>?"\BOW8A*8)A/L +M^MS-P!F;!D88QF%M[K5SB/0B.$*-2:7;?&MAM:(8HCX\?4=XN+5Z,>A3#91+ +M+J`"I*S23'H?*)=[(/4%LB+^&4]C\"[`Z`A#4V48;R1!\*(.WJ_>9T9[XV2Q +MN*/9*$X="7L)-3BMV:"SZ"UBI025GS]$A.QDF1;7]H"U64!@ADF\/,GI)>A/ +M01O9?UHQCT$1JR,6U8(R\)N=$Y*#2[LC_M4QN5195AQ?&-K"2`8GX`$B^_`% +M]C^6K_;2[TI51JI'AJ]7?<1ORGP]L1>8L3_&^WI=;\5&`71\'`G`/ZRWO5,S +M^MM$Z.ZQ`[^:,P2-FB*#?^9UB:=&H=Q[U4CC'Q8DD,R7WRX0%Z0+FAS=WT3B +MHJ,2;"]J8KT$H>,F'J-IB_R!U4/,-+ZIIFV?'*(@TD?<C*)(EXZA/9%NOLGL +M,")STHNJR@&OD]$=&+9>,W0727I1H\#2]/L8C&30XGVR=(H$I4YCG<J3O@M? +MVFFJ^`R+:*R&62TNTP8IKH7[AR;H\92%'68N4BDIL6"DQ;'70(%)B5O2\8JO +MS+AS'S8VL<=26,R<5T6X8?O:X0GU9OB:E%6Q\)??5Y]_P;)?8%[*UB;WW)KD +MC`[&BS#H#83?LD5E\`Y&?R!:7/'FR6SHH\VZZ@=8YV]9]8=VI=F[*Q!&1&,0 +M.@<VZ=9<N4V_*-I8]2^K&S[B!K*.?$_="Q$O9[)_M\^N==`:*PR-&NU"^C\. +M@`O1YK1S?/7&V&3'(1LOLLC37A,>P`3G5@&\^T8B<O8A49<,>+EJ3,\Y/2C' +M4SF^<N/VO%VWS]7SBIXOJT#'*'&0$_NN6R\%X0P[!_QXQMQ'SD5\5Y2Z!@E7 +MV\^28`W34,(/B7-&HJJHC-IS1-K)!RP0&O=:@(?%MH<1G.+-+0?L>G8FGAN\ +MF?SA'U^,"LS*P9:9#G\&26#3]!5E/C]>=6%/\];H]ODV<2%<!5ERXBW49TWK +M'GW25?7QTD1"421WOWR%!4=T%3=5?(R5QJK/FV0;X&W",A;$5TR9^5,A/5Z^ +M*3IC#P1&'/!6%*`*QDXF)"XR6K/TZ18[Z3J*QHN[Y^&0GO61KX2X&_)ZM>=; +MR\+,)%O`JYH'AF$1'!>P^IA"+TGK@'H&%WQ:((GNF)^O5BF7>8$=%>\)\;JD +MZ*%[UD.K3,:2ABI+'39,LJXTF&`HKM#WL&.*^>E`>'*CK\.K`'<&=FPHDA$7 +M$,MBI5BR.PJ)<[,AG9G]Q.H>/&CL.RUR@^?XFA*I&!4SD\/ZLL'!@"L#?@FC +MJK?33H]ZV)KC/(4!&.A'_#9-^YV2G3[2S?16DL.*W_LT+/6,&<*E%<#%P%\C +M^I>GAN0,4!?N.[^@@6#>?O(<TY$#!U\1(ETV6KCRR2165GHH6@8;Z*7++`&5 +MW^\/W3,-6C$(+`\9Q4';99^;Z#QCE"82!HQHAHG=24-KRR#+"BBEUR@5T3^T +MIVS4(7A1C4:.:G3<ET=9SK%`J<[<"6[_2^X#;K@#SJ8)YPX4^0RR.;CJ7^-' +MF"8\(`A"<J64\T2GUQVMW$QB&[3,>_T_:=F0,6M:H#'X)S#4,9IE5;[`=BOK +M3V1/RW%/QL5$P3;S_$EJ/<''[75V)P"QMH>D*(@_"5)%LAVA16FU3TPW=F64 +MT]W34DNB3'GC6@Z5/OK`AJ@L">M&8]-FNI\^N,Z05F*C!LUBTVLV\38KMQCY +MOJ$FWLIW%=C-FU[>?,`S\/$&B:-MH*4AH=]?:K4Q/4UYN^?1_E;(Z1TU&!MX +M<H>A)>0HR0+T)U($11,X"\^=T-*OOLT]*]1[9@"OJG6W4Y3!3OMCVGVER/&( +MIPM%HSL<RAFH"?,/FR_P%(&W"``P3-^RD#*6L>I[P0'HS*[R;T)L[:5P369B +MCD[C/5U1]_:4ZU`LE?XJ(2S77MN6T";]&Q\=%64SO`KNG(A`Q@^$J,%Q?<-K +M-U6LDZ#?E2Z$5)/_P)?Z@9]K^HQG(;!5#/UBA6B:KI`Z,@K80;K"1A$D&6=$ +MM%I^;SE,9,>3_Y^7/6-H73LNNB3VC`/>Q]Z>&V-MG2/P_:;8[4$GXLE-G;(1 +M->PTAQ"$_3W2P4S+EVC=G/A&^#I)XVP(N"S!+EDO#KI%9W^"-_-[WAW`&VR( +M#.@?#A:W`N#/).2I_7V-\WN2*-;R#68A/>C^J>"EGIZH=#C+48N-U].^PP_U +M;[>!2[R40P%(]^.=)6>W#<Z5U)6).2)2XL#`,X`;:?W":_OXG>`EELK\(NJQ +MMC=GZE[9!EG8A0Z;P>Z)(9&!_/_2[0EF70"JAH?!!+,PY=0WDFO'[ETA^_!6 +MA8O.A+>O3L1O38M<GX>BVA(ME0D2U^S,=!!OO8B'X*-X*E^;D#,@+_5Z3>]Z +M3*4SZQ(Q*JRJG<:_YI%KFTU)^=@UD<X=.XXWA(ZP^TKNLB$[++Q4Q:BTL:L! +M!%4+H\[DV<R$+C10*\%AK50G^,A/GMDV9!02<Q#Z4,F.-7[M^+^3L?<_^]9? +MZE'&=XKIC1;2K3X\2#6!0EP+73_,.1F]27.YV+,(+[W8?C2EC06"2I)1J8L\ +M=IA($#Z"'Y5D!S.&]L`&7^">ZQ[#^^4;H*/?G2X(7HJUX&T&<]<$&SD;A$O6 +MLN@Z(!#;RBOJ86-S-@90=TJQ>WM>%UQIDU=:N]J^ZBZ'B]F,S,2S^CLSG>&D +M9`=!0I6IH0$,RDX!"`I`&V`R37!X<8GC@.X>CHUHR@]Q68.5P23,!LC=]MX6 +M2E@R#SK(60](L-2!FR/[H@/D[MH);0=79N+Y:<Q*7N+:8E7]_^9<V,ZJ]?#' +M.GZ?F%_#F[#4<:?J3#5!XQ[C8X6M0X[2*"!-/..-AGN1U;>[:C2,RP&CRJV8 +M%RRE5&I"5MQ$Z,&H;,I;G)%1.AG.<A[TH'+,X-60QL#,)6'$X3H-!UX8N_J? +ML1]1%MT83;,1W'-ZTU?WJE8NY?%M:%(F+%?%'+]D(\!.]Q2@G/WPNC.(Y^-R +M2[$XBS7'BEIR7WT:R.<[ZS'$Z/<,<X6])<,^K>N(/(:%69P/;6A+,?0NIL3% +MH&:11#+L`.H9;6?7$T#D0]7X(VCL7]A`-J63%%'>^6W+D*ME';1!S[?Z!+6! +MQO*I3@HN[4/%*/NK^O6"0W8!P<B`"CZ*PW3G,O\P$VOE^S^MT(\@FD9(^VQM +MG>E7ETK*_*^S8H5U8JJ7'C7^U'GO"M.E,N?6;>[`DW'L+[6`#4#F[4^6Q'O# +MUB`)<J4.!3ZJ(NKR_Y/4I!W$L<\&PTI(0_DMLPD@BJ/PH[B4E2.DQ%4PJMH, +MD7I$ZS-H""H(/'6U1]CKLNI^G470GC1VSE8EZ:D[;Z$8G.GMXR5,X1WSW$&@ +MF#285+T094\;NT25;P,9ICPQ.Y9E]W$-O$<G]1F5!AB_%'42(J9KW(&YP0V> +M_NZ>+&<)-\"M,XW\#?YMJ&=$"JMFB"-)20/E:*^1)6&:=HN5X)K*EK_*MMA" +M;2]8MG+F!^XLH6^G^/I\9)YYD%7N@7PJN^4$QAL(7E'0)I*2]:]]O<;/FKR0 +M-#$O;"Y_67D%!10$"N'P8LUZ8+(B>B1EC5/&Q].<6!+!E))1AG-%L#P%R>WR +MIP5B0)I=S.)X#?97TO(7>$*EA/CPAOZS^CQO7)V9Y=.==D"[WTJ'C$UL@%\O +MB:N'BUR&9M4;N4W8OC9[8+&`A!JJ':.?M)U(]1%KI820*,:U5C'V`#'93^V_ +M[#N<!>M@S:YC!Q?VQJ+DMJ%5HD:^F\SITA9D4QRKUBS?&ORJC;I=>[=OXZV? +M2K:O84"'-5L$4=Y)8QFA6UL2$^#GK".Z]](1\BM=MF0CRV$?1667Q51EUA-3 +M2&5+PUF*>W^*QZUP`UV_P*;G/:04"FM%9UW?4,[3<AV."IT$LV+&&MMV<5W* +MG/@,#E:@1[T)4BM.T-``C,%0W,8*;8!7+[ZF,#2FCC[&*\?63:Y*CKPET9"> +M1Z6C_D<AK&I>`=P)@Z%LD_0`9@+U9[Z<.ZVL-9.64#9:\NNM%DK;4NT:$&I( +MP;[/!ZZ%AFA(@]&F$&W'/ARL3EF4TL%#\ZNMS/8:!WAHD%8X['`.O>/A>MCN +M%I7>Y5-<'3!2>P?)LTNWSBI9/55W`P"!^R%VRQW<F^/MS@-?>5Z$Y$TTT6`1 +M59LY5:R'JC,&E:^O,!KF6@YN(H!4Y6<$^<-?="AF!O77T]TP@B^T+#4OIL8Z +M]Z78W`X.0'3$>&1Y)99!9K6QZBG3SGBI@Z:]>FK%^T4][B?G;4Z2*"^/7:#9 +M6I?*C=%ZTW&`I\.,HMS&ZH4-/U*`_;S5HBV4_U^1C]'NR0'E2:?,WTZD^'AY +MQ[><\3,08Y:;'"%YKQ.'XCAM*_5_EF$,R%[B7M,#D7'S7%ZNBCSORWA=490! +M=5/A3J@=1M@K\Y5HA*S+22X8F#A6-!7K>`H8)I\Q2.$)D/?,<2*)3_/VYQ1M +MR[,QV#:+4$\$WS(Z1$02%@O6,H"BJ\_5A\I=MKK+P$7I#L^/1BR]C\3&4WHW +M\6N4;F%+0PG9GN)HL_D%%$3QG!R@3ID!?XD[[\1ZJ&X]M2;W^9V03RUPH[`% +MA=T(V\64DZ[03V8<QTD5*_W)9$EMW6:Q&JX%\W%'SF=WID@]P$I16B=5Z?PF +M;^4+-KC_!N]R:%(#<MNX=-!A30X4CQEZ9&[7UTPK'!)]Q,M5.\G$,W:T&9O; +M4\H975(DMPOX)I"5RS)9K;>VFCJ!+>Y><V-ZVM%I#4+5DP?-V?>IJ[0YZR', +M4&V;S0C.D<@?!*QMH6NI(!*@E9/0HM6+\D&MQ\XHC8O2*I9+RSBMAFBP5D<W +M4.<8;+>/'@N2AQ\#YCV*>#C*74M.S.N@MJO#42]LSQ=#\O1KLIG]E$V&9.L= +M+`,W1C\I#@#$RTTMQ#'&KS1K%K?PPFN$&B2UE`U;X/W[^+Z>@Q@$"N-Q>NF8 +MSF3^T3.O)M]I6#'8(RZXC#"M3W]_8XTB*+`-%&OE"0^]YC!<M<Q`[:3Z1R-= +M6`-9^UR/7'8/[8264;LKP31:5ZYC625;LC98J[1?SBA>M7-[1J=TL$V:7QLD +MB%!WYYB/*G8A-Y[5=MF-!P*0?&&;+'*O6`.D?7*REAZ#%E>+[EA0#5V/GZHA +MOQ>#)WL*7DP)L\R@51E%--*G=PB+X"S,_AM;]UPL6:#]E1S13UQ[0%.V/WJ6 +MQ":<?*]](ZZ8IU>D0"M!0#+7N$BU9TLJ^TO8^>8ZA4=JR=Y)@D!E^DL_5C82 +MR:'T^*=Y?[W?Q0[5I::3O+./+.WZN\XU;)=%:H8O(E60(T1(R:DFH)IUO#.: +M?HRU[(WM*;27?JZJF'3LT8<>+NB1P3Y`1Z]S(9W4_\K>=1-T>\@'W9AG;YG2 +MY-P.*PAG=M:G4($Z]9<:]5<?QS\Z#Q@+&<H$F3*_648VJS0-("]0C=)/YY>7 +M,D0+>,C*_D6CYC&_Q][)S1/5O?;BX4<Y'SP8*PE01>DGF6Q,'$2?>_;1C!;4 +MU&`M3$<.C4Y>N^;->4RL25W-OB:M;%]9TH-Y[^TJCA<V*X.;9/ND+V3`N@)7 +M4G;#;IBUN*SJ%(9]<V2@<26LF3';&J$UAK-J0Q+)<26M`&\,\>=3^M5D/*<\ +M>VASN1__>.]TEV>A?'LM7S(NXW(%1&WDB9U;#&XS6,[:OO&2KP:4I`:A\4IZ +M?AWI)S["`0F.A2.AS:5=1HOJV#.:';B+$&E99G,7`W#]*G5-'7G>,%DGH<$Q +M>N)4:1#PKURP&XS6_UI0*YG$<IAK,&7I"JIWQ)^2T:8?A$(BQ++Y?8G=-G^Q +M(94:0\G!\[S(LS]OX]CZMPI_:=89F1'W@JBX+Q'[#&2/BB?Q=Z\'N:9C\\-I +M,W7SUQ?(V08E!F=B4C?1K?D?V]:V,N.&[7,D;D6[YR/2B1OY`3$DCMQ[-A,_ +MD3`,Y])MHY$^5J`*@B&<JIH/69N[>WC"^M*YMY??B3QK5C;,\H%B:EN#Z7+* +M=K$C"3C&Q5VN%V+WNTTN)V85YW>B)R$4BS3&<I5]/SQ1[*U6W6?"WE#/=]:= +M-1[##_;EO#?@M,KHIG`&:.:%#J_8$O(J6#BT;@;ZSQ?5/]E[H"9&ML3^\ZBS +M3D1!L&3.T%$X'4/'3&SVOV'<3`(.<:J;GH7`@-?JXKO-FW3_W:KY]A63?@+V +M.N@]2/FK=.J4`9XS](>-@<7MD?HOK"[2\S,K3Y]@=(O:1"FL;/_YAR:`L'.> +M%B'Y+*%`TK5B`73+Q0BS9&#"WFEK17#;^6-.\@+6>)2X98;I[8"[=._G&[3W +M89>SKYN/*'$U0`\3.8E#48;Q+1"#<P%+YC[P.G!>EX?8?).S+=1"=4%J(#I& +M2M1U5)@"J]XSI4OZ$8?@04:U@%7Q+O7>#&OLV!+'5`5^+31]BB31QLV2A&&Z +M.N84RGL\^,P?U$V@)BZ&$ACE@9I=\[ANON>DM5PVCI-6.&\N#-8CP?<9I8R] +M'>]`&?LHT;B')E\)0*7QZCPP\+_Q?G8Y::&D55^;M7YR@-TK;0P4G_%"^K[V +MD+G,RI3(UM6QF9MQ,:V$9'6-`KN*`V=8#>%]6&`O)_J546=@;O)U<-*^)6*D +ML'IAM--*-/!-LUYUO0%E'DGSFQ*_#_0>1/NRZT'Q.$<$F*>A5GZ_E')M;11` +M8_%+^<3E[FM:]!<55?XU4UN^+U;:4F>E&>L(U86*;*<9)V$BW3*1YKG0M%,# +M\K*'HD]`F[P.3EN18Y[HUVM!WHSNYS:TVM2WKN\W+CMVFZ,29<%+ARV-;B@J +M_RE,N"FGO/G`(?.K$S\P]VXY%B11Z)?N+#L-KR6EN@EP6*FI2)@U1*U8F^N2 +MMH0'`1(5_%?[GNQV:AHB5FUF/;H/]X#$L31LMH6<@67!S4+F*1<@W9^DAY%J +M];I%!8'$@"#JZ<H.1ZR.M0"291#"60F>L1I7OA=J7=J3(K3A^U3[#BW^*0^# +M3PG7S4JYA%!SZ=TZ&7@1WG0S<YT1&D[OJOK4Q_MQ3.[W?FU1RX,@F4UEU``P +M]7#R$HL33SO8VO6/->BX2.#PU-V_0P9B/"S8&]:B$WOIUI09^3!BR@%^K=^( +M/<9^UR+*F.Y$DI5DA<6G+1<1Y%-S;&)_)>3#%B2#E:?5@K^)5F;<#IS.:F=8 +MQ(9$.4VU2S/"86LWM_&^VKLG]<42H*.7PS_B_&!SKH2)RNAFKO#;[#E\AM*M +M=ACQ?(41_BW(+)M][@ZFU3__5(G=ZWS`K;4.$<('O1'1P:E2?8PH/+#DOV=` +M%X]^NB4*[+_(3JK@0ZQP6#VX=X2@D4<8.9/I"?-=1MMO[1)&1`A]W^=`7@Y[ +MCD:@)+S(CBSB<YI0(P"_WRA,C@&CDV>V*W!M_23@9X'-*?PV;AE5R=*X>MVS +MS14K2[H[PL)`8X$*O8T[^M#WAB4@?2&VTQ&"KQ"^U7%-H!6$F7"^Y'"39#'' +MG(Y9C^A2G`2U"\0E\+$AW/:HDN@[IAB$MS'%,3[`KE>]\',HMU#,I3W=4'%2 +M$XG94G?$I&P@9%-^:W%V%+Q6LVQW4#)='_NVG8XD$C4\)XMHKB"-,$3SSH*= +M7W(U27/50X=T]T"#PF5;_.<*L'/Q;:W^ED\3_P&RQ:20TC6_S]JD8:_'R[,6 +M(3E:W68/0\*^6WXVD$A#R4I+H3/6I5A2JX+ZU\_97!,2+M94,E:NLN09E'C2 +M9C6<6I:"M7<<"!:.EP#%]#GC^:'LV]%/!O%5U32AW,_PC3PMGREA?">T9JYJ +M`8>P0P#MB54=T?H")G@YU%J&^7(0US7;K51ME)RN">X3(C]KBF,$BP^D>5?@ +MWBH8S^Y4L4X87^\)(_7IR)7U?(#4]JA.A0K3L&X*?063T!L2R/Z\IFU8M7Q4 +M//X[.)YZ[!U&5H@87CS#$3*JHG0UC8H[?PZBS;.W%1P&W^771LC*+`/E61J] +MN<F2GFZ#-&;PJG+8VM+KCRTSPH9<RH@<E%W;MX6C*P&&0RZP<#]:]78O*H,X +M&<W3$/!!_9CM><J]^Y%$PV$>>X_="DO02.0=>(/_*EPXLUIC>#4YBX$DWGI_ +MSTI_'F`7`TR-BHQF+MCP?8E(ZJ%.2Q0KL4A16G<2&G'<=J[$L!NA\_D<GNXL +M.`3;0[#>9'J6KF;B%M-@*&UBNFT`6Z47_P"?^;,.4DP]F'^RAC!$=\N7JP`T +M&*+GSG;&WYYTW'N_`RBNDA0HKTD*AQHA?]H?@.0M)"\T(7O9$1$@E7S2";6> +MPN=`8&TBFYG8F567%2JC>@!6?Z*3*16SBQ)#^-IDTC9&I9!0S&XTA%YVXH\? +M/+/C$4H#W'=I`P0A0P-RJFE;*KT*MIC-R@A06/!!Y)NZ`0%,]_PSP8H5)I<[ +M;,.KGW,2?)3_9:]VQ%"91?[KC\VO^%>HF&9:VA/J.(A8NF);=K[MUN-6[N^B +M"NAM9LDD;_#\#L!UMG<"\(L<8_0>C`:Z?GB13S:"SRCX<%11VP_4V['3V'+5 +M<:-X9`JFD`TZOS3NMK&2@X=/]8'[DGQD6:-G$L`GM#^@6ZBX%U.AZD%ET)^A +M-@)!ZF-)P';<6N6)LH-FW<^$9NL[9EA$W'^$=#T)3/&IGJO34,SVF+;W`S#B +M?"EFBP89I*Y%&.QO;@L8T*R]XC*."!D$07(*(?A$K')_.XMDDX590RF(CS4U +M'3HOLSN)%\"=6DF4GM!F/<NTA#Y<FZC(D[<]`_2^-KC+[Y*C80BI;OBF]>I& +M@<8GS&U8S6%EP<&2E-WE"[_WT3B-&BMXDV'+]'_2^V(KVW6,X>A4%'ZG:2S^ +M/'I:2(\\7!^`(XRZX<FW*SQ>GF&>$ECF=]1G@TR1/PT#3_%PK[Z+;[$$WQA_ +M-E<UZ'YBW+4Z8UACZ8V)S-2]P$MC\9SV3P(6OQ-!G`PGL$4N31:;)58!7`8X +MZ74\$69&SUHK#,OG3Z;;4*YL"+*9M0":'0G!EA#FU@#B[_)Q#YGY!,F%`;J* +MNEOS(#->2_A8/O[XA&4,W8'N[YP<M0P2DT2GB^<!/W=@JSTV"/E0<<)1EU5O +M0;XL^DBEMX`+'91@>1G@4UZ_9^9??VR0.AY05Q&>.8#1EV6^IF.,K:1Z]V`7 +M^'X2,"\:OBA>R/BM]X301P%T8@C:H$(>])/J2/VITGWA,I[K`W7G6M=DT*0A +MNM%'=6IU*3X"?ZU-FOY\DT-=?;,EO#.8T(W:*3Z:-?0(<>@ZU3<J:^:G0.0Z +M*;E?.:F0)>ULM/8L:JI2T;9CT5("GUQM0LB[J]`]"=3HC(F5*'<ZZ/AM<8/C +MV60A^P9NAR>0#!9NISI@<R/V,.DDA:`GPJ)F08VY:;T/16BK*GM]TCS\=LM6 +M)2XE<B>G0.:!D7"_@P'!0!Z/F3Y35AA396CLG7VW692]X_135/O;(&%)_G;6 +M*8,%7([M(+ML#&&(NDFUTOJ"B.:Q;F/K'%<%P?FQU4A($RLUJE/TI`_4WA*\ +M=*QM7"!6<(N>H",U+B'X$.+;E$Q;OQHUG1CO2'U//S,UJ_<,%C"A=S&P.N<+ +M('ASP>8B%^2`U$..`RP6D*=12G*2+<',P-BY'0'72(E(-&8)LVD)F[JM##Q9 +MAPLS")M"V-'.#*NL_=R)\Q5L`@,S#[->*L8(0:5K&]G)(&HR!3[*Y=4T0-Y9 +MBW/.[?+4DP`#`QEO07O+@@+QW)B.];$"+36PS7V/?0+BS&NOC+<]>V2'30$D +M;M/5%J2J$:?L!0"S9^H![*?58^S5.943-.G2:Z_:5H'XFVR4WWNG(*,"R\(\ +M(P=-C!N99.C4>Z-4%Q2*^SQQT`!6)ZZT!.4JZ&X]"08D;J:))_>"[^I9#F/Y +M>*A$ZX/G:1\+9L4ULN91%18X8Q:"L$@$-Y#!G+UCO:4BSW("FM)LQD0#.KA] +MW73#;8,I$\\XRFWA?L%"&<\]:([O(A0:GA>#@_C">8%9EE0K@6Z_]O;=S_:2 +MP).^(/.(I6_?A$$/8WH"]WOF[Z%,@R29*RCIQ'"+F%[!.Z73*NGA7V"][WD? +M;[JA$!#:N<>EIU-S_G$7:Z_V,_'YF&)\]N=/1@;&@VMHFP7`G0-2;/>1J:#E +MDF49!<G7"\3\)2X6&50@`(;Y$KS'R7V=W=.%G=3!DITF*#TN7@ION)>\G!\_ +MUY=5Q<"3=@0+HFZ"75*(G<]9UVKP*I(&`W[5AB<68WA)*VQBP.3M-=33QHA_ +MV4/)^W^8#F+#L\VBF6B,JI<XGX:T92O[$`6+X?`RRU4#]!5(3]][:3EPI0^0 +MPQOYAWA>([GB='^J5Q7<UO\0]=0,5L*3A=.[^?Q!WN;EL.UWE$&Y%E2BN?;C +M0M-U!#WU1"F-Z>U=X\@8C=%I>YD]GZ9L(*C[*@HV(O`$G@PZYWCVPB]0?_*H +MBG++6Y]8+.^Z`2J``2\<>XC_)%[#.P7.[)PC*N=ZIOX(`-O?9W78YGJ_&/`% +M9&NR"+(7)".^@,6?%"EY+"^II)(_(#[3I9CX_\K/+/ON\H9,A`^V&X\A-&IM +M%W-]7@,RYG5*16/G,OL1FWCO'O]-?%"J8`>74Z&*@P;9QAGUVSS$!&V/4%?8 +MM9WN:K\C%,1`D5LC[YSG9&R)GN#?)Z-,`5M.(*O.3\BX6\O'QL-A!\UT.Q.Z +M/>V8$Q-;7L`$7*Y92;XN;4KOI=?6\G.3PD&U8G8OM2_;ZZ@G,3?PX0RI@5[Y +M#\6V&#LMC+,&@"^*Z-C?<N.68GZ$F)-X+JWJ,:@6`6D01:;2"*T$1.>)?$ +MUH\-MO/D_Q_I(>-./D"$+XS[CL\H&:[<);3XNZ5YG_8+,/V?.M7:RMN?(LS. +M<%:Z8.[2S_@IT"Z4D5X^"PDI4ZNAP5#V_/((?\`-FI<R@5JD,K!.JC!V2?=4 +M<[F"7`8HWA[[?97X2V/$FG/H?#XR/01(I_&BRB!84[`MPE'$&DW\%74*(O_( +M_]K@;Y#MW9PDJD=>VSELHQR6GG825].;ME;4K&:%10T+PN=L*)7'$-D\3MTO +M^3R1J]<D+_)PUV%O%8S)-+SX4VJRD,M:#KCPZU@'G_PT$-S)Y/TI$<OB3:D3 +MMC3Z)19;W^^F8\&L3O!?IX-+8,+`ZM=V*.]!.%:'"5_,359""-X:L-2W9$*1 +MOS,,<#1@V4[Y$J:;T``U`#O!_^>3\T;_)XCB7F"@$03#@V6FZMFW#@:SN)`G +M0TGPH$4,TPLU^*D*"$T2(YO1L5G1P@0^)H0/D4%WZO!1@"/#T&HD2+MWY1"+ +M9C"5$$N)NW#4\N%W8!`U4D-HIRZ$/R)(N]AEQ<KF58S[\U-$C3:S$%!M0AI\ +M&LK`.D3('O?6#49I$89SGJ&R[,[F:H#6VUB;\!#VM$QW*D&'\F#G2(J5=X/6 +M"X53YS`%FMX?P])D2*]77:#^#\EVG*+W&)*A6%KN1<F^F3WIJ<!4>RI?B%\C +M74EV0W\<3FN^`E8[LT$+A`S6\H%!?0:@EQGO0RG3E.O;?U$4O]?H]\Q5>U_0 +M1K@]G35FWD3<=I*3X?E(//1Y>3$,B<PD\4HCAIJ2CO4RXF56Z@X-#N)(ZB<Y +MURJ6MN%;:=<]Y&(EDS`%'"CR0TB]L@=,+[DGKK&ZL<4!E=)F@6+%M;P/\ZD$ +M&I$%Q8WM>M*Q.NX=/,92R?GY5E\3-E+18Q_`Y3M&1CEFI@7',1&QK"GO>OJ; +MEZFM];HB\K%=NO=TT[-<>!:P`#A=/!6P`(552([ETUCP4SM*)_XRJ;LX`.)M +MH`::^I+&5J8*!>SF[>:"9WH!O8S[F[1Y8PEZ5S^PTU[B1$H@5F8F#(+D"=0O +MW,%)^-M5P')S7/LA)S9-8I-X(;U/ZJ6$VI.68=^)A;BT:^X-H;?C;US$2]J4 +MN*<-ZS8C?\F[@%X6"8K<(J+/CA*&N3F\KX*!;GMN+-;_';;EF97=2[Z6@ZM2 +M"7$N;S$8*.>_5WB9<#)1&-16*,!\P)-QN>U`2B)7J4A3S@2XL(9I2R(TE1"% +M$.&4>1F,HG%2,[)C=BG!QB-U%+?58.23"]0!!X8`%A\C(Q8WTQEX"AQ2^.[L +MC!J%$_]GG1M-'1.('=MW-Y-XBYD9<NDCSD*+,@01P>/KQTK0:_AS/.8VG60& +M\V6-V-NI*+6%)NFF&/^3DNS'LYQWBDA*C:OL@*5V&=:AT[+!1\O\2G2O?A_4 +M5BB(<1#<')GJ#V*S7-DMJ*@N6B<KV$B<WU(@I4.U&"BVH0V&PI=)PH9*>/!O +MD$]@5;J/=VH6-%%:^D$CQ5",ZD8([BU`B@ESZOZ:TL9C4!,?]J356[NQ<\"D +MNW^Y?163@@XN]O7\AZG(*X^`[RD)!X/JC+[9'/Q1%:"C"I\"M'NSZXPFR"&P +M)N>086/`H36>>UG_MASH\ON,5@V?6:;F\P?4[Y^02+T+5*K8!A.3<*:&$Y;2 +MN*R6XLQ0K3[E'.CLRN/$:PA#%?I:1K;;(4N@#JGMY]>EF1S-_SXM/AK?V9=& +M%Y5R5D[Z;9U'!HU-O.,/=4?_M>MGSO`]`H!-*/GW2[B'1<J1U%N3]1XE>H<0 +MS^Z=HL<%W5I:.D,W:#2B5-O=(0+,RQ<?X64UQ3[Q9=!$DT(R:76&U,O?X2MT +MVM:]6(*V[`89>JYTG"EHL,V+MX,?88=$7(Y!K7/MGS)>C3?>DNH@N+75@)Q? +MD.G4F+2&M#@UO>+>QU81>?IA9#($2\T?^'D9Y?DA27SCQWY`L!VH=FM6_ELN +M14BF0>=ZU&\*?"M'N3OX0+&UN[E2/MAX<3Z64V8>-PX@5/BY]2D1D!.:DT06 +M1?%GMS.A667T:DD,S5?5<+^UC*3.:ND\Y+V5WJ-+&OYP9FT+.5%\Q):;>_E$ +MFWW9N!:SZD,C:PZ%Y+MU2`R14R]G^B>RDA7,'Z\:AS+*PE^[$ROGAKQSTT*P +M<)7]RGM40]:0V2*/3Z2`&&O:]\?K0+(XZ`Q;L#8//7D$;T(1)D%^D.PW1[%X +MQY&XS%_44Y9ST(9-DCT,B](L]QY#D\(NCWW$]>%)6)3K>I89A0'2-_B1I.;( +M&YDQ!PJ++U:`D\IPK6V"&>L:V1+'P_D(7LPFK"0;YW"%T4DT(]TZ1((9W=D5 +MTXAHH@2#E]Q@K,3:A+`P>X;0+&XN?@KJXKY%4)(!83<0@\=C`;FR%'+<6F.\ +MPJ!EMVDMNCU\ZUQHL\A33#H.-@LHF`KB&E3/LLT"KU".F0Z'W8FNO81"*U+D +MU3[VMRNF6V4*\IWA:`>D5@0F30X&<H>!JPK[(O<I<4!OK5,H)%%/(E6U"J'V +M^&-+[I&$V$.A\4LABD\2ES,O$JZ!2VW:M7./6)QF,[K\9?BBF#^8P,[6B$%` +M\@2Y:'RLU$UQ7@,[^@NXC1AG<RP_'\@6N(MB0'DK3*DHLY6N0)#^I*QOL-*U +MK)\#_^LUX\]=.'BP#Z=S8'FBZ^0)?8``#&RW;(M43&41B28";&]IE4GM9.*I +M.S%I:/7!3=/3FW0ZQ8C11F;1IV8E6A0#AND-L7.2'KS7XY3E=G/B_CDY?%T( +MY=AL&>:?6Z95N0XB@2?X=1$X&KBZ1*>[M0,U(G$#=3QE-[?:]V,&Q(_OY(T[ +M=.[S43>V1IKY[,K6$N^'QQ/GLRH/&BZ<B2]1JY4352/I,W`,*K<>>,&?R7?C +M>:`=N&1"=Q<#LI/PA7<CQ^KEL[/93$Z--S`.Y2\_XG/@)?H(V!'H`H[[";Y[ +MF4&UIL?R-,WFV`9(!V=4<%MP_*19NF=/K+QNP:7C[TJ8W@[XP#($5P&[@>LM +M-1;>R&[_TI_S!;G\N(]*-1^RF$%67'V7D5Q5XBN"^X$LJ3G0_+GO,0VO^W]@ +M(2=U][/LXE74!(\_-2/5BQJ.7?7+?Y;Y9FXO_4>K\-HO7OK/6%:53R(A-0F, +M'Q;MM3,%/0F5<S+754,BX63`"U[KPB?*AS9>&">"2:X"?\E"6?%4\P%U[DX5 +MOB(0]B+F![9*L/V7IJ$K6+J\P@(JU7/I[T79FPX#?U(`F.F%4,762NS(;W=. +M7&5+K:G%[7>\2Z/U"U7%T&#=MV9E>!P_E6\326X."83\NG48>05G=R.BW>0U +M1_I_+Z)L'ES%*.'`B^,F'V2^,G4O%!5A*VM6]3B@@_*^-#'9>UR=VF.??^FI +MB`[AE6CW@32BBQK)W74'SINENS5L/<7\F*:JA)Z?#E$=FN@!%!6X;9S(9AP% +M[:'(-HAE;=`SW/)HK&DF41X(\VO_R_W+PB'SX\6]:VVE$FC",ZJZO-IAI^NK +M0=-%]*$8I"_E'7*^E&_@]Q'$LM_\/:UWSL:.@50Z@?1"AJQ;,&1`SC0?XDXS +MZ9`#::1;!;]),PWF,L`B-\0>,B"8[PYD&D:EH%.[ZO(BFB)GUN@HD"IU44:< +M=GM*'F64V+,FOD6\:FNL4KF&C02UGE-1U[7MLQ6LM^TTD8;P&;ED9L[E& +MU]%+@2<8RI3B2U5O7>35>9@""X.;R90PX`MTY-`,L;E.LN0S;B^&_34$@.@J +MY:'Z[JC$CHDJ?MV?1B.&JU)6&^Q\18U&#$DSJ[]MOJX5,NE&X96<7+55L*@T +M^A+7*4BM^IQC0,X7<G_D_A;N#HIMT]F_9ECL`SPI"(6BZ)A&.?*H(BHU_'>C +M-FQ^SVL%,!L;8JOSV!*S,DR;@R?W5N.L?_.TF-%26ZD,"/;5'"2ER(FZZR;, +M\!L;GF`FPIX=ZR'G+1EBNIFI'7WV<HA#9H"^DS/Q&RH$L(AZ*<;16O<1-8%J +MRRYL2,Y.*,,LF9.Q?"XE"J0#:5K19)^Y\F1JA7J4<N%F=%&>J(_H`:2LB;6W +M<>ZH/T=5&0*W0#M*7`&Y;\9+-9<T.7*"VV<&<*LX1!SK)\38*W;X);%5?6LB +M84^^J@+-Y9X>"#P!<R-5>E.)FW37D5!J,!`;AK-M[SJJ%+&*R[&W@J=]P6@B +M9UBZ15>;[V8S&@/OU0Y?C*8TLF0?\]MOYK.,#G?:/KF3%D9A@%>DR[-2S1:" +M+?T?(<;$+ML$`\EX+Q.+K6UQT&!"AY`FY"_YUT+B]3^_SN[OS(X<^VPNB<^* +MK>?6G12T!X/A(@Z&K_PE2ANV(*&`[19?H.#]"@7Q(FL$.Y/B$VI3S=MXW8)I +M%UNS,Q8V+S.SO=YSH%YTW7,.Q#R9EQ\$U7CI`?+<?+_2E")%PY3TY3PRS<([ +M*(ZFM!Q(-ZD0>C%L`!)+'31[^[50\+8JT7IK$]A3>&JO61-E8;72N`:&OC7L +MPS8I6;NK#?/S090WQSZ"F2`8::":U55OLTA"[D`2^%&^!%L\4T5`/,PPF,QY +MR;6JYG1)/+^=K950#1>Z#G)&N\]Q`-:>+MEL;9'M=3^H?A-GY8!&8-*3?W&[ +M(5T&<\^-U($.7HZ7#D^<0'-T>S0)"&IJ+-,1$(B15*O=BH@$U_DE33I/B^'S +M1[0,]@B>U93YDW8"-:*88,*QX\K`UUSN\)LP!.1Q5$.S\/Y=BO#R>`5L=S%$ +M4$F*JE`X)UN%'_Y!';!6\"A:]1W2"^HRXZUZ<RDR!>,96>&G&-D!9-9TCEB6 +M%D)F.S"!M[\!:\U)QP,!%8&=M`,*>_*9&7"#(D##/@D3:F8@6WB]"Z*ICM0J +M!YDR%I`:B!$BJ0WH'6L#%0/FK&XZP?4CEZ9JVRM7.J9)L6$$V=$5\*TT;X`\ +MO8?T:LZ2_C?!CVPPU!7RQ`XOT`Q0E[I%B8[R4=K<8`]UJT%:PE?'WF=OG2EI +M9XC*$WMYB0J],<?3H$861[>Q@V1163_)0OVP+P'9,-(1DE3AWQH=`#[&EH0X +MBA?!R]TQKHY2SV\QO[V!Y6^?_$0U4[Q>L[G_1'2%M5GGO)'[E9>F]>D#Z??N +M,!(D'_'.64-ONK[];+LV/!OSXPR+@2)B[@$G&2G+3ZULC$B63T^>$-,(DJ3E +M[MW!62(A?PD4FR?L7961.ZK>I.YN'EH#T%]C>,5?KW-Z+'41>WW95F.F*@#I +M:$#6(&@SNLC6)A7=DA$D_61P9)]\-HV2[QOX1C%\V1X*^Z5/:5"'G1GD([:2 +MN9"8_)&DV#$E`Q7N%8:4UZX"DDZM%RJ:<899'S#16U`KI#1RU,TDK,E=6OZF +M;\:7G,Q8.97]'_N;U*)U1QJT-V.=:B&0;%^]C04#Q3]%JM)$<#E($3OEY5(O +MAGZOAU+8_M,Z8>XT!U08XBHZ19:D*FN&M#MXLSZ=`'L\)W%J?39!@STU=US; +MG.7U.`2>R9:+JJ^CYUJO>AZ##BCA.:+ARF9`?:B^CO<QA@OGJDJ:/2$HZY`# +M"BJ$QYPH"9XX';86TA8*[L'@EZXPS`C?AWA:O-I!(E^\\%Q*!EB(@QC9)0)L +MG;H'E-K%\I\:H0R34KZKXN>5_[HJUL[W7R,'*Z/+Y7_U/>`(^`#F0I6$&[&W +M&IRR9KRP`>4&`?]G?3J)'K!_C-M5_(2`%,:/+ZUYY0U0CK@;CI4;/./JQB.J +M348V9*.\.$IZ9^EJ+'8\#D1H#%?I\]R/.#`$%8BH-U=7WF3GW$?F=-@V^%$* +M3<DC3];Y0E/8Y/7*%?V.,W8[49?DWG_$Y\:L@O]_Y3<2(!YT]@EVF[I]KRV% +MC%Y)T)??M-X#TZ;IHM'.[.'>TID[*V_06\>9^``RQ";'4F\>#UNF];5&/'T' +M42"+6;6VO"#ODD^VO]4_</2(`'/(2PO_L3A:!<61:Z0--!M`3=_@<O$*V<VR +M/BNK>6FH9GJD:+)WYXT&=5#?$G7Y11U>9Q=U+@;5UA2!3`B\X9L&XKO09^M` +ML*M'4PKN-_U^.'B7W239?OC#A`Q7R7<C=]%H]T/0L)>4W\.<V_J$+(WO8C_Q +M1.955$R=RD.^#X[W^=EG?,:J["%%_0_A!4];&A?4QV9<J!]_J'XGXKTDP8!T +M+U8K^?;U@Q96>-]!`@,%-I4BP2Z\#1$1'$P/VV?V7[ZJV!J]"B-`->>9\_)1 +MDC*X]<V>)@B@EY!KFC^G6-_(8&F;[PKW@#KS]L+Z5!O+J.4;68[>?+ER-(P1 +MH.+^DY,ARRX1I-"9>DL^QQ<],391*@YWJW5@1M0FXA4@;._0M$&MW:,U$:!J +M*WZ"?6:@.T\*C^HU(LYHL^#],_N0')(N/L<'LL'/;W58B&U3SS/7<@'XMLAX +M#6P*1;(_:[1NV2]L@@6T]DM,1"*BUQ1#<:O-/]&1U1^(X\>K/G[8L*+@1]B% +MD!_<GR?.IDI>(B:8,12>9AVJLTNGH%0A;#'L-`W.`"DJE#=<P$=/<*4.%4EH +MF60E`3\"'Y,_($::>L3E;8SJ1^2.'7/$&RXCT\]#99QQF8T4"80$1@+/X1K: +MEQ0`FV.4#3YI)GRQ4:1)+RKL1ZK=?@_$-)<BZO8UB<6'`_35?!_YF_JJML.V +M<(0Z\+7_$3&WH?_O,=._V08OECS@\MIJ60-9":080-J*N@_,B&Q173:A*7-* +MT5JC*:WP?!N1A1)U`O8GV$N[UO961>"8.07'>[F<;4]-*QE/UT&X+_2J;5H+ +MHV>;#E5[\<#*[V<HN6`]GSEVO2)N>1\]5[(+=/E0H5G]G>DR+[$)G&?<'?]( +M@'8;H,VZU?^@UB$S;J>(/D^(+/W?6@!G0JX&:?K#!PH-URI#6>X''ZN$GTVW +ME,6!*\Z'>7VZ5T[9_L`C")HJO3=?=]G.L11!@QW'CJ)B2M8Z";2?N;WLY?^; +M-N[G?:MUQPD-@`R[')9_K:3ZEQ]GTT[5_E:&-2?Q!IBU"DS5'!#M_IO[;0M3 +M+EUMZ>ZB>(ASZ\0$*BS)XO.WQ`?7%)0R!DQ3'E94D/MW`!?DGWM-G`@N=\;% +MPQ9\,H_OW+]_B,#TUQ_A).S-#DHM>GKI+BK*V5&F/1-'O78SDDJ%9%^5X-<A +MY8%L$&YPT/:D$'E:"43F0&'H:P$$)L,NAQ<#3$_=<"7ZRJZ9Y$J=L3<TZ9+\ +M_7QL]9]U\[+G_<+)]XB7D)#41OM0E08BW-,%(6&'S>Q*-:^<245LO2"LKJ3; +M\@G`>O/</GT.@:QQ==EXJYX@IU8*XIF8$(>ZW+41<DKJ!V&+]$FA)K#:>]S( +MG@C'QOC[)0X37:"@L\9$R[*>@Y'F1.6S_I6RC7W!>X]5[:,-.[OV%MLQ$@DW +MCZIOEGPZ4@*#GCUPE5(16[2<>:!7AU9R%XT&#N)0:12&F)T0Q\6B;J&O_6RJ +M=)V^'C9O1X5^H=K0P3V)."V%S%4\14OM#W]KP$P[RK,R#U+(*M7*1&W+TK\! +ML2!<_A@],=^AUZ$2.]33]FYG<#-T0&P_-X`1Z^9\[WVR2]>>((MNCZ$2D`QC +MPH]64^=ZS.\`]JM^CG(?%U'(`?`4)VG!..YO>#`FW_I73>M%C=%#"RLKRBD4 +MJ/Y%K!,-_)]&/G&E!IRS?"S$9NQ2FL8\=Z#4$,BS]7"_L4?J>O-B&@KU92@] +MY-`36YUG=V)B6N9<&(:)OUJ>$F1BMIZQF[>]"#WI-6Y@[X'_?I'_T_EF7S>Z +M@CCIATJF<78J`&O]#RV=>KJ%W4T$>GGMS._/(07O`:(P]2-X:/@33S\;_:6H +M0`MMBXI%`-I,B)9N[4\=N)X2.C"]I7\VH(.KP^68QLRS,-T+4C27-P-C[U(^ +M5!SQ.CZM,[W5/[^1[&T_+`Q"2P-61$C:Y<M,F_[+)=,KB[3-DLZLJ$'!Y:=< +M@8A"_@5<X-E#C7ZUMW((K$)E-M[F$1-24YN*@]W9Y\]L0)4T>+]O3(^*!-]Q +MWS#)(@B6"DZ/_:2%QG5R@'`/53R<*&-UF\*&:&A8F<6HVIZ$(L#RC#!;3.`G +M>@'$0;HG>P@[./@0\A1;<I!^DE@G]B>A"PH9>+L^H"#S9E8\_3'12G\8/V(L +MBR&#X!#A+TN[N9"7Z+S7O%[Q"EB65?7:<"D\J6[(]3?-M?LGJD/29><,N;_F +M;!90+:_5FER]23<^<GX0=/@_[:2$[I[T\!H(IZCM'WGO'RAN=U$Y\ZU\%""W +M-Q'!G55,&FV(R&$M\FG0!W!'L.ME-G$5B+[Y*%#%[:BLC3DQ*@%KN41QHLWY +M"E/X;BV]Z.4I,3L$69A1G)CAA0#"Z=:.PF8_T_#UOM$6Y%^T"31#PO*>NE.( +M=-_8]F\]"/2IO(8J#X7M81:^_9299,E"S[:EW'H6KXWN@IBF6^@`)J4Z?!@> +M34(;3.L%E4Z04$#9T.;'QJ)KV2U/9X/_EMEA"?C5K[N.HW*+W^]W`?<V_42> +M%6%"2[+!:'G[4*F0J[DWE,N0CP'>7BM.G*F&16M&/0UP:3UCK2N0LQON6YTR +M.''_8$X/"K45UZK?EX7E!Z2O<EN.`7'(E![,&S=]J'['D[-=,XTZU6T(>KK" +MIPX!_T!2%V]-'?0:9;)K3$+=28E,."DAC7C_G)=H#,U_G`+W8>23KFZ7KDN@ +M+_K1W*](6E>B8P*,6[!:\V74T@.7PO\`;D?_=,1%8`E7`T)N,AUW3'FB+G(K +MW.Z^\X`7N(7)<TGA!J^1#"+4F=VB\"%4'U+!V[M<&!ZO<XQEJ98T[CX/=5J[ +MJAZW-*@H>S=)0%*^(K4'U?-&/M12A(\XEIQ3WQL'&;40"9-)K),RD1*[&Z40 +M,9&C6+`VV9G,79$I8/T(,!=2_J<D$_ZDI"X;!5NQ^4P<9A&86I2ZT'-)ZB/: +MHP2S3CJ.4K]U)D(1Q*/Q4+D'07.YC"XQ@XLI?UU!RM>*[Z+=VJ>2O##`Q0/^ +M'?>@DWR!(7?B[T,^V4+1?W#V&0OA$GX8'&?SYML+Z#T#LV5`27=,[V!6NM?) +MFVP%Y&_!@+%9ET;%L7ZAD'PE7@.OZC\PB/G+62;V`M`F:C5B"6'^L^=[:*<V +MI\7Y?2$W8F0*J9XPW:8!XN@-%$OB96?X3,#*$>M1;\4%*#B*]3KV^JHWLED0 +M>S9PZG'"-HE<E[BB6=4\!#XLNIZG;H]^M8*J!$AHXIG$@!A5EZLE>W]%,#L@ +M(8>@X9I('QTA*//91`&2=<OND@^1JVL3`88;@`(U;I?1N?`)7JY\(^4[.;4V +M28^Q:2Y!R6NH-8CB:_]@OARIW9*<F+I=K>[U,2G:'W[,#DC+F,)>2G0HRWKC +MUVR=SXM,<BZ;)1HDYSP#BA$N2S8*@<03V!GJ&253519KCLH?XZ)T#D(0#\TV +MB?T@HW"8N%YT!=WTT@@_)^*.DWC?4>?IF86@1F;GL&+YT4YOV,D)$31^T=%X +M6J8+PO9#@LF>3-`4\,8>L*P;5V'N`#^11/J\?:X2Z/'0KTR>HZ!/OYC&58K- +MU?31\:06G`CH5R#8<ZW@+TVPU21-8,3\_,]\[MSB$G_ULW?IX)@VC[G6`NLM +M]QCQM`R5RL9N%@T&+"'G023O&35:[>B<RIF6J!KB?3AAU(A\)FY1L%!%/ +M'TEY0,RG;>#>4$Z41JFTR,)'10H:7,$-&@[,,[JT8E;F`FX+#U[!C`@.FAC0 +M%37MKQ'VE2C)2\AR-K*4-S*<Z%LX9]!A%1K<+D!7P"'LU2JD=$@:;U0<NB9L +M<.W"CH"/F,-5U_Y/_97]AC[U*HME".(/T)"IV=>`9("<L^_8E4T64C-ZS+'Q +MAD*N#;/G`W,5V];OX$N!/C'5G[!2.&?"Y),?8GG]=G0:KN&@Z*S0L4KDEE[! +MEOND6*.AVFV03U_9$D7<;!8^%<6AAVC&!EZHO2N[:^PE"Z$TFWQ]:MAN:\A8 +M8F:EZ*H,TS38OA2O%#FZ"R<,QG*99C6Q974RS70JB3?67J2CMQ/$-]1'":A@ +MZ4\L'%?N,A$6^`TNI,P>GO0?)Z6>M%6'9D9&"Q1P0<*@0QT'@\O+L$*CUWPJ +MSTFX70:EM<-VO=:VKDD0!5S5H,3FYO3!J'":;597(6QB*7C,J<R&^:<(4=F% +M%9[;!`]M4^626=[\;$6OSV9LD3EY$H/P1IM4/VA]KGC/8%Z7OKTKO.!UCO,9 +M['*KB'%!G.F*Y'ZV=<B2J*TT0%::^5%U,P^+P5GZE]E#?=U--X$I?SK.XAQ= +MWCB4A)1)B#-JL\S6#\QD'QZ`?K"C-S971LW68>0+-_TS6*7$:WENQR="U"4J +M#.:,RNR(3QIS+3DB!XI8Q0-/LJJY"2R$7+]Q<T`/A3)E).''T>%I3O>O1+S- +M=1ZDM"6F?]-['Q%A`CG")S(TR-`,T6#M]Q$;"L_N!_Z\"PVGG*YC>XWQ+F#[ +M.=-NCRR">/>\&J,YN2L>+LCFI[SQE/ZI[F2^D')!0.O$])^/97`>7./W+:-: +M3Z%0#ID3)M2@I]_3O^E?C#"V8C==D1H%$>\`]"$O:\W2Y<+Y)^(%KKMXH\J[ +M]LN\T3S3&V\+.-?R1\WQ3\L=>P<K$H9PO$%EBM'U8G1U+@+"&I%:R^4,'M</ +MV,QC])ZV)@W3MS\.A+'1$;\.U(EPF,Y8[%J%3RI!O$<[=/#)WP\_TTA$]@%5 +M.Q4:@4^IB$"?Z5ZT[`%A_;2I6)&;\,>OG&'&W)N369.`]]O#X,,^`<-(#<4V +M14D[-P_];P<[&D(%O6%$?+O95IZJ?;FLRKLE+03'C1G"*_@V1!!7$@DN:4H- +M(4",&E[U`\CBUM_9'E1N38OB<=&]L94+I^Y]8BDSS,[0WNXLU"Z=BJ+W;Q)& +MZ9]3<-@[UR/1/?8(TD_R>%GR[LEIS/3?#.<FP?DA,BSW(LMI,D]O+&2H<O2? +M_;#JX>[^=W+[C7WTU+RQT$BM6;A!,*48F/%&T+WOKO-#(2#.ML^OADU5_Q38 +M6ZVA$='1,::2^I5&N=82<Q>$":D.#@H30U"JPK=HWJS6!^K5K'X--8U[XNEI +MPW\,A*>)0-E5];-F6E.0R;8;#GKJ]8;*?BN%_&NRU!.?U7/987HVP$J"&&PP +M4CR+.AJL,A4M'#3XV/DY1*1D+T^IOK,XYH4R+D!9\.\>99Q[3%_8_R:/"M_P +MMCV_R?UOI*Q7O*5<-Z(A<7A%Z>4\Q=^VZ1/`\H<2_BEQ",ETB:WQBBTGJV+3 +MGSLN0]69THO\"^\Q\0UG!ALJ%@?33WD^B-PE\_>D.C"5^6:S'#(YSGS\S><@ +M!R1*843]U6N3\AG"89V-$8QDR5&@_MVC6-`%T0ZP^B._"U2RM((SO4CUMN\/ +MF^:I`2C&&X\R0L8,<8K]U7-%19Y.M;EK5%6.@N(TZP??\`CU=6KN4/*=I90> +MCF4I0T1IV-#86I\T-JL5!SMD@P+1`#P#"]H'D2_N'4"3UK&I>/TV0:;62@*X +MKK\J"^<:YU<@^!3/=T*=MEZO+(\(1D=+Y+2=>\CK.C8PD"Y0W/XIQ6X0[:=1 +M]'8C#%RJ*6<L+I<^S/VTG:?0FJIL>!7=W4"9<L:FY6C-EF>23@NH5X?6Q$0N +M;5EW"FWEVZXS4]^@CZ0WRSBJ_H]18.@IH<[C-,A9*_HBPL3?C]R:0#(H?9." +M,HF^R;*'3ZG>'"-=)R/^M(.W#H#*O*R9>`%\F^YVX\82="HH;*[`?OEAPDB] +M>,($*'N/2;O8M(2,>#<1"-7[/7?M+E`BMP9,H-B4MX-WRR_^T;4LYSWY1RI+ +M<H*5>"=04K,2RX8"]Y701RWEE=1CIN^F$'9)+UP(6?Z3Y[NBKK&D52LFC'L( +M.Z<.)KO*CH"#2F^<4"DI,_!S/+/*L<5C'_AU584QJ\(.-.(A3.[4[BHJ89ZA +MB#?\5#DN'.)$O-PMU@9CG0"Y51);4K,D"`:;^_EJJD2(T9539C%OZ5:FU3R7 +M:=.[#=RCQUV^"1OK+*$^::B#&WAB<E-NYC*G^1P8^,(LGB#'OU8".BI8\P+A +MY2LQ1AB>VV;.AET5\"<J&0(5>*@9(T73*;24>+*<]J\'S,@*;`9[BA8MCV$] +M1!9UCZHR/E7[P?3A`74F"I62*TNN!"N(Y^<A7R>\BHG2',S\N)FO?H;XB@C- +MHH+QB069*O9EYJ#^U@]')P&2M%U&!EL)M;M.OHV5:;DA#>L8,V5>4MG>MR9F +M2F")4FN6,(3!6MO!>37J8`MJKGF"ND\Z0#]-BB^110?QXH&8Z^KN?58[B%#= +MY'E3J,K>(,)M[+%[XGT%0`D;>6QPL[4_7FZ+-B&U*OPZ]SX%-\'9;,_YRT0= +M_YC^M]9]C5&JQ42A.@\LWF];%Q]1@17LZRB0>EGF=MMR\JXVY79F!<`[\MQ< +M"CVCRL^LG4$3J2]R"`71/@`WE,*9K)JF9"?X<)]C<>C3HW['R?Y7G]CXRQKJ +M.EE_=7#PG`7K?H\1M/#LIG\7TB"[S+B7*MRNS1(B?\_RM@IM*\HK-P1U!<Q@ +M+G#=PP_T=422\O:JWG"V<>YA9#A>(=JT2-R+22I6B/HDD]>N*/WEY#^F0HT^ +MBJ^RN*OMR[9L)68]V1C6J9]ROO\Z6LEG$R]2-T_3()-`K7>8!03M>8E[P"6( +MAR$(ZJ)=F9-K,+1LEL(ZS?"=TA_\FY:T8TT)',$C&8T"U6@S7`ML-^"AU>`D +M^^HMEDS,3[:B+LZ3ZPU.?Z[URVMGO!2)A8VPGNL51OA@"3K$E$](><N?*H8/ +M7+3M0%B;,Q8B4)#$=WZTMUL5`J00P>3I+'Y.;;]?:D%D>XL/T_\=16FLJM$F +M$)\N5/"17S^@=_Y96:O=IZA^K0/,4<N(RV3T^[)[3;A!I#285@7[EX%L<UXJ +ME,,^Z5N?\!$+K&L7]K^#I,\5\6_K.F,&D(61WR.N9?UX(.?2[A4=3Y.E'DL[ +MMFE)OX(E-5S(S=/\82)/]G6H8.V:$$;E(=3.\./LO.\!`H?V%(TZQG9/KD(? +M+:/Q94`AX7Z?5LN;<<)/@I,&1S'ZX6#1?GK1);-B7OI(*$VO&19;=86;@0Q* +M&IZ#4+WB-I^TP+\U4WC@0M*MK9`C/XN;@ZZ3<@NQ3A;_F.;5@U:RR?(@$$;8 +M$YU.R3P2QYB`PY$P>@7+7?QB*Z".@[R]`<N6EM`1KV6TC]$0O"\C%'?;SY6- +MKP8>"7:_5G7KK4,/VJVE=%`(D*RI/\[I.=$E4TT[-0I\X7<7LVWBON&P\RD* +M0GPEK$G[>\&NO1^O!X%?('4X!I@%>X])96YST^_J#9ODN7P0*&2T%%6NX,IL +M]J!8H7;C;'6\T@=^H?9IH"K3ZTG,"XE'0P,/QH63+B")8TJ4O70)H.%942%= +MA;[E7'61*I,@/$/FN8$T)M`$O/N?[P8#D$NN>#W3HQ;N(D,ZDRNK<F?38D)5 +MG]ZF7#S9LND$][/='E3POC1?\AO;D$+YA4C&&9"RH26\P:R0:@H%KTF-89K$ +MESKP?6MOQ[Y,$F@[H'N5Z)ZL*L\@NFV-&D]/JZB-A2"=GRBB2R1LY$V:T +M)C&]6WJR$I"W#E^.-YR37Z'FNY+3-Y?M#&_O:"\O*Z`T_8XO-3,P<Y5D49D% +M?<E;=R+&!(U(3KI8^^#[?XY1"\F2[>J6_.+1^TH:!]2,+IIYAKX?'S4T.5VO +MVFM9;6B(?E`(S'M-7@MC!3FUA[A.NU)2AW$]19SI&G>0S+_#XDB(YKU0QZL# +M*F[8)BHU;-;4="UD*IB&DC<@]TD21B.I3IAP)110@V^?'/9Y1JY+IF0XTJ8` +M',TG.6-S2[$$%6IB\$U@K4GH:7(TEX;0U^`</LMCMUB\$=DQT//$V]D"U(8W +MHL9BLXL0",(5K02&\>,3^/<![Q`RS&/*L/#P*QM0X2#GRO2(?IK)2*<6EL.B +M=DT\>=992U81Q-+1B8@*^BZMHHRN_]N+[4-!)VM;BL&XE215E;4(("%@RK)+ +M0:5N-5V+4*Z@TB:7J)7B%=CWELPA:Y37*JQT8MJCD#Q#S(I0[H*??$'L-,U@ +M*M-373R3:4O[5=VMJPH!;U]X\9IJPZQV6[QY'T724@TTM)U5+&?/MA1KSHFO +ML`J!@A!#W`!/\D(BIBI]_.S?]M*]#;D^Z8R;)@:GO@@MX)!CTO)2ZI$N@LQ` +M.?VLW+F$V0,=A,:`-_H%7LGD28AQXIVF[\>BYHDQT0!Y%*W>4DS"+F;L\LM6 +MIDV7$KPYT6,^1/PF/4,.3=K`4+:=/%A)1SE[SE0JZ;C`VA1D*@5BBG[RG*'/ +MP.B%[92@S-;U\"$9D9.+N6DB4K4NPKJC[013:-!LG6C:U8BG&LY;G!^N/3F_ +M`'A')=;FZ^(*-*#=<H[/^63410`*D$L-Q%D1UG@BSM7Z(Z0MV<$Y)B[4GT7& +M"&-US\2VVMO=1Q\&ZUR\YNM3:+_3PD>EC0W.,,&%VM[&:#.],$U!>UEO"ZC= +MU<5=`,I`D&29X+:+$*!Y@-?RV7TW*>R&T]3'&O[,?V1.>,\6#C)6H#`'5/0R +M!.SIY[GU2X'/BGSL`]OG?^*"'(RT!4:""D2'.+J14NE^-(Z'>;<*!*$.!M;U +M@8/CE]%34O@P"8F6@GZ,DWHH-`M+M8$[1Y)[I]"`##F/4YD&[@3FL%I!^Y13 +MPBU<+M$!<3GG"/FIHQHF[.?3#/Z/R!QM4Q+=9-V+&^B,G&S+_;,:6'[$LF;; +M_-:G@`/XP)KHR?X1S/L,PI6>7GC^ZJ(+5"AU(XF-%X+J1(GJ?Q\7-TUE+JP. +M?,9:1H[/NLGP28?@>=P4GMOT-*G9$[7VTMX\H11/*<VCL_XV\$)*WRY(NJP8 +MK!,&>17?'^E=!%QU>KKEBO7B_=;--+[R(RK.LZ`^E78,(>C@;=U4&MX)0@U2 +M46SV#T?7CLL/J[M8N;CFX:`W\V5-?4(-L`5I]`DI$`AQM-$$ML&[1/_^B):] +M"Q^?OC.!YXIZ^7K*L6KJ+TMJ>B]?B[`W*?9V:E2,!'0Z&D;'=E4?#,==IWV4 +M1ZIG(U]V?791O.WPC+1;J?(QRD//&'QS>+%)W1C+2AVP%9S[.NC960J28S^! +M[`GV2SMD3U,T_L'G=O#X$L"P4;W1`[LVD9YJ%8%I#[)T0Z'V"F&Z"+<="QR- +MNP0NL#W;(@\)+KY:#]<XLGC?C5*-`_<$=E[G``A-3'_!N!>V<CZN?JNB)G>Y +M*?1K9#Q\5#'F7');(BIQ#+78339H\QLK1;]NB^S=.P='L<`GV>#%"73&+BBS +M9Q"$%B!`M5L.:-=)GD:)EW29'?X1O2%]-ND=/AAJD/"))$YWRQ::'J.[NNYZ +MJ&7PJP>MB_D,`P:HK);Y6VO,.^4T1NM(0FF+&K"O&S)YNG2C3@))MTMF:`8+ +MHB"\Y!T;]__8F=E+[$(E)N8#1?UX4"</Q1&W!N'F2/X4B;P=P"(7OCEF`]=6 +M?-1\L,B,BX5B5="FG"#?6I3*G1R""Z=U&VZY.`NE:PO:@DJ#)'6B-RY<-^QO +MGE+/4!@1.0=&(>W9RM@*MN`!?341DRHCS&BM+9WRT42FRBWX#%,LDJ;FLWE8 +MV&]Y4:-U^DA*()#BM:P&R2HC'2[T(Q:Q$'PDZ<;S.7CQY+O[39NZ!S8D6DCX +M.W'6/P/XMP$34GO`F9455DN;63"6=(]B[WQ>-Z;NSY4[IL0TV5'&A9=?%+6+ +M11,AUA3QX4,]FYE9TSP+L]7G2$F&"!&!7"1+*4_CG*P!_4(69L8,;>$J59R, +M%@3VP^D8A%V3NN(9/T-C;G1X$]@5*K[YE4-B@A3PY0V967-.`,RR`RP9W'U4 +M):69,RD5EG[5B934%ZI^*IOC?F(YTECX7>B9%%'!8ZJMVWD+AKT01*A-0/"] +MNK)?SE\_*74*+J!.YI=1F,LEKP*;&BO>M42M20?/2L:M_X'*R`XWS00%ANB% +MFU)[7*O%*G"B0!)M1'"9ID.SPU=P;G?/)T%W?D&]'Z'"@%;@Q((GN^/?[C?G +M>PGP$-5?-H2O&.5AU4<:7$+7K-N=]`A53(W9/98@%N;]OUURF=I2E+-MQ/IM +MYUNM$ZB+LMI"4]Z\/.^OD,KWM'EQ-"AE"1)?_2CM?[F(B+`P*;P*)^Z9DR6S +MPAIS_#'>#>["!+[,.CT;_(X$K=+H*HS".EVD1G6"]K`4]I^;1><O1C'Y!R?P +M^I?S7`=_UU`234CJ-K7D/=Q<7CG+_-\7WI@SGA"WKH;:U'=:C8:@8DKK=4)4 +MD93B_S4FV=7@*I8G+`R4E=S$2:G+4C=_)%OY*+AH]HNZ]G&XK=SMQO%K78MY +M03$F8=SFNF5P>%4HDQ"(@"5$,^QB?ZG^GU0!4\Q1M641P*[R$VCR/H&N +M<5[3AY&;$\"RXWB%6I0/L626KTDZWS>KS?5*.AU$BF7;.VZ=^=3AFB.MM.++ +MK&Y8]`P?]I1)TNG(DC-_^R?47YB=T01&I8:G;(*O_AZ:-U(O`!0R#WT_=9YH +M><W/LF#K9=(C?I5X`=*#(A"%J9.7R@'1S9;)7(".BV4(-?QD?GNI\IEM(W?. +ME:,A9B.;]==A??4S6],*T[/MEQ];N8H0&%Y8[-&`YO-'BW6GY?.$UI8JA;P8 +MTB.S(?BV2LL&RZ[$5(9#5/^?#U:[BF?=_5>0;;.E]7$MT/RLWB[%\'<Q2GO@ +MB@4<^.5P/7:.<L8,V)?$DE."K2[O\VB/@:VD;H:=3'0\R;,CGR:\/5M<3Y5Y +M#WH)\'/FA/_K,MP-QL4KF?7`&L26[%M_9)?IL^A.VEF-'N#-+]F&[>YNY*') +MZD/&8*8&4&8-R4\]R?179%)4"G\F&F2'XT/JT\>)_)41!9/Y_`*>%+=\Z*1_ +MW\;LH-M%8^8'!(V1/487#[LA:R]Z$+_6]U>[\V3:`EI2MO+-;A=I2L:P`C;K +M`\W1\QI)R`;U]]2(D,V6ON?=HT-XS#!]S>>T=Y5]7+50\!U;*>'2TVQY?Y5S +M>N#3YR<2/HX2B/X'F4SC+EQG*\W,;LZ>GS$K[!R#5&JLH6+BE<59CY_20?^/ +MZ;N<T[PC+X1/E=+N3V;*Q_=CB7TV1LOIO>P3TC_QSX@C;SQD[%I[D^;5X:X? +M<MU=[/%#1TI;"F:40!!\L#(-MW23#!140-7/;)P!U>'T7/-"@""C:\M8U#K8 +MF7IG23R8-=%31@V#\@F2Q5@/=%&#?@?KV4X#ZCM1PS649/V2(8XZ0'-D-``' +MA8"G#%RS%'@A>[053R%/:(D!&+=,-#41O=$J"-5HR\2#;&24A^R^'D$(B=2. +MU?"T5^`\IHE)S`"LFL/Y3H&6!'34&3RG3?/3&'LE%'T&()%1J`\53L:<HJ?1 +M-_`N<Q*8=TP^]1I>KU\^>7C#,\600X5Z#\JVD;Y='M02#>M#&+[#OZ7"R$QV +M0A9@H@)V`$3!"C)9@C/DVXLZ!)^2I)K\<-SE2XKKG+<V//T8PG(?6YW,?M47 +M)_C&W#,AP@^\</OZ9P*B&9?#/&E'7.MI70&R:IX$:,A9`X-M.M\<9W!K3-IL +M?AZ^;_WV7J_PPU&LKINA1\0KWS/0JH8Q#J@`I_]3&M"4MKF8D$$'`ZZ7+X]L +M&2$SVOB'J7(62JYY.Q*Q<\1W#JK`\#;F(BZ5I5&5#%]!;FHI>I?8X_<?BT4% +MXX?ER(_BR&BEC8BV>Z68^V/A%^KI'HJ.>T)&'C5D19!^%F-\X-T2]187]+QV +MBU<FTO-G=&KK[WQ;*J2Y6_&!2<T-$S/\D//3\OJ_EF07.Q.F-!^V(O\B.H+) +MQ:+@>>1D5@M:(VV5ZR*0@^ZN)>IY90`)?3<^PB21BPEDQ1-KZ3"P5'8VO5). +MWU,35"DIBHGLA<_'H]U`5PJOW`*]\3M"%"2ZI^S_`]3813TX6?A1<GPJ62QL +MRP5F+<HUH6E'BV825Y^&AFSH0B.>4^S#Z-]D#&#"2A<-=<&CEAKY8G6V/0), +MGB]*'^8@#.,AIBGH:I)L_]]*<=`$3""_F&@4$IS525JT:,>,FO*$R-[:*N4; +MR\SFJL"2=U8O9$U]!I>VQ4;ZPWN\>)]([H;EBC.-"&MEZZ9S2)8$NY3@36<[ +M5P_0;"'N"5X3'\1(ORG^8+Y8#90EG2RH$DL6D'\/R]WGC%C8VF=63#+M;O[@ +M0OP]^'W&H[<V,B[0`@*Y-O/^SMF_;9D\@&.\11Z981K4)VDI`_A7;,<-_+2[ +MD_<</0CJADV00'2]!5KG"4"3@2O@@N,"SPI,R%R6W'"[]Y>-$--IW.1F)I+2 +MU[+%O(+>%-6"?F])9,Z6+S?4YFU,1N3F/@G,FYZ#*4CW.HG/&;^I6HV_W605 +M9(8PL13O-4G\:1<3S6;P^^U7:!U&W*F'P,_$&A4UQ-T0(RO!*Q7E"+>A.> +M$_=]MA)?.GF<*&'9,"8+?ANWHO28Y'MM4JF^\;^#YDY3H=H*M!)JYFJIEQ4J +M`="73#Y\>*%K#2F58NSHVI59H5S(?N]_QGFEW/$,VR^;$X/';R=ZOVW0M;EE +MG%3Y\/`_DK+'M86CLN\MMIHQ&A9ILVO/$3!E=R7-=8%>W9,)JHXJECG6_:*) +M=O@CN]P>-@L35%[A4#$&&H5Y^FPBQ>ANY_G%[Q1:<N<N!SJ>><W]R>P2M)DK +MK$70>'(`L-<#L@Y+3H5YH!H@L)U@S&T'KY$8)$IL7QG[Q/S'M1GN\?',E7J0 +M11J;1'.LN;Q(I_093K*CETJ9$BI=KVZ`<EH><RBD#+.;F8Q::62Z-I5Y@7<Z +M#"YB;*-IJPX)@/R$*)MPGRN\8Z&=8*+C^MPS<\#,'R\C9]$-=W@:JSSO2"NX +ME)[`GNA!?:&[E:QE+?EO.#F%Z1C-.6<X4II*/HL$/==EE:AB_L5!/5!#>--2 +M!FR*9YTM4DC"6>"M-%*XEE,)HY,:@SH34-!6@:23[O5IE7?G36]K$2A@-^7V +M4U@=/KTV3X\ZG$H71*EF`OVS:KPMM><_-7E+:AG5AKB^-"5D5BT'CD'N"\#> +M"GF7RZ^![%VN<8(*X[IW535["L]YY,N<'R>X.!)&=XPL*.0Y4.WFO9*5ZD61 +M+2%P8%`F[ZK9'E8SC>L%V68S+[P/W,_D=%BX&.SH.W]1OVQG</WWLRME86$J +MJCM;'DY?F-`,DB32B6Z,!Z2N$F>Z/W?K(8_0S?=G./*EZCA`M&0DD38R%T+X +M+7)CN=;#JH"@F/D'9!5X@.7NJ6$E"6KP3Y>+/8F'5//6(@!V3.NN\TV1CO(M +M"FC9JG9'/HOS>B<J,N$VY;4:7BJ@(_,\".)FP=Q]O*J#=#L*:?*!\&A^N_UI +MLH4Y15(6+OC(%@>=8V_?BKV*1I`R5)@D`Z__"-#7.ST?77HJ0OK,>QP&^Y\F +MV0][*O()VOH(UJCIAG!%OM&-BM'+I0$S#S_:4'PXH>5-]:1VUU.H[`NF!$&8 +M:X^E+</+_<+EWF=D?7'VMCPS\ZE8J?1?W-M^GTS$IFDDZK>L1BV\*V%*ZDRD +M[N*[^[V,>[*H7\J@W8?94[>"I$IRW;%Q67#`GG3+Z6JE1P7!N^TA!@Z<X@N1 +MMPUP^;9:JRF.>BVWLJ*F^5&K`+P?AME&(&I_5*A4X1S9^\?)WA7D47GN./+* +ML,D_T8%\?Y5=NG90CS"[-/IR#LM)GVAOJQ`FB,18V)6$`9UI66;EN:RIOF.4 +ME&(Y6C48KL*-$F19)"`Q401"`N&CXB<[A&E`$-,2++=4Y<4AYKBUV\!'Z?2H +M1)I.5(1T3>30DD&!6A"I2MI++#^90C-A^-PWC=5J#%/M[DX3?ZD4S\Q2XQ7> +M>ZK[PJZ*2O&8J";3JGT;5`1/[VZD`^+B!X44_#"9XEWN!,DO$*(3B14C]2F. +M4$9YP/DLRV1.NU8NT_*IU\R*ABMEZ?W/S$#DT@;;I_?^KF^OEJ!GUBD_Z00$ +M>5>O&OFD\U@PZH2=DG0<!&8N8LA;Y))V$4S60U]QW7GPJ[</.VMV]0#NG]NN +M5@_N+>/V5<;_;Q?^RN_&94/=/,)2*O3NJ*:)'%4<8N%L92I&S*EIJ`:QXEDZ +MXJ<X6P@N($=E1!&*PUB4ZXW22'YCEO74>:)W]FQBZ)"!FS2T$C6J7%@FH6A, +MA]7$)DOA]\JD,FL[L.Y+21I_E[J-;F6.`02X6,`Q(NT/;YXU;_4*"R;3[,K< +M0U#Q/`@8+%!'72Q;%+%OT/P!6>.J77F?-BD-^RA'">R0X0'115CBS/&]P@24 +MY[FB%#0Y<I#%<+^)_2+I$DZS2:)X'#4-I_IW8_Q8A"(-+&N+?^]B0B0Y[-=) +M\#!?[^1P:F0R.R$HC$!L`<8.TYG3<Q]"RT6:6!L;R4;N:;>[25170P01/H]' +M#^_GYSZ+K1#>PG?L\]NU%Z(V*>/>.$,ARH?UO//+&^"X+)#[[5=,FVPN4/7F +MQU$V5_R_X"&V?3<-8S3+&.'%JE15,4'?64ES44-Q/P++.*_(T-5<D(]$*5M; +M-9HWF[I7;6!X=++EG,!5M57V41U1JEAA1='$'UC*,[T'`_G<T&.>PW!OU5L5 +MA]E31!L!K#/CWPKN';=61RE-1X6XT14X=+*TF:J4D!7*X2#T<1#6))!6X:L) +MX$_`])$2M\/![TH2#6GU@I\]TJD("'Z#G=$VRA,D]]K&0*QMS*"1)3Y3=SC8 +M@U8RBYLG[M$ZG#[#9CD'18)PS_2Z2:^ZP&P+WW#FO#DS0,TO]6Y771O41X4Z +MC*/0'`ICO^<=E;>V'RKR\F/ED#EVMHQPM?A4E0HJK]#8MH)^_^ABJ"R.=XCK +MRB9!2:LSUU;@DJ!/Y35^V^JOWYDRZFB_AY>^E:3&?M9`P`6ZCSDE]GS*>=PX +MW(K#UII[>":N0!.!:'D<^)UV*Q9[ENQJZBS@+[8&>1GT>!7G:!3BC1%8335Y +M>H&8>[]U4M;-FW(JU]>/,UY4E%JR"&^Y1.K?GL4G!^DTI?JXN&K#CK%K8V!U +MP+D05^X0[^FIU$[$$FP<WNO"6TI4T:@0--`VPPZ?H.5DM-_5(W&-L9PA7C@= +MX0]BA!"XDC47G0IQEB/+EJ_^!THM[[F%H5#P5$P_5EZJJ.$5L\CXW\-PX69< +M#]LM/+B!K]EEB.#_%.`I`JCW;9[`*O#AQIU1E([Y5;'_I;FC&;4BYD>*>6$D +M>&C['')KYEQ0)#<NR;V:N"*042-E_9=7:0#&&LMA@Q3JEQ_ZS2875;`N$ +M>I1+UK'.M&5R>Q34[KQ-JG\`&AB_X#X\K!GL;CQ[5W=46@=ID&/LQ,F\-VJE +M++T/Q62XT//[$Q<&+*=*I;!LEH_Y?VPK$/.9&-`T=RIY?R<>KGPA]N^J)VPL +MD+C"DZ0O?3A@,F?IDD+(F_\PJ\"-XE2BXBA2Q-3;/_'G75H#-1>(XPT.?F/4 +M*E:K#^Z/,?+F-9Q2]64+L0;(JGO85^W6:N@<>@4]300.O>EM[U$8]URIA^%) +M5OF7FP\*PC:):N.9:?:`V>2<)1V4G644Y5X#E)H),HN7KNL179HY?R650A&! +M.WZFLWV`<"EDY<TL.V8]O^Z8XD8=DRV8G9O(U'D`F[IM")))RM7(:?+2V,=! +MX]W:P&^GNCW'SNP;DS4R%8=]TRO,PR<W2OFJ$N3@0_Z0F+VQM7VPEE'-!@JA +MHO'@_ISIHG-`(FH/BJ/?4:5WL.XMD:,O<0,"9V:$E$9U+5YV>"R2'QW4)GW* +MUL3+Q,">N6FS&Y%TG%47`FQ5>[@B6LM28NA1Q!^KC-KO=*6S<91,OK%@+7.B +M)KH#`U:FO&12*R_'AS1`LVU'<VE"C"G`_:<)659C):9N[P!M.#O")7:;0F;R +M.>0"\,+'6$NBN8'=>[SQ<6RE&7XL!+4K)*"V"]*A!G-YKBZ]KNC;+21Z0D,3 +M@;]#Y6R0,M<B&'J',A#GA*$KJ)9@-2,?KF;78ICK"<Q8P)&_T,)J_G8ZQZ?\ +M:Z@@1F2ICD_9`CY-XEN[B17LJZD56JD\[O.BR;F!#//H]V$%FLB6>MZ;LT$< +ME`?7S1<\O%8#Y#Y+H/>U1R"#<WX91860M%(#L+NN+"/K`1CO%1,&ECBL+]E, +MH-!+Y3^@U@3>E$`7^NQ8"XR6VH+\UU/9QRI;4CW>RNMR47RZ&Z2$B=AZ&6P8 +M9\RV111'O`;)P-!7X&@=L9+)#7H6/IE,S8]]0\%/C+JD[L43P60`V:A%/2TZ +MU@@(XP5SIB!&MX,/_U>3)Q$Z,^;\P)T4=VN@CH#0-_:+15O]V?0C/P*[W2W- +MZEM0PREL,"S8]YLQ%P9F9L*Z&,4YU*M$LP73ON&<KC`<:M[78KP=^+1#E`25 +M'`BH2M*9JC&V8X=@E7UNSTXOXUTB69;W!A1VZ6GMBA1?.;U@6?".S8ML5T@( +MV>N@*N([>'O@9Y9R07E#Z[-/MY>N%U79BFF.2Z._/?L&)/^O)I]"9?ONA/WP +M4"Y;X>)]6\K:[B7E$0>[IM&E+-ZQ,&YEGP$8QUG<G6@DM9+T7$;I:IU%%'3= +MC#9Z4["+.6'-AW:4+V>I@,B^5O)RT$9?)K+E6RNP=4`>G$Z,T`RS#RG(IJ^N +M6\C%B4T`SRHJ;:;GC$0XM$ZK2/:5S;XE7)9>_N>QN3N7I=99,>]-BF^^D]<C +MF2-`O.J1=4IQ'QZ8S3X---*/KG=Q'-/F+4T;5?'C&?0G+A-;PY86>$38?9YW +MNNF&[ACK`S!05P`/:CMRK;`EZ@[#;_(^'%+NUN"?&T'(&_)_C&_DWLZJ[NU@ +M_=WK]*M?+N>/DEE(.]#VZES>`7AJ7&>X.O\S!H:;=92%>V,CUNJSG"#J;P_C +MQ3J$2;FB=ZI!@.J`]M7<Z!5S)\AOW,4&3"`=WM:T"Z+Y)D<U8Z"0.C!:W6FP +M0DJ-];E"DM7$H"21)D$<`=$46#DF>/U,X>,":6"9E&0U#\2GKTS??Y\#3".% +M`'*BMST6<3[IWK/@MI.,C))`I,%H#DK+KO9CF6N=4)FVL&D;3<Q=RLB)(-A& +M[[/>*RQA&4Q-J;IP\>3FF;9I_S+<UG:&>Y#9VTLB6\B#IEO5YP`_%*E)EM_( +MH3HM)2BJ0"4D,@WO=.IH&65-?<C'J"8Z4E-22,/T<*'C_J?7E53.=3-^@=R' +M"\,\%5+:ZQ`_SJN=(_,:?TA+?/]"M^N;\KI$J:JI7LISM__LC;NYZ_W:<'4K +M,Q$D2\4O/=Y.Q^Q-$2U[>+'7\H.@Z>67VOEK5/89GYRC151XEA.7>L[)8=_M +MV<W7I6JOI,1CSOFFLF74\.I"*SI^%5BC-7HOHI]%'=\%%:?`V_V7>`0D=#`M +M_-E^"OC4@H,T:?X3_A4?PM+DD^??!,3M^;812$\2X/H(7T!2Z"G7>^2\RV]_ +M3A[*'I*(S11^@T%0M%N9)8C"X9*J?TYZX:5V.CYSZ;EY<AOOV@)RE.EFW9." +M__0:^]O`+>9OQ,_Y?A@+S_RFDO!*Y2HP8\;!>P:2+7NO#5`'M9>"K^W'Z>N/ +M:L_IOX,TC]!&\C=82%[$-(YL)VD:Q0".2C>T0=3-W<#C'=3(`5'8&A6BIM)+ +M)<+"'?=ZTFJ2$=QU6A%Z(#2DXEV*R)008JL\7G+(LZ9+'J"=)G>"B2=AL9K< +MI`,:1+)"9XN\1?N:F$'7MD#3_L7G)$W@]Z-1SLSYYF0%YCU84F+9L:H[6:=Q +M>=(W$=07A+FYN5]\\U@1>[?'"P8``-=/;:I>%.R(NECB$<_D'R/6[=DWO3;0 +MBJ=]O>:XC\YJ('!F-@\^RQ*):W^E*%\B`T5QB-FVV9R+Y5$K"S?+R9Y,8RF4 +M`A87S:2I--%4R`K0?DK`VC?;CB:&Z*@4IUUT&O:BR,%&"I3TD@5&KX$/?T&, +M[9XG7S=*YIXO(^4X14P]^"S(ICPO:SU!3_FS.5.#/L+LC!&,P*-XD37H@C_Y +M)4!%4^X!WECS5R;0CFF7"Z3G_C<II6W\9I.6`-5#!:]14M%]9DHC;M/T>`M! +M>]ER@/[A31M,T:GYE]/EBQ!-%G&G.T;W/!O@()`=O>,+YU0(M]`'0D?S1)L/ +M-](783;!8X0Q:1IP7_Y_G065I^O:5!8)S$UQV8(-&VV2'#\E/OE)S0>J#H(E +M72UZWI6=*=-4_4]:M:>_9'XZFF`RP'VK%@(HTOFI!)"XPLS>%!W378\1U\?" +M'\)R!VN[<8AF#S(-;">WKOJ?T%K)IV(C0S<*$AU-[X/%FC!9;GPU%8];0RA] +M#,L"_/JV*K3E9/G(BP(GE1:J,8*N$,_!0#Y<Q)OYYJ<*?-<L=#CL+[$I.[#Y +MD/JC12T.G/2SVO9FJP^QQ'M;+R\?32'CY_7'QK,0IK!<(`GL"8\$U=8)B0[5 +MAC]+ZQM95+%J[#9[1Q^;2.%>,WNGB@$N0K^T>4!JG!D>QZ.HG;JQ(FG.T"*2 +ML>:CRM0+5%[%"<(E64E>%)82)Q!\+AT[SRE*^F3+[M'&YD6758X9?J/'!!F@ +MQ\D3P"35ZZ%:U@Q3M7L*UIM0W]7^7I&J*R#4BXF;#V,K)$+%/G;GXN*G^4!: +MO\C.+!!+?3_-<\1DY;7!FD9,XJ]A#;/#]E\#<*A*Q-X_S[V0![AVFW-<AGC` +M\V^D0*+>!R-)=<<VGUPR9S,!-@?%/VJ.G!ZLP"/>5KBN]%91#@9*/"=&#M1` +M/!#?'5J*!/K+*MS,0""WI5,18"QRJ9ZYVXQ8?#`<.`2)N-U=]6DDH->!<6&` +MTU,A.]3C$^V.`EFPLEQ&G>-M])T*9N2@1K]/0^ZW;**1Y']Q\/6#B*>-BT"+ +MO3WDAJ.'':4B>7!MP&NJ1P5]>`T1I_#^]D@U+SGOH`CZ-TYS4YI/B"^#T9P) +M'=XA)@Y[-@G*9H:I\N?YDTY#,U6D^[Y(]<?`V-JDH3YBZI72+QU4:N&*`)OT +M'0(>=#!N_59#KR][-5WKSXA*4I^LJ!*)EP/[-41<P'2@=J()$+)]:(8N4E8Q +M,DU"X=KE5GUD>SS=,?.PEZ&E>W@P2\`T6F-*W4:F'QLFCQY_V.:7F"*U0G(= +M2>BG3QY>]]2X&0;/0'J*N766Y9!5*5,'X-XE@G$Z+^3ZAP`&^^7+1%ZJ\1/" +MGB444('W*,NC8#+``[-*#^@89PHGM7[0;$W9E7#>#=XT5NTS&]HFE^J(!!^I +M<6H1;./SR'.DM,XX/@:B%>K:2RJ@^XLNOA3XS(#8U.5$&:Z>BY;.SA]A!+'T +M74F2K]62/E!`=KJ?K7;<?DL:Q/@MN"Q2BU65]]VGY&M\H_?(,0]@C8`N(\6/ +M<(N,;!MW>74ON7H_.=K6R*Q&L2N^1#>#`?CSEK@Q+^ZO%";")V,.K9>O\.Y& +MKMIQS%3TM".4=WK^]<4HL"0[3E$>@?04F-0.(1U.YEO560N[>>20ALC2CTZS +MT,T?+@MN2:R[X;B$L+X@%B,<7%?V+5OI!4V89H0(S7C!K=B`*+N@FW#IJZ^( +MFZ`*GR!@Q_'Y!W$>=([Z8!\OLPDM&0"4SSEF:>"`BDVBC[1;/8+YX#8Y?'30 +M]W*D[R9)*C*X_OE?1*XD)/Q6:,?-^CV@C'A%^A[>!JDB//`/E&S5RW+*Z13O +M(68>IITGL,!R0]*-[2$QNS9T;W`S(S^`3SM7YWA?U1>,OOM$-BB-17=QDQT1 +M,F],K3`VGL9$@JD)G',0)J:GSEV2`-,MM(R&3;VK_+`%9K8#TODADO1T0"DN +MD,%S0RCG'HB*VA`10H;!5)K+;<ZG\4G['/!/K"Q3.,$KO4P,-""QI15\#_6N +MO,G\'@;\(?OB)+E@G)I>IR@:PT2=R)4V=K+[Q986_%O$8YW[B((N!"N].%O# +MY(%J@$7-=8Z?`4VE*G-)K#5Q#5\,\@YMV]0YZK[+^'19.7&("SRP[3+_Y&-\ +M-1V/$%T*FW\#V^R4Z,NQ+'&-8NTZ(J^EKA$F,4VP6QYS;.)*_=`J4$L;<LH_ +M6SL..]>6[/FH7`C%JKL._<'(I4;UBG3<.7YBK`I'T//WYXT1PCH]QF^>\]F1 +MC,L-AEG3OG6EW@!#'B!R56"<_*^>Q6D8),.MT<(V.M+PZU\]T8/D-'IAK=1% +M15.M!N*6R8+\^(H?5@S5DV2ML4O*X4V2$N<M'1Y_SRG-)&R<0+/8L\R%)82Z +M&N_)WT;PD$Y:7_EJ<:MD:EGO^QY'P::S\BD)N_#^J1FELL[[`!(AX<*GA$FH +M>?>,'?\-!PJ0<#7EX06TIG##-#.0=1BF=YS_F:62>I5-."#/P55(O&1O?4;0 +MI>F`+6@W\XO2"LDW]02^D\-B:F0+?K3;H,L_;`;)$I#%\'.FO-9^Y\T1:_X` +MM0DH\>M?VO`3]-;Z0]Z*MBYX6E.2%A4J0#-E(*=3.L7(XA]<03/S^<![./)> +MJSU4NB<!-#]Z/L&VN;TKXY)^V^8<>5@#C2#97QVD(LUG.12]RL01ABZ!*:X+ +M<32+0?5U&J>*-.[J2;]\='36E9)(L:!BT*8I1N1I+)]BNW57+UD_)J*%I6?X +M?$OQ`WK:ORL_,!['^%BO!)^(7B!X^!TAJ7[+4$U(N,L!@"+`A,Q:TX`6$1\5 +M^G>:L\.?/'.V#22::*/B4X6A/#J4/9,"RG.(M/*UGO1UT-.@8CN3?\Q%1XH] +M+S.-S2,)J3:'+'6=H_2_"G.]"7T&YVR`:R"P%']3T_6XK?[#F7<7OW-&P3LD +M?1.W$`'04PMF?[!O:?]AML@/CF3*3Z9JCJ4L4":O7WU,5:?&AW;@1LQV;KV: +MU;>N^S3ED)35`@K(C+[2#U-MA_PF-YS3EOY5B\2">ZQ&QY!N@/B;,]$7O%_& +MG;DY$(P^*.&I10+[B*4)-\>1J'O)0L0,-Q3=0.54JB'DJ$(\-<WHY-AO.9)! +MV5)G;+S1:4V$9'IAM^;UFQE*_G_I@[N79?3$3J-O!O*A7\0S"C4W%3EV\*=7 +MJ#I'\7NS<*8$96[;=-"I9S&N(T5FMX4C:`VP?I>Q:?3L-`!8JD]E)=3L9L#O +M_;$NHU-I#,*D?OR>(_H?N9VS?RU2>RW%OL+"\ORP[QSR=3ZR:%G!O/9F]OWT +M!;'JN#]0>W$*6B&OLXE$J:4*4Y]$^#ET#'ITM#L7IB[$\&R#_S66`*22)>RO +MEBD[PUNGBT.T@$2/X)ZR0%YJPC2P0O6&BOB?SX+TF]&LD--L1$SA)1-=J]H% +M@)^\M4'-T<3!<=YG07K-*0_TR?M<&K5M,G_9P2*7L7#MG'=VWXT<[&E`I*I3 +M"6BRN($TO%P]&\+!L,Y`V:?7+TLWPO!?&I52X@-2=`76Y8SG:1'&1$S<U#R( +M0CRM^O`RB-FRX&X<:X-RPZQ16E^JV.GR]7,0\!_H.EKR.W6FHF(LE@;C=8Q& +M)FN1Q=IE+T#P$X<IX9<8SI;EMM7H(&T^QSW2UJ5'P/9._K=LE#OP2YB7U:3D +M=-E_2W[I-FWA@9FMC%Q4*U<M)=N5-<\(Z:+/OOI^,&MM>;9$9!L6`.1]0@JK +M^F(2.UJ$HKKA")B,,_R#%C+_4]R(>$(]9>4IE(?_$:1!:@EEOJ06PO#<B^-M +M)FGZ_4V*T#_/'/"QYNB0,#.<F+"42D^MF.C8/<SF=`8_?6&J#^_>,=95)2#\ +M9RXS!1;HGV;H\OY<1UP=_]@8I0^]P0.Q^3,3E.%#S2!"][>K%T\@V4UHM=S[ +MM*EXZ;X=(`>+#\TF&*O72@O$SBPW$/I<O*28)56'<<-XNZW@XO:X)##GNV<1 +M$&7PN&P5&A`UX2-JY!%;="G'GT[,1QHF\[/?,I&BD+)TBFS\A1+?I7;3XT!: +M("GN(?],D?Y[,1_6%W_JY^AFI57U?*^^UULS98)`N@0T0`7J,LXP@_A&B%"3 +MJUV2XQ41J.WVO\^-HO%]E6L$3>VE4;Z>*:EI^BY/AHF%5C!D5'S0UPHD+4&< +M,R)'AB?O)`>*=)"LK[AT*IBH5QZ>X45A8%@]LJ$>QEY:;*LX1#Y!L=/'VL;/ +M%YG*]0+]($\RP:B^`P6P3MT^X[%G>MRJ7X%9ZM@J7UL6G:P]O'T?OBL#$.V# +M4V]=<",0G?O_5>U%4%#!VV3G]O6#*0!]-*&3X`SK_[O&B^^4W8=_R@'L5,(. +MR[8J^+A6DD4ZB"IY$>CP!M;0>2M4#P8M*P5R-2K"JNT1T89I),TUE]H1%7*Y +MD8+XW\V[=(()!,GLWN37U4B0Q/WN\.*-9:D#7\B76)@3:3WROIP:0$LE]:+^ +MC%Z.5R6PXB+Q5U%8D,:..:A/*/\W)#X%J&1V%*"^C=^$"(((EK0KC[6D0)ZA +M/S&U9YBH.>SE!^?;G:1F#+O8XL3Z4QZW.F``]:3[3)V.)=*M>OJJ%*TZ0!39 +MYS^?UOIB]MJHX#[Q%"^5OM/QJ96=V?<2?[Z\ETB9IUAIY9XWS)L4`?Q`5'FO +M>%IWY#@P3HN7>5F3]-2C9:IG4EU\(?VY+9I-LDR3`XWW_#%BK!'."24:($-! +M'^4E:*K$]74G$_,6>4=F21GEW3Z>TV/@P$I<;W?J^MBV=/[-F,U:5[L^>(:7 +M(*.%>S.`G[@US9&ORF9RQB\P54LFZ35)IZ3!LD+8S,#6&H,Y&SVN="'C/.3? +M"8LBI#I-2CI&YUAVCR]@2'HU\+-9S1LBB#_\7>"NC;C$U=5]>5Y:@I7)H!]S +M;!J&]"#QCLR`G^CV3N0+XP;A?HBVM?E"+3<V.$;3A>XK,_*-[4T#$XRT/"WS +M,'L.HQ__W$;W2N*9M[>4/&-8,]E^-.!!H1FAF<9D%GT*91I$7:X<`?`"=\$^ +MJ*$6B%!I!-'#KAPV%L4H#8?"RV>&$_@23V551/$&-4&*1W+(RV#A/O$5J3J% +MV/;10;@1]#G2G[!<$ZUT@(R?):S._7VSH2KEA!B`'ZVR4T\\FQY/:<[(*N!^ +M(\G@N_G7J'+[M9G*GES[K_H#NEH*[HRB("H&HF8P2QW3_`6S<<Y2,I7+>':2 +MITIB8H4SG=`\UE6^]+"EIS!8I*?'>I-_LT>!-@,$U"+V-_IYMT+SG@4DXMZG +M.J%%'(R>,\1L7ZJ`6DU3/33D7@)A%H&\HV@G5%]TL\8B^9I_#*9&05J,DB$) +MV%<0!\#$0K%<*_QUP'"XF@SH(.:</7=/4Z2_^$)/I$I<RD*#OQS'$?T6E5&` +M+L3_61,RQK!D_O'KHEU?MU=EBJ(3Z%YIRN^2*V/*<J^_:)DD4[>X[,L+J!]+ +M\STR[M5Q%M.W6NOR.KF*"8)<_MQNR/I@HCX$AXF+@^^$M,6ANQ6T9.`-S0(M +M;]/>,/@3Z;W7B-WE2#]TZT=^RTVB8HYL5Q%4PS=+;7;_E+^;B.BE.%MHF?K0 +MJ'VO3!V"KC[!2WX0CCBGJ6P,!E=L21>.=V%D5>U#;4H)HU7)!8N-4A(O=Z:, +MU(<OV!>3MICOV&,4Y*(D2X4CV7715ZQM1#B#V`E<"2:.F\8;TL)\>]J"TYXD +MO`QP@WS&/!>4RAV39A,;5[3^5ZF9'S`0!_VB*.>!BGUL:PLMMUB.`50PVE^; +M+V\^K0-I95]Q#`E'J'+!E%0S`I^P]3*42).1]1>(:49=V9=Z^.;(9S\+1F1> +MY.>-OZX-@A"ON2ZT-Z\EWJ]#CI74FC)I`B_F'8\GAK*?1/I_]F#>E1\FK/9I +MFY?`,,$(7=L?D!Z2[4T:FS)7(L,E&]I8G*899;@1X!<[\L6O>RL8LZ;],8OM +MEQVLI=NA9^,X<@T5Q/>(;(C>:-\V'FP@M_Y#BD:7)&=*F%:O":[X/7#>$FJ\ +MSG`'^9>QD*4@\AQK"E*RFOP%"@:ODVX<J_.+/_KU(\]].YK9'N+%=G2$P)^> +MA/Z)<'6K=N4B`$I&T%?OU%TKWJ$JG5\L:X6P?N7_Z7_;/ZA3H2_AO[1<QEVX +M=>>AL.0KM<G#XP`:HN6M5#-MG5VD\#E@,/!^1&5C.FE]1H(W@%6MVEGM\`DI +M#K)8L9HPNP%.<(.12"J5):*EX"!"!7<=/S;FP?Z9&\.2L&IR<UFZ='LT&.LM +MQ8HN6)E3-$Y+LR&X$-=KYWB]4!(!6FV%#*B#ES*&N!V2(OX1PW<^Y/[C#CK> +MC=M,S>F?&-3:8C9O(2'`O0P/,NYY9D'D:`6Z5,S\M^YHKQ^\MC&2MD3:[(/^ +MKA[<;%WL%R$P;=D2O,C,R[3@N:=49M\I"[#G*\:OMBMI($6$X;V?KA!H@<H# +MFQ6]0E->SQX,887L:J7J-_0+E`DF>\$AD:KL_)2;("9M8P,M[NRQ)=TTD=)" +M1%6G@1J;*%I%S0E'9(]T*Q3P>?&D/^/&<_])J>9UF0GU`JWUX9?1V/#-+MR6 +MEXYZ:W5['!C3Q#>UJ9'.A!0%174<@8"_.09\#@6+=);P]3C]XUHLRZM=!++A +MP@SU;:V6J&[*?F!N]G(.TQ56AQIW4P\TB[+4RX_EZ)SV:-\U./0RM*8C>/38 +M:6JR[$L0X1#]D\&GU;?!"9%R<Q6?#\W$OPX1Y#Y_J(@`.^>N0LP&V+[D-)!^ +M>[;RL$ZF[WR/^G7U9A.45H^2T"^._I^#=2V^J*%\@1M=Q3OR:?&CNO4@SA4. +M#J6X,JQ^=1)"Y.5A?.@"ZQD8)$[@@!./<1.Y$'/L<_JV.<H6=@!,Z;^88&3U +M-#B#2J4*/YYD./$CJ<]R^,5IW=?&NHLDGT');F?'^QO_4%3[58REH\\OT2P6 +M$IA7'&1-]&JI]G'`1\)MI3D+/N<+B&L!-J"*UR'*;T\W8V=?=N@]Y@>>F^NB +M%BKE7\L.G*9T*$*\TSRF6><[>>FMO#EHK&5*7X\KD)I-'!"C+JT#\;=_#5[Y +MS*)W4KS"6H,.+L+QG%H=7;5H9B2HAU$5BDZ^EI*U`WJJ0(F]DRT_<G3#;E3% +M]K'W<3JC4\TR,ED[?_:':OW3DU+J1',Z.A@E;A5<"FDFZ&)7SO)Q-VQX"ZH7 +M3;).4B6,WZE*6F!8CK=D=9_*(,^<SH3*?%@'1*P;2`'[=)\BKH2!2VQ`CHX" +M1*&Z.?8RLS'J`T0$'OJPN\]+:=V3-2;0(;"[OBAO(AM2CBFYGQ8#?HK.TS.& +MACLR\KB<>:\`GP-#L:%*95MZ#,[,&A3.J>_!I]D3P?(=+&DI$_""8_]_5;BD +M(_3K[`!!?RZ20P-DSCL7PRN092U.N5+)+!\XSF>AUSJ;PTHEQ)!SI%+NF[$" +MXV&#$%J>IN0M^EQ!$UQOU-],#G3H:@_(9SOU8?+`\F9I\A0EZ`.G(GZM="-X +MG`C>WVS,<;0V*RI(D';/E=T^6!2G)ZB1KL.C2QXP!7]Q79S&[4KC[=@:3`3_ +MDIY5@=`G(FJ<!\8YJ4>,";&IODGV#,\V,C_@G^*Q[;(X=*?4,J]E,L4B.A#8 +M)M7M,'Q-\Q4>"JSW'1(+_?6*7\^W,'YQ!N<I*H-JYMM'A]!L,JDEH"(AU_Q< +M='J=LJB"=OR`)J[M\5B.61&Z*AA<AHZEN1W6$RQ0D@G=FZ@Y#E>!\38NYL]J +ME6JX9K++":G?'"I!4R;4>_4O/(ER*4M9^CU'OQ2!!1UTNZK(/,,J;X"5H4VE +M2Z3*M(;W,T0$T#1G<[%Y#%.=#J4/H9:G`WWZ<QD'9N4@7?4Y+;4=/(O.''MK +M&$(SF']/7W&DJS,T\"%G',W9K]F%#QZ-F^\-1`G;`/'/@\%/WC'94#VQKVB, +M-NC;)\/_*JR>5]XN6/^8H>W^Z.\^KN4IH5^K^"?78Z0)1,$1K:1UR2)N9L4& +M3V40_]:SK_8;-@F&%)[-$,<+(<ZFNI9$LV:@"X95QB4L)(,+1\%/5-ZT#5<6 +M>Y;`6IWMLW)[VCVQDQN"SZ34PX\R+3Y^5Q;;A\,L+KJY)GEQ0<(O#Z/=M"^6 +M.PG51+$93:DX&'UWJAAL`UB$CK666J##&A%>]<7S0?J<P:*^UDYR);*]_@?6 +MM#YJ9$306F]`6!VH49)ZN30LWDGFO'W@=(*N5=_D<\QO[#\=Q^PX2A^0=<VW +M\]LW><"5X(!7]*O8;^\`:2,5'/P@JA0Y&8E!UGJ>'2A7"!'$6IP3=X&EQ5[Q +MGS[G*0KCIUS'OC*$_<ZAQ+^&#BZ)LV]GD4F,20+NGFB&E:6#UC),";A[)<4? +M/5Z;8="Z,YY,GXNQ>*X,9&C&$!A@R-?RK8]*"?W8SC.ZUKWTI6OH612UK^]N +M2;>:$-.$!,+#8<^,837M@7X5!G2)F.6S_`$K_N6%=RM/!EKL,Q=NI[B<Y*$J +M'^^ZM-PN*#;>=Y9'ATZ(?.C/B."K_@PT!/O6_B`J,8\O@`O*9!5)I1ZH?BI[ +M\S:/.(BC,FBO^'N#6-5$@R#(SE27'M2>E(;/_N]+"\=^*2J4"N5K-]:#N]MJ +M=07\3]X'_`]<!&1LO1BX_/Z\!\Z+)U0XO#[0&O8Y$TKJ.W^?D<Y7`=`ZWPZG +M>T0CAGR;=!#?>8</FM\W5(II!1XY*KX-2;Z/#^R`\"P,@D@UD%!!A64!]\W# +M_<)L!QK*.*SY?Z@(@R.1/$M]^8](2-(/AXI>D1CW$HEAI;4%T;"$LBA=`&IJ +M,]P%JF>%E%8$]OHY"91#+>_85!XL0VD"S[FO^1&T5N@#65$+B)N6[X=]JUY" +M5&TYBS-<.KT+3P/_0@"K\:K%%J@=IJAWY_=?>L%X]R?-#`!W)WYCX5$@9II8 +M_`N+[$`2_R=.:@]6NC#93?YM7G&Z*@I1>4O85T>]74I0X.\^#@(1?93KQQ65 +M%F33U(+(CC^I-LD^3I#ADO4O?!C^U05[DE]G/Q4CX')IUS((E;>C[:&XV\X& +MJNOJ\HL1+K:;7R?SC,`%#?E-]!^*S;AOZ5T`:]?YOY:/B<<G.FJ(RLSM&?1\ +M\-7RU0SS'T".#:SQ^(84J%RABJ&5\N340T]<^#!?4'XC%"WB$SWZFI?.G*8K +M[P.AK[L"*PD![':O_X[=B>^!G-DY"ZI![K@HE)(T8NWIT5'YIQ!-G!1`PT<C +MX[>H6Q:V9GX6BZ8U7T,H&H>X'(G_9GX"#12>@!3XB_=DJ^Q*'[4CY^=71!&^ +M[>43M&@8D'6^X@1?TRPFTOL@.+.TZ&VXN^-[@F8"JB/8Y7ZI*3!"'BML3BY2 +M!.?T2IYKU)0Y#4*W*\#X",_ZN]%=7BOO=L)JMBQ]:`V^9+LZV-Z-`*ZBGW:W +M@234C`"EL+_CV6N5VL6UWVGK8.S<V=">:GT&WO&<5%;JZR.0%G"])=1G0ELG +M[@^[8L\<-JI@IZ>*D.#$Y-*1Q'5:IL=]D\VRT#+T9-9PNU'67MSI)*5$1TO^ +M"DY5#;_2*)*K<*QHT+]6?']N0I5/7=2?=U-\>:P*SM327^!RWZWPM&34.J+: +MR]?-0,6Q#WH]?\I8QI#J:U\$*YK'Q(=W7SX>%!A]WTV^+<L:#;&8>OOKZ#MJ +MI8:9J13-ET:*HU-Q0R/[;T.@?"9(QG&6#[\7\41=O'@_F^,45'Y%]*LU3^<I +M#12L(T]P+8WO&&BS#(1""'7"=3:3]D[VE=>VX`WS6$:-HJ421V"G];TI6%;D +MPF,V]-U=$S5'U&G@:H_?`7#5WAGRQ@,`^/F!"/>`91Q'L[1U6.U.90F7U2-= +MYP4(I&0TE-B`CP]V!>KANPZI5BG5.V&(=G[2\\Q3QQ8`I6OR%K_V`DV\H'6` +M^\CG\.FK[W&TOJ2$\BD1%FR27HRX:I.^-XL[+P=:IS/3#.3JQ%P$5M==MW,O +M'L\H_/=[H7`0N`W`D\FB0\'Q#3ESCHCT5N5Q#"FB;Q'RU0P4L<%LE_>75<+4 +M.XJ]V[E;CNDQ!LO!HE6:2,7)BZM7A+#;A=<M+0=SZ*]\?;O9NA*(2I971;2] +M-L%E<V8GI7G1_%2/#B\GG>&O+"MAF7RM,$,]+?*=5NX)0X+7_$"Z=UPV8U:` +M)?NCG!D@>^VOK_@E#K&/?UMK1ORIYP0LD5+6S*,9Y++OP]4$XM*LA1],C,=_ +MTMJ;ELC26V$^_+H9:!&LA_W$5NGK`\L:/HWUP.>U:/8Q2_7M"Z3</'=HU8<] +M;`[M\&S'QSOT=YH%:MY#70FZG*E$=/'G"@ZVTFP3K`20WQD]!$(/H[^''VYU +MPU:`<^/%(5OA*I\?<F7Q?S@>&ZO)KM6(-Y_.Q<;!Z9^B`B08`S:L$I-C.,\8 +MK)IN&ARZ`Y]N5_ASM]!N4U1AFO!3T&A(C\;-&=RX(P:7TV>DX03=@$:\'"8* +M&XRE_Q5"L=XD4@^$7N3TA#1]B9@?+SC:DB\R'-B,#'!:1(D?5;`^E[,4YA,Z +M-F`(QHZ[:6O,+FL;56U.6(M*U7E;F)+Z[<3"#(OZOXW7+*^[#?;=BA)_Q[OY +M3.A9VAM="7%\'5>-KO2.]6E"\\Z8S*4`T`/^*M2WC_N.W7Q5U**X4!8,Z6Q7 +M!OUYP)Q$U"['G_931UL>ME=*L=C9CDWA4\R2JYF^P%QT]-@Q2>M6X]JQEHYI +M3,C`H:2$5V;+&Z\M9ZE@Y0-VK2V)?CQ5E'MO8PLJG$VC@-H)</BFG0"B]F+D +M'#*FG+%E3V&W69$8!5H$M%Q:P:+.^6\T+6](")*B>I]E4$+0--0[7\_G`W4@ +M;A?!,>2\.T*7LG_EQ>7<#A"(!]*6'4:BW[OBL`+=V5C2[L)#P9*,LIXSI/?L +M./_W/TIKQ18)Q0F#%92,+L]7$M\W("]ZBX,_60"Z!_T@?%I.26'X&@"Q0L6? +M1UQ<N[R/QA?/=QDK@`CJD=TB^C'QO[TB54QN9G)`H(F3'QK@G`]#,\[S@%'& +MC1MS'1WY@SR24R($C$_B#G-.P)AT8))1`8AF9G$RO@Y+3*B\X7$A7C,#I1!\ +M/X95U'V5&%KT*5QVX0@[S0CBU*<)DY_$-1,;H.'./R_U2-:OFJZHQS"-Y>V0 +M4F15]K=<(CRQJ@^`W'64JP1=?W=FOSBD(H78*4[E*R'B1O+!>488U'B\RD"J +M^0OY'S5[103W0D^$28BH]B"67P#H?RQSE#G^<4Q/6/%S@>TUN.%CLV8`(>!J +MK;!?:-G@M13JUVR;)KA!M7$A($D&MMO.@YF1L\TS>5WR#8N9_3EJ.F.$'!7( +M>FM,XM,=#Z;[LI^S06]-Z_[--:/==EX9XP09*4\V71BO^C[,S%@6H`/JI=F: +M;%E\WCZTCIG;I9XHY0"#+B:7P(?;QE%4J=[/+.X\J9_7)K:2HZI@+_B^0'@Q +M:^`BP!I]',A:C+'29\&&>J$U6?5":%X'#:YN=[HCY&O$A`9(6AA7=UG!8HSN +M`#-&:WB>-6%D=TJP$)QU!I0@@R#&A>;G:AUFI=A`T=>`N[CT+B@YMY`H=+&8 +M'WJ?A5)>NHH`2`&XHRF^L=Q]A+994(%WH@I&["G_FKPR<<^:=N3+GZJN2Y:D +M6QJ0$TFU4PAZ'^@MFGP4"__2_\GVR\)2>R6:]26";R;Q%[?+?3F,`]QTA5.? +M&@G\5#EL`&GS71.JX;Z.H>_B$#6G]PK5IU7PB"E))92*4.J09#%8RR1U_T_P +M<2\1I%I/AXC:T/-O5?K1S!<3V*6WBR[P<$N9T#3Z+;P!P8".M'G5A]333\TZ +M^*DSCIC0J!K>EF:QTS62`6$V6/5K&#JD8!YP'K%0_%"KVD=T\4TF)LY!ZIE3 +MR`>OHO2<[17H.$YF*O.FAY5SQ[YW'G&RPT!'N=T?A8CO!]XQK!\2[E'=[V-4 +M]W$UIF`IX*%X(!Z'L7"Y!+%OT0-7SLSR</[,W`'$!@<()D$^]2K>UAQ1Z(D& +ME#<<G<*<$(;:UO7>S`?3-GP.)N%#!V%)O"5[(E90XL0++_,!8J.=HZGE]>TF +M;DI"]AP?*HBW"E%TF@Y>1O%11?&V]M^A)\EAN2SXVJ#>IM<ZE+$W7P'QW6(I +M])$[C/?W)F*!R;Y/+@H=!=S[`Z])$285K,>7@[+T+XUWI'K=8J+-F;5WBP#Q +M_6*'J[C^8\&_P"0\W#OCK/-ZN@/T<SV*D3D_`0SC<44Z^(7>T3'!=?3NHZ\/ +M6BAD#$\=315VK$Z+H128SBHVN\/2:K_GTA:$NBXH'T%UX>+#3Y#9!N7.R-E( +M<9._H43?H$<Z0OD2SMG;G@&'O>X)=ANM)(=EE,HV<DER0;_^,">M5#1Q6&?J +M-)K&"(YHEY'5V?D>,QZ>1I3PD44B-GGRJMNHCL?,ZCBAWL_28_]X.LS;VI/Y +MW/6MN,[.+2.E./JMBC$OKT!5(KT,^6/=JY8F,?A7)Q_[`ISJ&^2T7.-N=_]- +MTD/=?I9<P+36-#D%DGSMHCES;/<<XWM%R!QX\49(4D[Q!QQ8%T*=2UA5D?E% +MF59U&#!FUNQH@HU9K=8P):((J#WH1/_]%9(Q[EPDH`C]:`P5R$7GP]QE&'") +MD&:X;>Q9I7AI,<D:"O=?OH"F"-WB,F.<5WM"9YZB"&CF9EFSZ$UO;B.-8RK< +M5>$_\!$ZGL29<F14^D_Y>U8'O`./P@Z9F\CX2R8P,#DTP`2.[JWH#!M@>5R* +MR:T\H3Q,%">5VD;>WRU^9$,!5OP+$&%7F^_TN+(2DC&P2%\(>OBC[^!?JM+D +M$;.M0B=CCK)6BQ2,U!['M95`BZIJZ>PN4X=X&@2`:S[F;K>G>T!3T6):W[F? +M<`,0,@0H<;`_`^33-::5H6[:4)(GE0IV(-[O^ZPQSW2%RPZS5/"N[DYP(*&S +MZV/-Z2@'JV)%LM;02BG23C?XOGOP$`B)\L*TZ]3-.>W$!^;81_<\<_Y-&GIA +M$B)BNE+%N?TR-IO7ER)UAJ,'Q35^<3+D[B'=RK[=)-O#C?R9*AK+Z"3"'+M, +M]DQS]`=JX.X4A;'PXL\C/6:$0680HDOG+>ZK:0,YU'Q-GYE.?.8*.6^WQ]M: +MW,`CK8\&$2V?>!EHNC5Q0'-VQP+7M,:50T\&;&%[T8DW@U.`]$B,)9-IGIF& +MO.\D5;'BSI<T9%Y!^A7!0'H=U-X68/645^[V>+<XJXS\=%M'IF%MRC.2#R=` +M5N7,>'^H,FOEZ+6BI#T;=;0P[!]Z=N"@KKVUN&XN51ZDCHT;)TCOO&Y^(;H: +ML*6CQ()K#=J2])7D9+UZ3\:7RMC\2(4UYG44:K_\E34$F@^'JBM,K``Y43'= +MR+.3YN`TJ:2!E./QO.:5SF4/"]<Q,H\1RZ6\C$U+-HGPGJ[XH%Z!Y@0K`_]. +MH,LD%UC0)+5YPO<)%^E8+?C!9%=V?TVRNIOYE9RUYUG8<!0LDY,03U)U<9*! +MEC^T+?3Y$V@]]5W(-53C*HJ'95@'S@,1H^:$Z(&?,K8@%0T4II(:JHMSVWSH +M9)]H)NC3YT*625^8^[*O?SS:J<<P(00>&+#&2MVZ+\4'YP>U0Z2BP5YOE7N& +M+)OQ@^!HLWM8_5LE;5DTR0VY&,'7"+S3>\;F%$^5O=EGH$/%5:%(.U%!VO+I +MG!W1M8UU'1#>F7(<*!>UD[?%/&'QI$;L!ENIK,YJ,3=URZ\&CJR(98,9"(3& +MIU(RP:R(\(-DDPYJU9,8K9I1W)$)R':'\2J?M2L<+'#W)^6GR>/[9*O-3R-= +M,T`9I9+(#)$2^\`7^9=@*NT.5R(QYXL+JT9I5;0P5$:T>T#CEJ*#)5`:8/&4 +MKPI"%R<JA/4?V"L\_@CW_@DD$8AI5N^3FYUZC&1.RV4D#R#G/B^!H(YOM'A` +M>OH%>35WZ/4>\E2H[^_%0:WLT^FPO!*!C,AK5TIC0%*OMQ>=X>[OXJ*KRX.< +M>7D5X%$3S9G(JX0@-C`F!0'ONLQ&&\R^SKVIS;9UGO%K'3:3K9:13>N=?(V@ +M1G[3G-++(MX.T8W"'PMN_,77A,Y]9$4R/OJ3IS&H'9%WNH#&>SW+M](X-9'A +MWAN'H+)+>T/W_.G04;B'#6\(>YG(IUZ#]RK:AH^XE8V]]]R"4"$U'G:@'\*_ +MM717`TI>[CO)`V;7LF7ZGH=2W@*JWQM]2)FR(CA">,>7KUQR0?(V6$BRJ"OA +MHOTDW%CQG[[UK%Z8<3N66?]3.>*>F9`O[CI[/,EPOY,5I%L^7$`02G,UH!>! +MZ.1`N:>61-`;^'.^W%W95WR3CMN]KZR`T7-2LLI^Y0HHK@<]9344"AR!T`"D +MT7W2P@7D`YPI^JWT)U/JMYQA#'6&6FZL^V;$Q$UV\%RR*^FG"'V>$>*Y:!GL +M9.OW6T"DZ,D\7YY:3G<YF;[#AI<I^S>ZE!8B_14)QU=I'&_DM8N3,)@7DFG_ +M1#8>1SP8KRZE9<4-(ZBM?\'/^^T0?)DF6,0&*D@-P(;^SH324S%07VS/2L!G +MV<ECT\3_-R]N$R;RA:C0.),+5S11F8#Y;0:/X/T-PB4B\4R@5;3=AB9%.GVS +M2]9M'*!^-^LQZ[@F!:A>YA<.`$RJ.%04:=/\Z;H:)V.H[+1(0^H&<U)"6-`B +M^D._5)B`FN&@)V$B>?OFW)/SX/6[<%PLL09DC./KQTK6]L[DN3"55:E%F6R? +M#,L)P1!DJ@H%,DQ>HQ*?3FEM1SBL??*S3C2\K$^X*B"I*UK3KTVB*YX_"%." +M@)?-LPK4[2CDD>Q-/[??U5_UZ"$Y/%L?Z+[1%6B*\6\<C].Z2CQSSD=M(2?@ +M``"M4&HB_A^%;"+\)N17'!BY.0E&Q`SX#SMNWP;+^%R&8BA:1Q'TF@\8K:3_ +M)!)XM?H7S:,ED4XO#'EZOJWK)LR4JK*_(/?17@D$P1<FYP"E%\M>@9LD9ZEP +MUK?]#MJ]>#3QSIF_ZO=<V"H,2Q8#N"^F=W.N.#&/G-;59]\\U*/3CA6N'>)O +M[VPC05I9<>SO/B)5&07GL7D)KB7JDEH9LSKUTB>S9<(I(_Z<%DMJQ)!0-I8Y +MH-KS='+<*:Q7&_V'I>Q>V7@1JE?FV;-SLL=-DH'ER.']5?3?ZE[O8V.V.@JQ +MA/%]GH7._O9E>&`&)H\A<K0)R!7X5ZAP8X0S)".L^8*""5]2P0JQ,/&&O`"1 +M:;VGZJ^U5N'F`R;B&=A3IITDSC[#U&12C>O+6O]D@@B?.,7<1<ZR\((S*J_A +M:*`(&$4/^2.OWBB,SBXOU\B"M%E[8MQA8)T@Y1<U%8=6>W;%"R"Z5Q'##$[* +M4EZ!BEU5B;HP;NQ)/3_,>(0%8H><C:%J-\W`?Q_QO8B'_1`AW:Y8,S<&<8I& +MOPIY@VCYQ06W)\.GE'PX)F=5D2'-'+@6Q@Q),A2"I(=078.+EUU(7J,Y^MK* +MSMM5$J1<!OEA*G:4`JN48J!I2JM9?0E&Z4\L:B@X[>>@(3]N2%QZ5%;JHE%[ +MFS<Z^H<HNF!QG.&+/&3[5IT+,["XAX&>HPY#GI9TB^T]+R%UL)H1X3J2GQ<# +MSE$8-2!>^H8UN&IY!`'W*P:NVR:1&P==4"S^M^WM(&\2ZQ%$J>>_V0G>3D6! +MF<A@==4;VY3?[#-$AK;)Q1W[%O]YPX2+Q.<GWVS6^P`K!+*,KSS/&MRLE(8R +M\D)GO#":-&B(K,J491%!W'.^H6]:1]CNL[F&"7>B+8MAYW%29[SR`[(R6*S) +MGR^Y;J]5Q`41R.N&"!@B]NJOM1+`)CVA.3E&&1TD]$<#U^:/1P?`41,40!0A +M[GO3)V&,\17_$Z+@318Q$QU>'3\>@+%[=EVHJM-^D;X^+7+;@9Y(C"`G[LBO +M+06#_=XG!RE%H<Q#N9Y$TDW)0(#HZI%I3*7W";CH4_Z=.!\(W%26I8MBJ$/W +M,SI>'#.<+LO&&`%H8LX`:X2EB)TQ&`:;8%PGN!0ESP],A<'$D@JCAY`FP581 +M<TUUW]LSNR09Z4XW'-;1*^'1;C0;OE0SI_P9=I<R?_UA)%`F*I+U>K\]-`,G +M)<Z?)5!6&F2>"N?O3,?$.@QU6>BB\WE,QC_A%NV"0KPFRZ',<0.2X9^F:\X> +M]7T6F]!Q3\$S+J0HQS#N-"&]!8>X6,2YL;N.Y;<AL6.>WQ>QL7?GV&5)^R3% +ML8T20II;SZ<NAXQM=_C+D0J,Q<T&#@GZ;#1OI``#B3"(PO.,&%QZ_Z.0YY]E +M;;J[HKBCZ9>&9$4BH>Y]OW[W0#HJO1(26+6VZ>AQ5AU8=!(KWU63':Y_='3R +M\TE;U`GZ=G?_:=QFIR:84/:4V6FR*)G[]$.D7]+N)K+"(:6!PL,5FBX]!<T" +M07UW^<P_UN["ME.:LR=O?[1QQ9">L%_N\6G\"CD-1T"R^#;\0I,<,RW`L]@9 +M/AP70LNS\GF+/.K!N;_@<P%"K<$1=;DHAJ?H^HT$'#`#OF5E<1J67ZEP$Y<` +MH]KLT=BTTWVCW&1"5P:[[>`%V':[UP]8R(8_A@F.[4?0$'[RO!"AB'"JC?7. +M$:D73-Z)_Y^@((Z[XCB&^.X$P:'S1IG20A1D^P.6@YJG[T3PH@0.T7$KT\:L +M7%6NG%#<;&50`:E76;0DV3B[6UFN-YI0/Z."KG@Q<,WCJ/.LF$.K:27T.?`W +ML?4DF]\`Z#@;%WZF;,$)]$9)VZ2/BQ3/`V_0V!V<UP`LX#+^_?0"N:+$0I:M +MA+1%!&\028&.)SZ-5-BZ`K+Z)%AG'A5K=?I!$22X^'-V32FQHNWZ8N'!;Y18 +M:2R%T=0Y_M64:C\V>:YRLUV"D77?HS$=,/.Z[K*M40<YK6_D#::[$!NX97;< +M!"28@/]?]@FX`JX07.M*;$*:)W-+#YX>\.]=APH0I)\4="`.G]AK>(:S'___ +MV<N5]?9_E-W:FOB"UC`R-Z_"DK18&<O[9PRU^&N%#Q%[+B8)5I)=WYW5^1)" +MH(%=D6J("0U1+A-HI0UYV1I7LW$A-)/+63467_"..XGW.EQ)B@JW+-&"&UIN +MDE<?^8S,*C<'T@/M;0LF2-9QR[2GTK]3>MDJPQH.AC4!4JW72G+62&>V3+YD +MV5DS!S`3GUB3P$'"=0*-V",^9*-Z'BUE*^&;,T#HW/0B/Y)3;7B5`M''E^7U +M`C&T)R^$YG+0YY+F>$ZE"V.&E<(W*WX=1FB47[O(:QLSD(B$:ZAY.+,R_;>W +MTN^416*US*%"UGJ1-N^=0<7XP,O6KUWJA+*^C#_Z=*KS1`->1@NP_@`4_XTM +M-54T[9A>$(8I),470/7F"VI1O'7.C/RFZT+&7+5NNHVYRRTA$D*ZV.C<?/7` +M?PEP&0+:==:%U9S#GDVC0UH.NWF4UGE_,6->*$:AV;^\9JQR+?!"MB,AMI(, +M'-XJ,KTT]R',ORZ$35?@ZE(\:3>I1B*;+[=:I<&8%EWRFAF)3C%*QW`!*ZU> +M$B=K)Z,9UU)A6XG>:ENMH'3"4*0W99A,_Z5"UCL5?ZT*.5LG<J#1NLKX"X(' +MW?Z8[N@.H1A\8;/RCUP&..EG9.36`M2%$_A*_<YSL`1N^KH_RD9-D(!-RAB% +M1TA[465#"$:=P1\NS(K'A=<5;8FG_P[AD1:-H_7R:&6-(V\!N1RBT2C5OO9, +MQ#R13^=1ZK+>;+B[RBW`@!>V'DK"^-Q>CU6J9`TN%QCET.M"[`3I\_HS8/4J +MQG8BQ&N^8L9-L<E3ZR`II,07DCNO8CM29_5ZGU<&L[5ZO0$T\!D0JPBCM;LN +M!LGA:7MJ?'TDHP2\XYF)D4BU4@LVO9#-(&+XE2^V^DFM"A0'[PWD/#;3Y.8( +M5MY5$(#W(43C>SV[Q!>C<3O%T_);Q^S/";GKRY,-->_XH($0,2YJ4%N;H^Z_ +M&WYXU696HGD@,=0<5*QH?F>9GM'*5VO]0"B9BSR2+[)+$V-FXL4%IK^@O34G +M30GBR7&%D"'5.A+\G$Y8'I]R;C++/V`/A/B65H[>YIV%[2JN9^=_1T!4X(&` +M',7Q_4$?'Q`,!=;599^/23EUAML'2)XI06CI$C:<^N__+BL2DYPD`JUP`?>B +M<&JD$)[#"YPRLH8,1+WE^T0E'K1+Y9&EC]1/=3TRB,X^6\"?80AHM&?%'=1& +MOC^#-G5(EF<VZ_@W31/<$D!F.VR'.A"OLN7*E'XG1]U:$))[=P4'W4)WHS[C +M[W3I%U)\L0577KLQ/6%&!@LT,BV3]4:2KAU2<G;@U1F37-<U)(I'>R\A_$0; +M(/3P<).2=-N)&JN-2#'-?`E`76[VM;*;CPJV)?SDV;\=V[*92R\0"-G9=_"6 +M!$Q\E+0*7TQ\NWIF9+MR!<C,IQV.#3#.RF!YP+2`_8JJ"4'?#&#!B"TUYR$L +MR[G0*8;V,E%W@A)PGBIN?7]3?R9;]_8CO7'`2UI\:2`#0#:;+N<+:$1Z0F/H +M:=V4:C@Q_`NCZ9=#/4BEHEWF0A9^4K-/;7_>!B!Q3'.51\K(RY1D:\&.U<GP +MJE::XP:'P7`B*:>#>N8\U3"Z)<<2`&3BS3?]1C,(&^%.5<%"?"3=N_'-O`N7 +M(FI?&C/MDF'D?10E$B0NMI'<3*6DO/OD$I/RH@>XX,F2G#0E#54=,$3`^6\E +MVN*JH^!O5U&(.W0_3%)$&L%M:0#>I%)HXO":XOL.QD!K9Q)_)#>8*S@2)1$' +M6F.@U&"+1>3R@GS<7RU$('32!=*"SM;'J+5C^ADKK4<]"`"W-F1$@2%TP7FP +M4P3KY8<-N7+K>C>^`I09J7-1AYMUD7=I4OX^`X][CWAMGAMG"P85F>@@JG^I +M8S+K.,)XZ,-^B2RXUDMSZ?DLI3K\)=QXNE%QYS&+4.J`=>">'Z[8(9QW6\F< +MVO%J15UNH#/C#0(U2$3"7WYAJQ=;@,M1UI?IZ4D[Y7&>D1#PPZ.UP?H1BFK/ +MS/VZ8UBP6C\:Y@'N;;K86%%4"="-0==UN>DAQZFEG%0?9S4T`-JEGLB*+$W: +M+==:"J4_IH,YJ@??9^ZFWQ0//3BK+8%PO<.RY8%3LE6;!6TGB1,N5C*[5`\. +M6(,=5LJB.A#J!#K^1-FM\_<%G/,+85K4Z;8LE;KQ6<>'8`OLO,B[=C0?A69C +M^>^=H*SM[=`H[HCD<I#=(.^JTR_"*<VY5P>!P%,BFQ24NM6:S`B=M3]\$X(2 +M`?0[@@(9,3'0&Y@1PT%2!^/QZF)FKE4C/J&H^DH</_(D:\9$I6T4\(4$R'*< +MYDHPA[,U5QF\%HW#=DD7K)H,I,DCGHW!&$;M=M:_D:B_)L:3O[4+RL)F%O=^ +M!MO<BW[-03`:VH0'GA24;HG'1]_3XXA)$+_L8T>>6C7F<)EO2@E_1HF'=F\$ +MO$5+UB-8'3L2DE?FI88[+JLG:<&16PI]XG=L_V^L<+[!X2PHI7=YW/P]$N?7 +M5,]1&LYY\WZF)O7'\;>.JNX@BU,/>#P5`$VO2TSJ%-J-&*V&WK\\WQ']D275 +MC,;L=`%&_Z_&WWZV_`M"MB%1LW8<;2EX1/3K"((N#,5^`&18C/MT2LAL2BM4 +MSOCU2M6)E(?23JX:*QTE4-IT%:TKPT-CC].$3#HS,?!\R@4VQ.).\#><1`@S +M!JF_A/8.W29I'>3^=U_R+J]:%TF(#8IE6W3D_MEH_'?Q'6BCE=(7O'^U5ZLM +MGP8]")VE=;T?A]=W$1NMMLU'C`^R2MU^7!QQ\U4[(TJ6RP3LDK()(?H=I.KK +M)DZLTR])P80)%,$]%3J1'TUE&A?)'CY@`W*2<%?JE:9\:TX-U9UJX:4;+,(9 +MBRES"MJ;E$NPJ=DX=,3O@EH37ATD\%F!*&&^R,GB?V+P!-TKQ>VM8F5YL[O! +M_JI]2(^[G*#"20,O+08J!*3C*1*@:/M#XBYX)Y1='HP%@'WK9>1T<Y$>D&X@ +MW:2"`2$GE]674I_*FJ9&;,VBX]F6]<,W[9L&ZL;P_[@MCIS0/KFET3O&WT/0 +M?MY@(V.!L3I.N]N/,4P]#Z!$^S2EZH&$+^R9+3T+#-XXT;,8.*4RG)/Q2J\* +M8QL&,O9<DY,73QB@-.2L<4JZ"4Y`*.B/DX1D%`K'=(=L0`(E_XSF"Y&CMAT9 +M"E0Q>==M_,!3Q-2\76H/9WSR_^;,%6F36<_=0@==PS'0#C>XW"GU^F1/0]?X +MC$?CGP25IYPBUI&=4!#?;5=/T;6>5DS@M5N"?B%G!DT1)X[+\^%6`7]�_@ +M`(<-HITQ.U%=A-H9P>9AQ`OPG/%MF'1Y7R'II7#`4+,)8H-=4!Q`8>9(S.0+ +M>*%.!K&I*>9NJV%O#F&B<0D7+_]X0I/D)R'"XEF(?T1W_F-(T4N-)2H[=X(: +MCMR`/5\IB><=>[S.B9>;`QOD$I@E9(FI<D+A6/1N\FA+/&<P74W4L5]O<S9+ +MKV9O6FX/`X8Q%\/G#J\W9DA3:I&E3C/VI:&A6N8Z70HJ[8V['6J<)J]FTFA< +MQ7_*$C%F/)$9ZC@0Z'WX_4T5^Y*.BW7-Q@7*78KT[303#M[=(]!I%)C20`1U +M>:N[R*JMI@OP!X+P/;E)\P2GY3/;J5'Y_0N10Y^LV>[S`%[C@?2><Y7]C?-; +MD*E6OQT"FL:V]N.%"O9]NA/.PIL01KS?N>*S)J!5&8FWE\T=]Y/G:=\"&Z=S +M\9X9!.N9VK]<@C;Q-,(QY-DU]-.28(E-BM]S\YMW;-:+3@+"0.3*,VJG+&VD +M^9:O5&@O6"<UH6IRN^>XF7[PH9J(YJ%=6&,-9,NA'%#F^MUB1#)Z37UR8IBK +MP'3#;L]H"'\UZ&AI(SGWQ!O;Z$8(4")D,L?]N.'E>IO:4`J&LM\D\LIC^ZFE +M8-8>2RL8:K)=2`H9O=]X+)P>.'PZLS&[5^MP7#IP#/;B_WNY[T`^U>(`@X^_ +MFP)X]IO&0#,_F[%"":G!>(\$1RZ5GW0QT^?&UU/NA\'87#5EAGOX3X=@\5+/ +MYE6HA(0#-FH::6EO]WNRV<7P)UN4]VP-&C&L!'T,I\'=([8UYGSKKS\!M\20 +MH,*[X(O?VYH+T8W>M0Q4F!S+PG"VM(87]-[92`PQY2!Z-5UH5/J&T"K$MT8= +M6!:MKV"F^]4IAJ1(+S[$.$2_1W>"[U(=L*DCS$A05S?QMG+BGL$J41B1NI\& +M_"\5,P$=&((`>QYJI?"S@4Y_J[&(*4=NIIOCN^9"MJ.-VO^OW0U>^Q5@J,OE +M6E>%-#]?0YCL!`JH7O2S=1CE4LFUEB6%U3R8A.J5)JJ[\4X6!_B<^;-'BL7_ +MK]EC:Z'VXF`6,J7H#:%#6]:\=G]T*(@J?\!62P]J9P!5]EETU`%@J`0X61[[ +MU[;9?-Y4HO&SBT_1U1/,(]4,'A*$&A4L09$^7[UBL\`6N51\%]6\0)&>H!GN +MZMSQFQ[)I)%A&96V9,@H3%Q!)C,?TZ`'>^5-".^)A,,I6_(VQ'`]+"?J+X<* +MS/G'Y8E?XJPK5T8!)J4[K<6(:PI?=9V-7P!46,&7HT>W/$,,F:-]C"[.M3)2 +M>,^Q!+VO!IO"FFL4Z-]0M):EU4S`CP/]"S15I6/LN8"33'KK\/:]'/!(Q+OL +M6YRU;KUD,74<RS=2(='R.+/OXXI="6(X"B)/(4E1C@5H>.0\7W$<6R(KK0KJ +M_.OTTWP']-?6'>SV/#,$<:2H2_C8?,>Q<]DWSXUF5'>,CUY:OH"3A(Y<<R8E +MB,ONTJF?C,8F0@;9E-R"9[$R*_0;WO?H).C]A7+OQQEYH"4FCD_]`X9,]>Q& +M+,N;*$8["4=QX+XM\J9*%7?@$<10.EC739J.1[&Z=9149SELHEF@WO5O>E7W +M*O7M28DJ/*OV2CFCV&E^E*O!U3>NN/OS+^B'./:!D'1TBA>B(WJ'(![9^T4: +M@B+8"""JS1]H`QL2-VUO7,:WW^:SMK$'2)E]*R"ZX;W*K5(4E)]5B%A&*&,A +M0CR^=9-7*#'G(FYEV%&C3$0EXEJ-I@?#`PYN6K..O7:"TTG_)U]O_^R7$L`L +MK9%[\I%S^45"M7!CX"SEN[*;N8&.AH:W2+R'5=K9R[WK'LGPDI:P!$-D?.`6 +M&^+J75TFGOHA/[@LQ,*F8]>\/>Z3]ONPU'2$?#:SIMTV[CK*;Y;.'%SMU)W\ +MFZ9]`:?C-&VP+QRD]+!SM0"O[Y#L1#;A`*"D/3K$UN;>?N:4$ULQ_5'?A+J> +MR_6Q>HYA729_5:E>7W#P"*Y0BRMJ051BN>GYZ9E:;D&],[/:V-C9A6LN#<@F +MII=DY==-<W\R$+TCV;D"X!RDBVNX+Y'HIS?)K9.=K>[?"(6'(#ZT8A&%,]V] +M^VMGHKI?6>1E]^C*X:;?8I6%G=Y@%?/(<I)SWWF7F^_6X=C64O4AQ`+@!\$? +M2:]:@,GQDJQ/_;"4V7*Z#,CWER.B&(-O)`CJ!-3,$G'%_@EEQICEZ:0H;7<> +M-R41X^"20S;Y`&.6B&'`O$2_+?V0LYC/AXG1Y5W'P\\"4I=.OL63'?F)3CY4 +M2V!D#`FW)AQ+,4P8?5&2!-R(OR1D:"/_TT,+<9^,"&4810+KE6+FE-V"\N[Q +MMC<3_U9J(I9$G_"Y.>&=00'M,IH#Q0VXVQH':P;6"I^XDZ/G<),QI4_**/Y0 +M9(Z9LIS5]2.$XF"*X;=.1UX?_3*U\!J/81%ODLYL@?X5=_1.3PBG/JSNH5R. +MTF+LL?IFM#9YNU'D1$`,X$E#V%+=L)WUJB5K<X'6'V4+H$1UD'HXTH84.7N" +M4K$T;/;P&_567,A*Q'#^7FJZK8S50I^)8,*AMALJV.YC*7&K\?[$0\JZ8R`1 +M/G*,%;;M<K"U<C)?!4382%V+AM$0OF63JH$H&37Y!K>&D6&7QW%FVK\SF#TC +M^2:WNC_^OMH++\F;:P)FO;_(O`0>])7"<Z3Y:9KWYO3#?&L!C/8W9EUOZY6= +M=S]GYV6V,\43!K4=W2AZ=7J=9UXV^/E5XUG5!+^$?(784HV:Y9+MY#OCL:-B +MS<#ENKFAEEPB=N8*((0V%+KEQ,F-1ZVU#<ZD`Y]K.VL?N)D:T<#@Z?M-WT<J +M1"D(P&!Z'$8A_QS#CH5PGM5($6K^<#.=XF/Y!<$UAW@6@UH4`"_M!B3X?&3P +MQ"ZX7/&1!Q%FWN+YV7N?8Z?#6MSQ\-E9RFMWA9-<JU0&]:&63--D-R\_:I5U +M7BXJ0`)/V?.?!\0#RKD#Y?8'-Y)]L&\X_9#F+T6#V)7>4WA@$EL[UE;,5U** +MA2A\^*7OKW@.E/6?6>,0RH@U"FA?47\]DN(9#P$4A^B)3D)[#SH\%ZK!2]S$ +MW^/*.2[AZM<3I:7]'5LQEY8>A&DC]BK'2DH_,90&MQAM3&46VCX()XYO[6"B +MB6G_O"S=D;T@4=R4=C(ZI/#Y9@FE#!9Z+W*!7$+D0-71[9V&8`FI2;!Z)=K3 +MN&ID?LFUL/H7L&@>MY$N]FEZF@&/'"MX75TE4QCYMF71CA1@4&73?4V47=^4 +MJX8P>0TF(+1#16AE9#I/)8?\Q][)Z$<C]4]K=[=@>PPWW_+=]1A'J]1'-MV! +M=Q8'0#,.GY=$5)(,_)8/;PM7$>@7146`@]]V+]P<LN`Z*.V'F2I/TXMP!VIO +ML.?Z8U(UO'G[AC>6NI%"HHQ$`]PH"L`XDDZEG^<A-X]ZGNKGC5?9"GT*T2K$ +MK;K+A?P@`_RBS//<?/>!&_$2"R/^[\C2EJ'?`[TO8<^MGSSCJ7_/H'#]!GTH +ME\#;HAAEX3]1/XAR#I0E+R";#CK9$U[2.#UKN1MWMDAMI0;VK)FTY>?:RA_O +M=(;4M[C-2[>MX>7KE^$W"ELHIST$22#&+[HH-,H870J<"<KM+7LNWB_YJXN( +MU=-375,0>5<[AQ]5*BIOA($;'%?[6XGD8^X,LH#A7>07Q<O`#2688='(U?QK +M#_3)UAIB(:74G^9KKYXP:@_Q&?A+NN<\Z'T2^4@W;%TCHB/X)>D,PY*AF*>$ +MG!<;'(\QI4-3IB`F48V_EOTG(>PE^2?CKTM$E'#F#'_3MR7631(/\WR5_I?. +M4_'B:E(A!$:%[@BS+_H9Q/"OE&-#[??GZR0@_:P9N*F-;-7*Q<0FHJ;'.UT1 +M5".+@H!%T'UFBR5E?JY-1G28\BRH_I^>;+6.(LKVP)/JB?6OG@Y9>%T?,-0S +M^T0U1O--,V15VB&;U`9L\Z_?6)N15,'YZ-Y'&(1'BSEV;*4U%I=$=RGXIZ=1 +MED"B`OI0ME&?O7XK-0Z=H'Z%+E7W#*F]LH.AU7JGW@NUF-QS)X,?YQ9E"&2V +MGD>+\\!NU4T.HPV@D?TG2![7&O5D>K`Q:7X!!XYG[F7_&7>@$X<F;J/%(X"= +M-SWR?]4L32L*[F;+N=<SY9R,ZQ$-N3&X89S3G%*)-1I6R]C0#Q#-0GKH[0+> +M4RB6"R@9F:QR(__9:J?3>I/9@\BKITEI2;,Q9&\A,2V"EPJ$(^,"3!E^*=R! +MB.V]/Q?O(B#_LK`H8L-W@!"R]P#H"S1TK.$I((B'!HY7HW9L(T/Z3S%<6CN= +M6$K:>-82/*['@2@KXR(10J<Z@D\&``^I$EUG/@KM]W.@*.DEW.M=D5Y_:XFG +MMB3]WPV"3-HLPM\2:MH/VW8RNRA6@L4,[#M*74MW1P*8A57FNWCI^P'2323F +MN5#X<JV;!^O=)2*A@SIEF2)YYFU='[/+M4H.WO/S7?;*/FXP&8(KJ!@X*6MB +MV>=Z:RNN4$L#!#,``0!C`(RP#D4`````+B8``*UR```$``L`3D574P&9!P`" +M`$%%`PP`O+MA&GN63K,ED&Z5"B;"E=_]*#J*:B:.>O.IC!<,`V89N#"I$PQ' +M''MTYV#M=K^C?Z/-K#(*D1`JH\E%A;_\J:D1,I)B%A489*D9+P5$-=85E>QW +M7'A('PW(#8BMOV85>_7EJ`QE,RE+E/WU",[,/W0-/%1:I\-*]Z_V#E@LQIL9 +MT1!&3XQC5JB"SM"A7X=/`%;C$!F"((P<_9-P7H#WI?MFES5_/Z_[/:L21A=* +MYY`T)AZN,PP"(I6\(A>>L&]$`6YF&!%?O0XG69'-O?;%.L>=S(?MX#^Q"5(- +MN%K96L9USL!H,=VCM`&/)M`7MNC?7$(?!5B^!0^XII(;<<K+5>:U@I;_I?)E +M2:EY8F[ZZK0B5ZF0:\CS%\=:BYMM*IRLAM@#W(?SBK;0Q$<A]7&WA%%E):*$ +ME]>@"WQ_M_93+KCJ'"L=2A>]B$*(^9U4)@[EZ"S\TE6%3MD^A]53];#/$'%E +MG>G2I6BQ4Y5#[+1.&B+R\K/-"">"_?)U''VLFY\"!([G,J:`%AA^4]-P/KI] +M4!BR$:=>$?'[GD^VL<&Y4FBW7<ZQ:_Y[A1(#--:/]IURUE?,);Z'':KT($<. +MFR]L0A^B,*,&_U<O@?[Z<>XD)#`M"VY[9S#]T%-LF,B(97:5UC4,0]GS#'SS +M[T>X>)![)V2N*S>ZMR7K\H]ZEI$C..!](5GYXW2M=QA?&P1RF;XD[FD-A>Q< +MVW*=\=WUS,2?:_KG:-&.`\)TW!=++GS&I_[X."HZ%=E08+PBF@ZEPS(/C6S_ +MN03#<&[!@1%,D;\(G%#BH?'598TU6LUGQ=]@9`7C&,RHQZ)"^!#1EI"4]_0" +MY"J\J7)5^Y::Q6#J>"$ZNS]P*7=?]@A8[=V:8VOA_]<<,;Y2L.F$-PH=4S+Z +M*[_OPQF%''B/,;&W%EA.OX"S'/_:K+&U19OXT2C-G>4656`XP@(D$P4UB<R, +MM2@16%-!,S?^2Z[:$NH@,G]Y\[HA?Z<9=QBE3]/]NN#832WT^VA/,&6B5L!* +MEFF8!M*MH`[#P+G;VY\Q><*:9P(:^3A8M_I6A/.9?4^.]4KF7C41Y_%KVMJH +M?.@N@$C#E3;6[KRRN[Y(Z64D&#U\[N'%CF8*YC>O^)'8H4,GYY:ABZ*2WRKG +M7\0]CXF0YD7<PC_'"!0WZXW3NB@[PDI$[D$XJ=4D$6>:MXMI+B5CV1GYHK^> +M];7=RZ'=_5WN7)JZ$HU>U/K).(FDDA;_T/#/K4JC;S<V(C09L)^2`!B)I-^* +M2:F,<&1@3;_L!]]#H(0_H1PI1CINM_^/>F8I&]GYP&>P03FTR#<HQLH7^6F% +M*:3G*=3L:XU`HN'D."8;N.'ARO+AGY-I_>L.E4[0D4WR-I5,QK'9AO.53C[A +MK#G7\+9<>82<.E$N/^2@/TL`QAO66C,?*MN]-(Q6%C\JF^ZZ0+?WA8(W&&+M +M>["VGR#64^D?M8KKHRMO2G0+;(1S);&O#9O-`M$VED\HVJ@KY]);_IS"D^-% +M0(B@C-D(^L(+U`$),U'DHYCFM[.K']0(-8$X3]=A*%_-`B:TBO+SID!,IS"4 +M;9)X(K+UVG%T#O>(`X_:\47C$HE(M#<-<G3?&U[W&.#CB%UUD$0E_>Y(=PO4 +ML^6IR\*$/U?`A)[227X'Q:2J\W6J%X\<(XDQ`.B.64N(Z;RN0O+?,+';1!]7 +MD_4!P:Z;,6!;];/.@X'HS5I/3+'MR9AG>,TF!)9%7#TLO1`2*9^B*3::J59\ +M^W5(KRO(;;T[<4>^(PB66[^;`Z=^*<O%>::CLQKRI7[I#!^WXWH6R1V4+D0\ +MFR$N(_1_F(W=TZ\<W`RK&S?W_`4TSQ,'4`C;HH+(_F2_)%+?"203G4K4XNJX +MDS<\H1%9\X!3YL;+[IP)R)JIN-1RK.90Q'&7(QZ>-TZS%[Q,C%ONI\W^C?]N +M>^\36IHT0`^>6EF$\,!$(>'>2K3JH*,Y)Z<J5@S(&7<ZXXI1(ILH\(1+9_JV +M4)W?<.1`#$BK]1[JA;P[<CZAS]_[6EU=`X_UBM3F0;8:4&6PFQ];44&M66() +M+)1?F#M?Z$XBUVFFIZ:3M5H79^-/)_,-<ZI1,:GH*OG9+UH0H3J,?>NME`PZ +M<2%E)D7$.0M87EUY><X(R)XA7*\H/Y17)DKR-V@*DSO1Z9LBAMEDYW^7)XX? +M<%=W+*2-J&F)O@8FE-(\48H1U\:_"JOY@S41+/JBYP&%%0_8W@W*+?\MG%B, +M9'-YZ2[%>%2KBAV]\)/K';9/KEN'2;!8KNL.:T(?48OGF&"!$.(>\X-\DS@3 +M4D^<L84!CZIIZ>GUHZ5;@VX\+%["U#3$Q.S^!>G$/[`.0D=#<TO]<,W\_V;9 +M7!9*U0XTN%G61"HOP<Q[6+]K7#V<RKN^,&FEYC"?&K[,;#!G:2;R$A.3'^3. +MR6IV&9RQJ%/^:W.M:T?Z!3]ZMC[CTMT+BP8?EHNC6X:'HZF^:_<+3I?%#N81 +M!3G6?70H1/'M^F[&Y]N?N`[YSON,8[?LEOD)%B$IE$-E<IYW^%6=+*1[6N`T +M'V'XE9E`_M\4RX_Y\@D,^)[)E*H@%TNS(?!5U1V'`N_YJD]R#3&&HMH3^:&Y +MBV_5`SU0ZC#/#>'Y/!>L[S5(`VQ]1-K?&C:'RP@PQ4<O%F-H6K$#@#WBBR%6 +MO6Y8RPGT,<DYFR2YZ&*:%Z`[S@+AWS*OW(*,]9%%.I/*37[^Y>@VK`U5@P3= +MU1^4!_6Y_..N)K%QF8KFNK:>6A<'V.246R\(/0PKYS'"#,A(S6+D5T1*AHK' +MI3W&4^\?064GX*?.P%>2@[0-R,@<U*#Z2Q5-/-WB6\HA/T6'2E/\23QRA<[E +MZ,Y5K)[`20CJ*SUEU^39;+=^=NC0?L92);1!+/2L$$LBX\V5D>/G9_/PH-/` +M%EB%R2N[Z>!ZB<8AXMLV3'G>[+M_?JU_9U<*V0V=2G*DN8)/H$9!,=>G47^Z +M7%]K`:*G/KT.DI48I52]SLGL/%ZU5%+C6$>(RR@H\\M[UQRQ#*3:!*.$OY,D +M#=2L0CW)26Y]W-^5#S"[-+<SR%M\$TL-XRNF30^AKVGU1Z:LI,"4;[#6L6\" +MU-&4;93'!MEFJE;G,9;-%"QQJW3?W'0/"H[#95W$@](3<[XGM#KM?SIPG'$3 +MZXIHDSL2%OYQV'Q^3/&J9DHY<D\LFLT5\AR@.I]%G24NT(/M6TM6,N_1H%8$ +M!'<\)QWW;N<Z.O-EI6R<FYF.KZ>4.N=?W`VI6W#%Y6>N^S'A(:KD]?NJ`50" +M>X3+0T89B:LU2'9[2Q6L?>&XEV4^FH5FK8T(F<%7P<DB!QW_-RE\QFAPW2'M +M*U2+1.KLPFE\[9TX0]B`O#%.(4SC#]KHWJ$*2'N"9UB?(`RU<.J*VX]"VO]O +MZS!(+?.?VNBWJ8^[^X7.&>LIK*7YOJW-Y\YUE*X)T+)3^R3A+/+G*VA`,/E< +M>HK#@*<X=%N?_LUUS7]&RJ^>ET85CX6;^@%Z6OA[L?%HY4WE,8/U2C70*7?` +M4W#KH+J]2O'HBH'C[4%:S^F/=0879R])$Y1H/.$6'\_UM8&+.\L2=*%H0$]J +MCP%1Q2&LI>FRT$?7!,I[KX\0!ULW7U9D*00Y/P2*)!=,Q<#KO41KEX\QX9Y` +M!?G:"Y_<-2;P65&="]FCFD;:&0W40()OZXF42@'-UC=W5YA_1!GL+#S[\Y\Q +M-UUM&[[*N/>AH@4E-[?-02@8\Y]*JA%G+AQ!J&._MB<V;IO`YCK6MFAY`M!K +M:HH^-;K0LT&$J22KKX`!M]>"DIPY2*%]VY!$<&9'X%)Z9[[WB2$7X.O>UVL* +MHA!JEUE>]'%B&04,G`41-X!@5&\-]U097<:--R-`B?+-%%0RT;I-3$0J&H_K +M+J^F]I`8?(8(>P;7AWFUP2Q+W&6`T3*7MFTMJ2D(WZPJV\9Y']<K&B@<77E= +M<.3U7RX<WEW:BDOE^@.<5WX=G1L?A,YMUK3-#NO&^/7\\31BV:5!J<Y#?,-V +M7VN?8VDZEG*!W(8@_@N%RJ/LFO(+;?_5GNGK^5FMU!S1SU\L8WOQK-A"6(:: +M_Z)6_]6\HH#!C+W@^RS$(Z2IPR5X0,229SV\I]OM9.A+SGJ]142U'+3GWK@S +M@_>\1T&F21+6KWKZ<^S$Q7./S@=.=/X&"^O&$[D!^(_`7[9CHI"$%%;_AZ/> +MP2>2<OSO.!DQ/<]T)`WUWPH/-V]QY(1C'!"?H6)[X7/V6*:)"Y#U=)UL2J_S +MS(`PV1?AI\_Z/CJBRD/Z$NV+-,ES'H?]M'"7^(#[^;CL>JQ^JKZT1/0I%3K, +M!""HX(P_44Z=7LF*KY;Q97<'GQ,J\DV?<[I'53^RO'*L;:Z?OL_'+=68%Q)2 +M8P3"%('[NJO@IST.L.O?!RC&*NLF40>[?<L+SBNI;[!L6T_SF=<"^//,41V1 +M9&>QH53N?!&:$*[^)+Q+)[5%%Z\*C"ED5VQD2*Y-,[P]=I!-K,M9WU,M%:.I +M;_]B+U(@?+FP/CA](6T5^Z9V003IHY\513H"H(TO6L39/P-"-C2+O0/MN#7P +MEU%QR--M1H>?WN!2M]VI8$\VZ*M*,-*Y.Z5C0@M_9>B^!<45JJ&`PBI'#M2# +MI(5Z^Z?7>*(XV?M8BY+QJ:W"RW-J/KU#X98'9;7:Q6#6IT8H2J^8,#M:X"<G +MQ13-6%S\"_D2EIN3&3]M.*\*2N<(/#UJ,Q6!AC6L"4<VS8^-#PGQ3$<\F`4) +M"<_$I(&B.B<?TVK8`DI*H%H%^4F.#4;<X+&,^7I84!S)=0"HLVZ#N.XL.O5$ +M^*D$$L3/"K'>7B43'.1_`$9-W"IS3"'PK\BTXIRP=T8<Z8;&V\1F9]?DV0@R +M.*#B)0K_;220?A\9DVH0VNZO_?:++`D((E>2M3DSN4=CQ$+D8'HV_1U_CV?. +MB'>%A'?&>:)T*_L`E$DVU;:`(R`U,ICWA.Q1.6T\]]Q=2E.-L/N#%J,P@CA[ +M@,YKDP\QM01QIOY_X/[NL`$LMH^&E`H'?.K,0F8W\J!"3TUNJMQ",008+XUE +MM;M;(MC4IW&QE'\?)6=@!ZUW#YZ)LI3`$@1L9&.WWOH@K"KE8P2PJ`A2^PHB +M&QE,:[5>M9((1-53H/V[-D>):ZHPN$`9KS',Y#!?\JBSK)K8<4`/1TXRMH=0 +MBSEG8M([7U4WD:A<9L$>[86JMJD2/4P5%X[D7RLB2OB*Q4?`:E.C<].WUM;L +M%HBO;#O::"T!CWT[KKY+&ES?#F/<RL#GTS$L):)E@<CY?<#W'%'5*/D^01H@ +M07XD4R;IE9,L!0<3NEV*6D%.CV1Q=K*0'1E04B-&=V@ORTNAFAU'"!Y(O(;P +M$(`Y>/<=(+"3FN>CK2Q#>RI?_>A(]MJ+)SE^Y_A<="HJO3C[\?8#,U_!R?F[ +ML>S"^=.%N:PQ8N6-%'Y+'9F0TW0\O;HC&)<81?.4E:7FF+<6XY71.8.X89+' +MK>OG\;^5W(Q;1@F3H-OT9O-TWLYH*?T='`:NZ0@6"[LYN-:<%P0E0`Y4@3]: +MO17QKT1,*5;M37]#+Z][\CUN:LZNEB[#250XD,78]>SP&9"3A)77ZH\X]>X[ +MA&6(&?C'W9.N+@J`VQ_O937^H`MM2*G=8PB$JR\],ANZE5?/3G0+K]R=T5?` +MQ(VO)RB':R=T!8U5TGS>^,N0,=$LXQ;:9`_:+G:17'3QQ33X(-<],\CE8M1D +M"4"@G<KUK`23L:*O/'F'`JV&^US%TR-4]A">!5OA^6F9[%EDYN3,T[PX*7[: +M3&NM$_CO208N=B.X,SN#Q7>%JG:UZUZ%N,/+D_IVZX8`8S_0,L^'M>)4RRR7 +ML9'((S*%"A*GL<*!I]U5?2`,!)X[L58_-TV1FRB-'EB[ROFX\/MW'(I1%M@@ +M32Q(*7:!+/")I)B>"SZONUDCX,WL-\:I,1G5BJL>(S?T^0LY%9\H*A":FLV/ +MLKU]U\ZMMD7@>G^G+5V1;P!+Q-UYX@$EQ3';AW"3\#B,F&Z,BS54WEH7*`^` +M#H7$T@Y8`;N;%&CR`-9*%FY.YDQDU>3>IJ6;3U`)V'?S9]WU.7%-6R69^0(F +MB02R6%FT?&D+F!&BHWF,+T.T-`!%1@\>+Y8Z1*]8"E^!7\L-YW?653V@]CN" +M-.V^T@#1UFLW<<`+>F):Y1#JE:X91X4XTRGTHR/5)Z*Y"C+J04DL[\'OQ4LJ +M+48-_E"$YHO\\(\G":5LX%I61:PZ%[(-:DD@_@`Y/4RYD/"R8LA$I-("J5W' +M8FQS*]RO1%SH.U97(0I1#B/?17-74LPQ+M,W=&).)MW7:&5$3Y0UXDTX?KR7 +MHV$G>WPIE.YK3M`Q<@_9H`N`J)28DR*CR=X_`+Q<1K")[H\-"8&DZR8<\&\; +M^"E#JOF-,3=Y>7,&\JZ73APW\2>[VZ5;I#;VCI+38G`^&&&W4GV[6>2<.X!^ +M&T!H1,F-EOWE*DVZV\\G=YI&_`*)DX&-M5VF4X"D;07<&=0V!&DZ$55O>!8F +MXCY@)S!L9_/3*K=!T9T4B$(\28N]4`@\)UC?@&B04BUP,<W.A3D!SX%WX$#Y +M,*4U(SUA(O\&OAS9L'934,`B(%SQ,.4Y[@!#)^OBMH1OL.]\<I91S7!S1INS +M[XGIKS:F]T8=O*-XP4_QU8N\%]*R.SU3-%!XJF^4;RQA>U,=5,15Y2U)U/[G +MVR4^:L?H@_H-=GHN?H;N8;%WT/G#9Y<[&A35`('V?&/XZ=Q$?R@04\3JV&PU +M6+SSES@N.^;[9HS&-Q3!$[G:ATR<`]$&RVN_J2F!/IY4A/KOK2,B_<MJ$C'X +M4_@..S1\:**?LN8BX<%O9^?SD::U^(":S_LVN:U6OV:4'*\)1VHE@N#>6_-B +MG.@ZZ6OX#3G.^&[.5*<A3!O8"H:A5&9CN!3K2J<TZ/3/4,06+!3P#M907C*\ +MMVT5F,5:O?F00+-G+L[Q'J`SN;"P-Z('@GICMH1$KJ>0"L)Y&9F;0.^[2Y4* +M\S%5]N,IX-Q3$;_&BFXLDWVA<N'(?TYD>-JEM[P[7"?DC&4N](;@%,6W30WJ +MV?_^=HEYS&/WG?GUN^6S3D%FABQXQ@SV<R>)\A&M2]G&Z;+UBV.N\T'%VTM0 +M.H4.18W_YT:^-K4<Q%O1TGA$"N4BXY^;PN5(/*O3K4VU$B/[89[M,^P2H1O3 +M1<MDGV"B.P!4QCV\$!5$[?F$$UX3(US"/KBA)QJ:W*]([T6^2(;TF-#"A^Y8 +M>W!.8X%^C<`5!UWT018H!;PYHS7<]DP]B.=1"0]J7G87L@J1LQS'M72<WOOK +M3*D*'3Y&G]3`#M!\#<K8:4Y+.K80>?'+LSS>M>)4`9CS#46%5'EIV_0&(9\' +MHP%#]6]U%\V1`TD;-,%=C^#=K[2-BK7L;$L_=8[94@0FR](98:VQ>)`#>)MR +M,K2IM1Y\.!^&_Y>M'X.[1FD'A7KT5^TUE46^<4/]8=A2XU?0Q7A_J-=F'*K) +M>#;H:M]S,(52N>\J^N^DB2'\UD3U2X:'[_AT2M2"6-C^EB.4T[6MU$%%&OP7 +MR\R73/FZ[X\.!5[WI_8:,?X9)ETUU_M-_-P^#GE>;6I=F:)MC+1)MF[)#S*! +MCF/Y+9'I_J_.2=^E6EF>!G69(8`3$&X,RJ1O6U45`I+`DH-=?'E"$].@/C.G +M<$>K^P[C;-4<2S2BE.S5.)OE`M;^SOD`&T['0\<\]73UA1%DGI\(*A?&.$$, +MN)+@_?0B-G4.LW"G]N]DSE$W0$9,22WN4ML\IO9;C"'P[.>`9*<]TI#]T0XR +M'2LQ)1Y.Q9:6]9-9IE=1^H#+S-Y\M<-%P)=D+#V06=3*I`I!)LP6ZT=D!QVY +MO(BYPUS`JS)B8G;UV-,.0IS]+O$ET6'9AY.-[-;<E5;/##*P6@4#_W7..?(" +M`*6"*K54V$*L'>YDF'WM04TI;2!GP&Z9;(%(B&6!#B1D^X^\+_%L*"QNWN0[ +MI=>"A4;[6G!XSN]#[6>P-(M=?+`+E<-\V-&@N-Q*FAFW1ACY&[_._LV/#Q>\ +M<M$?YZT9[KX2?!89QL"8M'6U.97_TVIQ67P]'DQ#D$Y^->WY:,!0&17]C-@T +M_IH=J*#>*PZE.8B\1`L9&5HK_:W45VPV(WZ\F=&'0QS!_R2)_JJ8VR:,*(N` +M_DH#WB_O$D?@6%^B=NJ74O[/WT_)U38,YT4.T`I5F68(H3_"`9$;#L<J^HO+ +M;IBN;2;"',7@>JNV7`T+5$+IV[*3*Z@LD-[1J-SR:/K6>Z<9OU)`IRM1"#R' +M`.[E9SDG*5E4/(XE)4M$C-+ZKY.+EWBY?=6,^I*V8P!0*VQ(]BXP/TZ4YVBW +M=K,('^Z%IN--P)C@^-J9DR),/"`Q\3QC'Q#6#'0MUPI@[NT)AI_=K))C5["[ +MMHFO3IW+P=.!&-%_I/%M']G4Q,Y8OX*,)0QUD@@%!/:?V`[W[_@"T;62TS+C +M;G!CO>,6,@PM3^5EC<>PG9?DXI0;J4#AS3L@1ZSZ1N,+HB&_=01C'TTNK923 +M)4$]S[@$LIY4A7F^6_P@+!;T<$DR1_`>&*K=@J;88#/!,!9'=,;+@;#WR@=C +MT<X%,8*YXO@_\)NON`U$OK-6VZ%S9=&E7_Q.W+)^_6$=MI`0Q/L2],1)#?++ +M"I<7(1'JV19CH\WC,`,=\CDCV*K_1V]Q&"T<PLZ?N?UFUUKLO5KC6H<M?VQ- +MADIIA/+_E>Y&8A*\/KU"4%P!\VW60]-O]I'&RIDY[&IES4>FQW;R>,J=TQ+V +M=UI7W&0KX^5\')S>U=T;#S?0*X6UY:9``YSL;$1W",8Q`0MWJ2'E(J4-5Q\P +M48:VS<4-U*B.F;E$'SF\1;N*R[1O/M$<VS9[T,UOB"1KVW!/X8X!7X5=Q"R1 +MO@#"]D/?]RPK(-:RDL'O&ZN(_;/-RW'24:[Z/SZN0[S%3^&E9^)C<:VQ6$C$ +M[U\2W0X"S=R]S\_G<L3TC7MV,M9@B0;0>&V9O`\[VC?@H26=339(4>>.P;E' +M&TA93_T=I)W?:!T^"_,`\J^4/V<_2MQRVX)``+MEI8R(![R+:&)"#%#[2RQ2 +MDE.WH7X;`^N[F6?KP!(K3#Q76JX477<%9[IUME$+Q,T4D?!AZ;L9-#,T;B3' +M'(1#!.?0)>,))S>R7P=$-3N7PX[YQ79XJ/VKN0_VF15^A3MZGXX32%O+YP9O +MFFTJAP;V_,X_N:P4/7DR:8V"&D4)#YV>J'UOH#]_+L^>D]E.8"JN\<E_N"S( +M)T9_G'6/1PT=7F5@U;_J30H$4;=%7,/C1J'+:8$O?Q8/N/_%6R-!CT^@,^,_ +ME^J_?+9VW1_K^(,3<J;#,(CZK)[9XZ*9'Z1X[UFO^RF_[&N8A-76XX:610H( +M^;DNY%V\?CWW'^J_*[4@W-1[NGXQE!(9%T,3$X0$H?$]J/M<^S;KI=I;*(IV +MP(C>L^Q6D8(QV9VZ]2#>=[.'?\=PP_.XB%-NW7(4HFCCKFI3BJ'=%DX$[</O +MG$HVWB3)F^YDOOR'%8]M;'1::HY"YK1W?5!%8X$%Y3;441_J7X_OBV2I?+HV +M2/]X"N/TXS*5_:GEE[Q4RG5W4SK37HI!NZ&^1\@7.RL16J!5$<OT(VAMV5GQ +M,0T&)<WE-YY:'WKQ7'PD1L/^$^IQO-)DSGZS6_`Y#;<A7;H#;F()L+I$2;%W +MBQ;(5\.N+R[S5/BAD>JS\#98>XFN;)JP#3,T2"!*<H'J`BC3+)>5?YZ,V+7B +M"$-RJ"6(<-467.9;U*L7W5C#A=:NO5&T'L+\RC:*;;-NHDW885C9]D(*P9HU +M;K6?<XAMW`=5`T<E5J8D9FOUPIX)_CAQNK12HT?'Z%M14U8\)[4`R]^`S441 +M/DZ!!41F17"_+O^2T""[2]XM]5C4*=ALY:9\SG#PS_^W/7M'7%)3\I]UN'.= +M^ZKXUV1)*2KFQ-M0"$]I`46;AU,42$)YV\>LSI8X">7#,&5>#H1D)_9VE2!= +M_B.C$3",_]^\>E)E$Q1.\(%7[SG:>9<QP*EP%[(P3J^,'.69%G7[KT1&:S)0 +M^&_P'4;"S_P"^X[94563,]I@0JM:_[\1!FIZFYXZ.:KTVRH$-]%M#(,[0+W? +M[YRSE)!^*-E0MQ*R6F?TT%*W6?;&9'!R80A727^6VQTUI%?IU\M4W<:X+[+2 +MDI]#D:.(RBB%F@,`XX^[DO9X1GHH:Q5LAR#>_+Y0M_X72X^5PKB-ZR29S0RI +M(F>QELAWGN[]:I#;Y+O]7.0H,Z,J_LH0!<VZ`K9S'(JKB^:=`N"Y;$_848M^ +M19-#._EVQ?:U-A6IOU*)D$S@`&*WD6^@*=//5O^F_Y\F4IQ5-EO7F'^Z.6IV +MZN;[<"TFJ!]%5VMN)T%)^0!Y(=0ALQ5]`NE&[6>7="$&O0TSI?;.1=!UQIGG +M)\>EZAYY8D\!3NY_5NZ:DRKQ2T!;'!W3G!KY8G+-,X=-JL>I0O]BM7ZE=#Z9 +M8Q3_LQ\I1I^/M!S#FX*,_0X8SY/8\/(+U=;4<(V!P*^IZ%%6NX<WOAE:L:@B +MSWA%5@MA*UY%D:JV.82W`=,X[0'N66W^/$>-67_9?$3$`3*CE:KU[AJE%+@< +M/(7?SGEE]J^7/8CP^N*"':BTY&V.T#./O*?@K&="'>!Z1_"VI26M8I-&974W +MJK4(2+Z[B?TQV]*2%BE09$CDVT)JD2H3H7^N:O7X`QZ@2NGWKM)D@TZ;HX9[ +M$[;P^?'D.MBBQD."=UF\:0%Z._D'H<7`MQ9:,(.[L[K+,%SY</C?B5;>4\^3 +MWTR[PE1W8"8EP5:SZ@B`'86W*:ND6"C2,WN_HO2;-T?H5H)4;Y)*.$LE<^Q! +MUJ+)8D6WNI@I&3Q,+G6N].YH#JQH8">^.YM)72FUVQ'(T%6.<'H;TGS.6@3^ +ME*Z1]$?<W1=<'XK[3OTW`34!D(>?N]_ZJF_[4MN'5&!*TS%1"^=)8F.%5[L) +M!RY9!5Z='ZHND=PD-M:MH]^F4L,LEL&:3[%Q;O+X.L@L869(R"3UFFCG_LC_ +MQ,#B)WF*+-]5&F.^3-_C(X9\JP1=;VPO;,^V-TH;Y.:X",/>0`6.OV"2W_LF +MZ_Y:V&N],ANT$-Z,&TK=VMG+`:BLN^^!W;M:!AL%NA0BT+BB)$1G"X#_L&Q$ +M&QZ!--6U'CN0D!@[!R_\U*.=R;$&^]V?^9'J.4I\N2>F;%"F_D9L"_@'S331 +MFE^TD9"^WZE56>G3[-1I>M).'0K^C%JV'Z^@JX$0NXH?$#05;Z_#G!@9(_/O +M.T9HK[P0,));RPXX?S%9*%/Q<I7'(JA)"<7-L4LFV^^<P)7O'ZI`-,"B\[2! +MA5H0OIZFMGR(GP-QK%5&$?*-^N*`^N&/=!WW/LM-*-@L5+JQ3<K7DW!_CM_Y +MAF0C$T_BG`Y.BP*!11<M.[S)O_V-)VB^.(%X!GFP619AQ#4;/9I5*WR2Q$NF +M+1@Y-;_>UOB-Y7:)X[377500&!E);2(WC-"LX]K'[]5_$<&PO@8/=V>RA:\2 +MX2=HQH0"??DK4(;6["27%%UQN!O6M+8;-*R.__H0CWE2Q&0`Z.%#)8<>+JBF +M9G(L&7$RVY\K'">0')X7$D7<?#CR$^JT9C"JV;L,!&42Z1WE''VC2*?O]<'R +MND!QGD@]GZO,6OUC(!JWE=E`PA?C^+]@:.'<<GQ_16$4$F*E&D%,+L.HN:]3 +M6NNCSV!;*Z>;A0G7%4TA5(7:\YJ!^],H1B9!01^]W($1\_MU+6F&V"C_*,%- +M7V[C)2PT#^<:/T?YF]A/9#Q9T=2;&A`,@49_2%8M'Y.6^Y;QTJBB;I&I'B_/ +MW)B%4<8H4X?7#M&*N0CUY?T:]Y.4(:*VI-K=)/UP(PWI6)$S1O<J%6,!?T[L +M8=>:JK@VG_`:&3^O""A<BZ<''J:L2X2#%:M4GW<3&F^^"4]S2>6@Q6JCV.;^ +M[:M\GU37J$6ZE[HDYNCM0T7II=JN<B/(5=HZ;!*Q2#+QO6CZK*6!/<PO\E@= +MND![K4RN"&-1\[AG,P%]SG5'<3^M#TDSZ8-%C.NV=OOLQ>@P]]G9HXTF[7+W +M>2OZ>\B:'PX+,,.GO)>0H4+M(HM5\QKX.*$"%O#48T)$6LBM>97$6Q+(=G6' +M(UC^OL$Y_F!G_B%P2?!?3\%'VI\G:APY&%EC[/LI*>N/4!01""54C_<&Y+?U +MA(/-@H:0:V[[_QD5%:.U.@<I$EKC6%PCRVZ^]!+N(I,/NW-317UD:T8]7\(S +M`BZO>*;?)^/F2;+)KE[]1,G*VKW]#<=CM4A'^QA?N=<C60MYK?PUK"KP5#RF +M][*YOBQ)JURR+7CYGKITZ]S7)-(B7L/51)`$18Y6@?(-X7R+N0KT=^V1[*$- +M7N`3&\0B6ZEU?.'1P()OH&6H5&<-Z$J(_L_-4^PY"M/?HM:%JBSS6LJA9]]/ +MO@EM+%!/`?7<[>QAM4Y-(JB<XT(MX@P`9R'PR-$>(P0SZ3(97;-NPZ'</BM) +MC`G4!@-]4=5-$?-!UI>@Y2.[,X&'S-YR^0+I(1,A4%-=Q(2W/AQ,_JEAX>V0 +M7T;_*1^EIA+8%TH2I"RV";6I_R0:P''*\R2T$CA<*/.X;9@4Z=NO!BUY>!!9 +MN9[]]]A8^YF8(1Q%$N\Z+`)A9Z&/^:G9P<$FL*RM>T3(?@CT0J^AJ<Q2QX-O +MVU(0'UU$,EK5<K?N!+FG^PX#3P]LYY6<B_%#;4[Q<\L:_H`L*]8)!,Q/S4MG +M.12"%3Y#L1YO*Y.]6$#;W$G@I*3*:1,)\;R`\R-^4*I5+(+F<A>\28`*M2I_ +MMAX.F8'#9'`42GZT=9TI(C^/2>9C.A3^LSW8E/H\M_DQ#/$TLFH]5FC(Z9_Z +M9O_8)79KRDJLJZ,7?"]O22$CJP3A?I'J*DM`X9Z2?3^1WC='[Q:C0"S%LGP: +MK]E^C/Z&@:0T\U/W<O>V@OOGU=-VZ:QG.*57,[6!I)KZJ<)UYQD,5[)F@'Q2 +MC4\QF8VO.!19SC+6I`JH(MUOKD<7\?=`^8$2`V@'N]L$9`''OE<NWU*Q"B>> +M6Z=:UJ,P0=4)PB^8O(5YKYCC'_'"[U^P/>/72(2=LW>*_(@.KWT,'!_\UM)E +MS-OIIMI!J5]Q770@["M8:+O<09+SW=GP':S=E,3.RR5CH2`8WTO=7PIE/U:M +M;&(W1#/T%ZPI#?YTG[\D'^/@A9?0ENGB2L/0Y;AM/D,OQGP<K=6&K^(K.,A# +MG7TSQYG_<_]+9G9K?,!(4$L#!#,``0!C`(RP#D4`````DPH``*(:```&``L` +M4D5!1$U%`9D'``(`044##`!`G@JPM?>XNX3N=I<;[7%,52AP^O0CO`<ID9IU +M%=2(2:(J+SA<XP#YTE@KXCAAI/.2(OL>)WN1?Q!&D:IAJWZ#6MJ$6HGYI\J@ +MFT/%#YH(/O*W=M:3],9'@UN0^LA6FT)U*$)BT>9T7#AE@$P\_994ZEV!&,*; +MAC4`]/0@[(7@[]COPM'1;;S4244HZH5JTMX)FFLDES45CP(X3=LP)ZA2G3A; +M,JQ?4M5OVM*Y5*X4#BZD!(1"7E5M)V3[K:LR-5;;G'CTM9"$,Q$2+$177)P` +M,1QL\LK$Z!;7A4%VA7WYI<I;:-2H)I-X.1O,7<P[J_NELQB;I%0-H`&$%0P$ +MT_.#O:%B>CX5`OF#%M5P_A&4@U,+O7MZ%<-8P!$#0O/>#,-V;G?I()ZQ$KF, +M4"P'E-"#;"<T#$-]V*:^#(Q+$"]4/0-OO"E_8Q<HK/X&%=$GZR2*::,&W3^\ +MM;LLI9DTCGFF,/)HHG5%92S\Y_7\23RS!,%>MDLQ7.6INU=@YU,JW5#^K>.0 +M<7-%[F;CK+N*(3=H9R2.VKXAZ\&C7.;%0HV",WZVP+J=Z?,^EI\+9;]P/\K# +MX#(\%_QET[K^E*%T7>-(="O>?3("2N;R)7F#+9#^VI-!$LI,TTKVD0Z]F0YS +M")?=G',91+J!/'H6J9>QM*84B,+NXMNY21`2?O)RXVPI\`LP)5$`$J#M'1,[ +M6F^2PUU'2J->8M74#=?,`22F!<"L"2#S+ULZ)Q)LW3!QOD)42(1E0\[J%,,R +M_J8;Q!%!Z<4#]@:@>L%_9:LU%4=76DS?(Z:0F5M_XGS\(K[`T69>!I;DW_+2 +MG9^:6.O<<B%R;@O!,@UY[31^')!0)T9[3T[)J!UK!@VB=L_TI]C+XQ8O_*_G +M\+9"#45B#]`%6M7[$0>9L,FT\U<2B[0@Z^8L2N`K_\6`_)HY*4DJ:S%B$48V +MCXW7,)!-@XS_O8,%E:3&;8_D<JOG@Y:8:H';?I9OUV4IZ\QD7KRB#KW0#O_9 +M%.3[J_D(%%NCU]G#!G+"M.7Y:YOF_VDFO#*!BUP;;T&X1SZXFLE^;PR:.=!9 +M2T>O'!:7]@X>1;L6-F>/RS<>EI-?#+/.4W$O=9&$ZG?5W7]F2*A1-HC@KVXD +MCER1H(%4UFO<52`:JC1=)./<O7'ECY/L"MGA[SKUH.S'YFB9FT-E'^*@-/[: +M)D2N]U1"\78-3ES*TU<8>]09K1"H!]))-2[7!;\":?AVULH8DH#EC4*4/`(% +M"%>T<5[[@6/Q);8?7;[+>"4YE^.!F"<*OZ7J#/!]VH3'\`TS*FYV&E0)Z$*, +MT_A&IW/GRY@[#"RT%0E41I%1R1KU_`+YV?XV5=C^YXA^F:&1B,WL#4$C?[\% +M'-BHH/\V[OVQ%WO3-(V"7>_;)\;=3FH@5;EXU^F?B>#VVCS0ZFGF-_WJY"C; +M".E<`<]@]WMCIER#JLH.0P5]DN!]))Z"T48Q`_V`%7*=H3T"1Y\:K_B4?42# +M`5(GU!T71QI?=HZS8Q9".`6R7B#FQ\`L;<M!@FIDSHRD+CPA;%<`"W/$.=L\ +MSA+%WD#2;)M_U6\'.J<BINZ5D;NP:%,2)O>+`DH!^`$8-0I?)J;,8+[[9"V? +M'RLV5BRMU5N:N'/4]$@.,$,3RWYYQIA8W3-:=,X)>G`,^&VF<UW#C;9U@\D/ +MV?JF).E5;R]3E"HECN/K]VBV*0T]!2D>^$J/8R7'4R=OA\$$RA_B<=*ZVJ:4 +M8#7K"IC'H(YH04IGZA?TK-(*UXD\*KG$Q!7C&X/"!6&&T,US`$SN8SP-!=\7 +M^D(M\`EST!G<\WL=M$@\(S-TCTHS3.1@H,<N$O:DSZ+GK\J')7JE//36^R6F +M:JS;@USQT>8JULAJ?JM*G1-A]=<J[$D*Z2K=ZNP*D!-%VHZLOLJ*5[K?\W?0 +MO%;UR48P9JQ4^%$V&T&;8PU\F^\TVJ<.G*E)T<:%F@7@5.:]\>(8NW-97!<: +MY8+R:@.W3`/;$(1FRX_H@=-"T]N1,I0)H9N(D!;!'P6.+5:8QB;+9<=F/($0 +M.(&CNDU1]/J7$\E#@DRCDG::K==*)4.K<8/TWEIY?0EQ:2.!9WC[<+-L8<QB +MOD]SF%^DXNS98CS[[N1?O)L^SCBQ^-[6S;J>LG"1>ZME#,F?B,Z)0[/=XD:Y +MCTV9IS&8(2>.@_;2]97)/_S2.&BEA<J>MP[7]=`ONU3;H.SA+)G2QY#;D]&_ +MAP6O/6VD8.R<-C=/'G1T@$#N&'GYW9[R`B/'U53D$G(G7Q-C5E;?04+<8#Y0 +M,C5*YKJ@C".%)(5?Y:"MEZ3^U358;%933T>D(W5IK1M/T`\9C0G]XP?25_0D +M;A\;5+9R`2<>3$9_$MD=:7!.,&18ELX33.L30*'W(>H[@5/:DE>NH\VWHOU* +MQEJ2),L&6]$.C6)^=OR@;"MTK,;;)75W:V16%-<\'/L\M(`E@OIRW505!'O< +M'U&*W[B83_PO'1`S_@`Z:&4W2OCU;Y,MC<0P;B(5.J;T$_I)I7M@A+R-HDJR +M'X%)#$E".:=TGX:5N2%UY&XGJ#OMXF@I4[[7:IUE>6]Y)H;[UF7IO&I@\?EU +MXGX/6W.0U(+JC")A]_X7X8)=RQ@(@$(FQ@\LZWKI,9Z]-L$02&/@MEP7WS:O +M&?,)S#2&VLM+1"AA<-\\N)?U*!&DA0;S9-=.1>3Y)A(3$#E(`.8V\9-\MDI> +MU:ZI=<2Z=?`T4J@/'9)0A[!HC<FG+CHTAY`@D%!_`VATAX.$:=WE$HU*:7,Q +M+MJ6$R(F%0P2AF$V4Y#IU_EQUWCZV4^61#<1J'L\A8`^"2ZO!=;58!B2++U& +M`WGTZ'KAY#[=*UDY"[_XYEF%R9T8O>`,G@\OS@&_T(:H52)HXXW+>;LR?*^- +M*B9#^1>36=#.$>+:_?R*[8*8M:1ZP-RP#7$1HHX#LW$QSM+YF$YMU/XVM'%= +M?.".C^;SC3G,XDNJ@"X6BQ47WM37AA\-ZPK3WV;=SC&:TSUW2'5+Z2IC]@O? +M-=8/E-WF=<4/+:.0*AD,%K1(R/)]CSYD,S?P+B&=U-#W<1)WJB90OL$9M4CQ +MXU'9WY<&ND]JX2S7WM4.[3?=,K(><V&*^SP)I/J!\_0%K,Y``C\X>Q\<>'KB +M[FZ7PYI%S*C-1O?W_-4XN(4UZ4VB\6(XE;+IT+1-[9+%I4[`?FE@?);#/+5` +M(?6?I=BD)6]2@\I="1VP?.=<%T$V*F5CELFK+=%=4-X@J:OG:?`A_D><VA2\ +MXEB4IUJ>U(N6B]]I'','TBX>KR#18BZ+W'CATI*/'^<C#LRW)!2V""FJ^DB= +M"3YT()T.PYI+THM$\I%8.LWCT'X^^.+%I)08D>WN=02^3!J>R<R\B:KE<!OW +MB;R8:;D#NJLG,*\,&AY6[2EKR\AB"6HH1\)X(?1CE_EK^$Q1CD_F^.I-ZH%_ +MF!"YV<(V#BJ`_NL;W6B)H.HUII8'U:&^SS:"$]SP$'%+=/%,ZHHS^8D)+5#G +MSH=J+_^`.N]O_SVE/7\B.9*N&PC^LE)K(<JR&*/Z`23LE8X[`LH0N[I1A4KD +MR5*4B=>JVYB3="Z_NJ\D36X9&#J-&%*_X[9*_CT1N8(#LL./9RZ`5N9'E?HP +M3FD%[9-<Z:;*']V,CFRE?'#C6Z%+T3_O4$L#!#,``0!C`*>+#D4`````W!,` +M`)M_```(``L`8V]N9FEG+F@!F0<``@!!10,,`"4$,K@8[S*ASC+-;8#X_B%V +M-ZB=<0:\GKZ+0K>VR:P:W`JIG&+];7IW]9+FC.TADG&B@\[Q<:5EPDYQEL:E +MZSMUUQO0"B,7389[=`7W..%8;$:"C\:F47Y%JHLTWIF<$*T/?>@*OQ.7NPI# +M`J/OS;7J$T),-*B0**`7G6F94GA##B1J0@G#CBJ2M)8[T]'EI:\XK;HV07A] +MWKW$R9[Y$VNRA`/TS_$R">P"57%!N0D`-'=?$QJ=1;9?:>AP!^][#&,A0%+- +MN^7NT`9(IQF]K2J5+%1">Y)XU\A.-$#X(38F=9;JX`PA>+CPR-4RT3-HODZ4 +MXIG7-,"SC=E*42$'C)%0[2=$,9L3Y9[_;Q1;F!>N%`YN;Z*-)\$E'2T'&[6G +M/@BJWB4Q]*RM4V%/(>&ALVCL;C6=O]84A]>6?&?54>I(]K?FXDC7?_SBH!D% +M-G4+(/]&-A^(6&8#%(7Y6F)_9ZV@^E)#P1=11%OO2OCO3S5="`&3.1I=MYI- +MK2.(U95Y4%R4<AMJ:;(3H)QXJEXE3.QV3P&)DF+Z?U^"F4$L^D#KQQ9DO`H/ +M?Q<F=ME/5%.^_2*L&6V/H'_8\7$(&+2Q&#?A^9C:=I^^M8%>5S[**,\=IFDR +M!HJ(C"X"SRJ/##9JU<-YRO`E+(Z-EV>,5!$@#GDM$R=#(0,O=9$R28&.-4W. +M`*O&RNIT3?27-67FJ+-J>LH"CNMR2$=3Q#,YA#`LW/84>WUMMQ9,P8QK)D*, +MD23_`U5VQP]%XKBY\'F\4-DP-5[HL=Q5-4W!G)512]H)2!.4VA6_I+[Q#-V` +M5KU7V`PGZNZ8?U]UGJKNDERQQ8/FK%\ZF#ZA&7@:N)(IY<&NOS$M3A'BEQ&J +MF6!I.G@RDH\.02X%8;PJ24#^K-&RO%2^I]G05>[\/K45E9H@:-?YCY-JG>#@ +MR88BRVTT9A'">\):D.6BO0[A,IUZ$]Q0--/4#>'_:D`\5F0^<WD"M"8)IPW- +MK[^JLT:\%TY!N;:94A:WT8I<6Z%/[:[G3M<6QO^R^:KR_[L$(%DG%I-]HH=H +MM&'F$45.P7O_)_1HWA],;6KI0YC((L-4;E\]D7*)G[M):)F;5,;_PHS9(1@\ +MFX`Q+STN;'N;QP",JB5OG+TV6,95M,<X/9SSA#-4LX@#_NX4T[8KG,2N;BQ0 +M?1F6(Q/.MUE1&!C@E"XB`&I/<^\7G`5M3`TO^B(/@E2=JA(;^;]6X29N#7(R +MV?_@3'QK%E?>(I_3DQ8%-'#IC7@%-Y\5Y^&I"DHDBU'J7>E7)4@Z8*TV4^"$ +M>#\TKI<VS+4566G9TT[$:A9.!/;316X@E*6M24MVC#F)M``3GKF[7?N=&/%! +MSWF-8U^FOY+_.$V*JOUL/'<XXG&D$,[3N@S[Q*5^-Y`G2=)S8,_RS&.D#R<B +M88HS&KZ1N955LINDZ.""R%0SG=^.+3N.F^6<7_TWK$0"B&9E`TW0&'N%)8@5 +M8BHWRRO7JR3=UV9VO#DGM47X3=64Q(5QZKXN$2G5[UV[(0Z:0/>(<V9D9TH8 +MA'XV'JNR]7.HP<[?.[?.-F\FH[-^#=Y6Q"G>`AKIIVX\5_[U4]E[OXON7[65 +MI$WWCO%(%32>AXY!E=:&\)RSIW:)GNU@`^,"OQ[LXN#[(HQC1Y\8W0522$L) +MA5-H/3]./M%"`6<X[6?(QM+2JZ865/80*`CQO<=16"%X<3H3A9H\6F,+4!XS +M;[;#)I0UL%"WM8(R/@>NE.9V7QZ+H.*H\N7>C!.]OH$NJDBMV#Z(57.U>*)/ +MH2OU[CS(3A(K?-=\I>V3G7M20G;VAE@)L1M%/6,>%#<+;3!<Q&3TN*6VL[NA +M4_`-D)`(D(S!WZB2GKQ)L$OV<^OP^U0+??K]F3<%97Q]C>Q#;#98\EA!DN%( +M/G7RGOY%9S+'&YBZ?X!W<`[K""*RU3IT>\WK3'?!.U*B\'FZL`4D<+:BH"?D +MP>M98,`<O0+5O98."X<;$C+B=B?P*59U*K+(0$F(7@NR"!*`!J'L(O;1RN%' +MIQAN5R&PT!2,/)S3DTYCX)1*^#Y`0]V&L08_</1\\)8L_\UTQO[Z@*2;+''A +M@^O#+J.DU[%EB^RE7+K8H%\_GC\T838W$%`5('SOH1#@07/LG;9^6_?DKH=L +M(BRI4,$Y!DEBG6*Y>F:%?&/9*XLUO9$2=(H)WVI\V7Q<<+J@8VD1%/"KEFF/ +M\\S/0\N,#.Z;VL\5F`?B:Q+ZPB'$<WI:DK[>9XH,@GD-<V_\@9+#&=W5])N@ +M4G'/[S9]5G!GK=X&4+&0&RP?@&*%EJ0N6J4G3$@=07U\*5/9G3";*BWO6[G[ +M'+;KF/)E$EV//9=LHU7&/TB]S;"$'IJ1(U^`86P=ME/2,0%7]7NHR+=82.6? +M6YLM%W!(WW"VH15B[#[^)PR6YG*;!9PF\G36T.5"W1L`JD33T"WK,.W%LBN5 +MRFFLR+M=N&70KX/Q\,V'2?L/@"-P'X]I6OB,>988E!J]Z3(*)?U.H]9JN_W` +MUHFHYEK\G7[(P"^*;]\,4PJM`6P=VJ%R*)K.7J02,F_SU.*"#N=1W2J>BXN, +M4F;+QEGT>A&/=_PX,>?=O9\*(#_;=RP,W:7N3C1HBLW*D-#\(,^RB`XN1!+O +M&?RQZJ3K6V*1I?P8U!"@WK95GA4#)_G'3JA:^_2OG.10G2."=\#7>T/^A-KT +M'.\[Z+VQ4.+3G;<7$=J#N@)O9/CJ1P9?W6';%,&`BGU:P#C12D<^X.SAH42& +MH!!9U][Q,*U)!:)@4_,F0IX9UVD24RJ(24*(,WW;NJV,CCH7??X!309O@/EC +M^9R#K'ED?]E&JJG5WT28$W>LL'%EY4++1O,;:_!VGS69VKPJF.W6XW<_:K:I +MWV_ZJU5B%#BE4LWF6!B2HP$AMZC_KW?L6@>-`8"20;CL@=OEQF(\GU?;N.A& +MLY6`87[V#%YZZ:18<<`6ON%_3V]0Q&9:A(FF8K:CC&=\L(VAGI`>7\+V<=[$ +MI,M%D@D9I3,W5)J+[4-T72=G"IRDW=;]'J;<7*@BC3JO?]$.0X`"%Y^G4P=Y +M%LU)^>"EDH'!K"<K)3D(-]1W/K>F6SEG@]'S^=-8''"_V38M)Y)%79'OH_C) +M-&&K$^QN<J%_-D3&S0D2[`PTWNL64&(MHQ%;NU_U2TJP?XW:ZHJ(#'FQL;8> +M!Y0%`\_NA5M\@QN(\9J3#D88I%*K"0+\^9$XB2TESO0J:OS/NZ+^3=HQ#]C7 +MCR85[*8R6ME$<O><SK'FOWP8`B&IR#D=;]<^DI:6\>]D5M&.PAWW!P-]MHW` +MU<V!VI9T%"&U"?ZI)E8W!;F?CN&T$(?5]ZR6$Z*,$W%7D+K$P6]\%S=(56I, +M2M2I;ZH`OI?NJWYV01U0GP[SF-LPY73?Z,(;YOHI"F"$/+B!(U$3G"=O`DPL +M9?Y_WC:]VD$T%?%LU.0O=.M^C[*N(N!A.[C:/M*&9-ANH\PLX81+"D'\H/'3 +M"'ZO0:H-T/Y'+7/($),P7C=`7C)WR6OLYZPY0:%R*45?V_UV94UO>F07T*?> +MC^3&DS\BCU1Q9U)&PGNBGLHNL8)G4S[=A)"Q2Q?QY,/M!7"=>(Q^^N#R85@7 +MOGMM>D3'+376&G3X]TKB3\%NC?]`:AL&O$'V[02#8HSJES?^^>>U4G4(7#VV +MUU+")]5%3Q]IF%J9Q?<<E[=*:HE__7>L"R+@GA/+PM\SWTYE76C1C!0K<H)> +MCXQ%F[40)Y06@)O[WLSAIC.$[C06_NC/0;\B%'JVG@.KX?!W8<(/F7+<,W6( +MCPBO5>H@,J,M11(=@N+$<G,%[/D1ZHB_4<RW`6Z[.,&IR]R``(8_$S."/:2> +M<+?AG-PH1J9OG>5$/HU91;BP]`R=J\45<V2^M'/T4B<!DV[H3`)9_^P/LJ`/ +M!.$,,/*TU0MI],P]EO-B+\J)'37QQH+T42L5$\`WRJ]-X0G]-*:E6^PN/[PL +M<K?Y!OC%VZ&Q4!R%'+B+%&,OK'Y"/O&I?H;%_D\X!OZ)A+CL$[!>;U^JBB7` +M-M:=>',]?__@7W3T9(\Z1B..4FC1*I/%PO%*+$$?PJY;/D$:QET6*H>_#S6M +MCPFP,3$Y^3@H*KHXXB(J"H0)I'5O#FBE,6_%>L[KK$S"']7!G1NYIFO>J2<! +M\>14?5CC+/5J"Z(B_XJ%_N"E!LXGH86A]MR5GS)>.$`C!1`4]%1K`H"YZ%Y6 +M<54=:-SK6]Z(J7RRFFN:X*R;VM(@#[V,X\.4%9<GAH>.+B.<^#`G`1R-WF9S +M.B!#S]>6KH5P"'+@,>O2:Q#X6ZKPP_/W),'"V5.P*5(*:46SKV63\XD<_PN: +MJ^=86G".3J#`-EWS&>.B0MTE!!7^U>:Q-,SE96"UGB<4+XT"ZU;<\\X?<=8A +MO:UN`.!K5].Y>7C["Z^Q.)[$HC9[9BB&9`(Q[R;A:"_H"Y+5)$<J^T_&"+4P +MUVK1O$<G1OX<=/*)9E0462YYZ+;W0H'V'$9IR(C]ADRP131?M0\A8/5RG$DS +M""4CD.Q$3E479`M736X8K\AX<;01VF<,1"+1G*PU53',O__MU_6`+3J=5`H9 +MVGC!_.R.[LEUW&89IC%JFU97)Z[:J?*(5"9V]44G4D;>4Z^JW)#$?<%&_^4D +MFX3@OV$DIQ$0ML"^>'O`A<O>PCX?II7%EBX;,P4M+52;4(ATI[EZ,@D>N=L@ +MSVYX+Y;/YJ2K6ZZN<+>O0-(6L-<,G7J891.;@="[7I%4L>-CO&4>)#U^5Q4R +MQ$BCBT"!*C>9,[K9$B@1]23Q$#SWFPJ7\JKF(#.OR82+=WC^5"P<<N7L'@E* +MA;AC7V\=^PE&,4!]TY/]'L"BKZ?:KDDWZ1=0^ZT<$V,U6M=G&K2FSU*F_5:M +MU"^81K\J$?+'4#_0!D[[^/&F_U0M)_^P&`7,YZ4@YI^]U?(UP;MN;.OG7'K< +M+A08,][%OG$7J0243`((,BY/WQ&4R+T7O`[DHO$VO:VLC6H]H4EBIWBT1!!7 +M].@6__&=9VTSX]S="L&B#B7ZN!D/Y56&:6*HZQOZM+2SFBE(QHDFU0Q";'1O +MX-%]H7&H\0;3:?LUCZN3*U-]">FT.1]Q(E:*,9AW-0^0ZR,F'O)(RA)CC98K +MWLAA5LUIH?B`.7K8H)-OQ6?`\.K(IIP:,=H.K#TA)H,I`031I\ILVWH+CB4( +M(J=D+C<@3E-<G$=#7V,^]&^P?[/`+`4F-F8,+CT'@>"Q16K#U*>PWJ$KLW.K +MQX(;W<ZE$D2AR?192(26702L<`-P$E7D*-*9VX-E66L5[H'3D(2+'D<@;5O' +MLO]4V8`P/P$9%U[_^FI/9>O4X?1PZ:..@:2OQH<471F&5`$KGJY(3;OV7O.< +M,`Q4O]UK%`&&C(-10?X9L[I.9JASV,P>/A2E%)V<M_#QPYT:_'*WOZ)?B#J& +M0Q&!_=[^X*X$?-H1<&G"RL!S(_T73M7+`_L5<U8-OFMR:+ELM$NW+A<U&77C +M[P1U9&KIL7>JVJ:9V_G]:2@8H&7CC<1H2W!F(Q?LO,H-B]H-C,?F-.G(&;*1 +M-GX4+DGHVE\<7H!?$DRUBM`1PEUKF[=$`3N7#9,8E"3X8L3.O+*_G4F%.;SE +M9`^(H]&M1"HT<GC(L->)>W;R15=ZJP!IY7ZS8S\/@3XE7@S')K.8OO/V#=HT +MC%'5(86^FIX@N5B_G]#ARYK[ON.N;'.=1BE5B/N=7X0L9!9<Y88@M3'Q2PK[ +M-BCC(;EYJ3AGR<T)309/6'A*)"K28[0=-A]`&CXI>UUS,4/_NG=?G?/_E>![ +MLMB;;I6DJ^]BN;Q>IX"+*X`2/'%7Q'N#K"B*PEMT>92$=A[OA!V94LNB^.2R +MEM-*VM4E[6GK(XA3OV5XB48-7HDV$]S\64LHKVX![WB=>R+(=EF]-;'WBE=5 +MDAH4*2B&VOV5G1%8R[-&[F03:)<PTCZD9+N#L+'./`62*&FE"]"#LM]0<U'\ +MNC&044':IZ+'8(HRGZ-US@C!4K&\P/*F9@R:M0F]1!CWW0D&RUO5]GBE*7V2 +MM>I&G*!"Z-?-*]RIT?+HU91QJBXB^3"<PJ49T*,??5+9>OI9W,&`OY)KG^TW +M?PJ<LH60>*[JSE,GC/BU0J/<C:L@B.[#_X!8;:^'07`!UG9_51N0OUG:H/D+ +MC`%A*I6,<\H+P`R`Z\1_1QPDS#Y:<2#D@OXWEEW>/Y?][T%"\"Z@5/C$KOK\ +M$-I4Y0)08B?WR4W0^"[Z?Q#3"M&%L)2V00X4%;4#E1&/.QB)T%"I:@W+,7/W +MQT>FUVCT"Y01ND%CC)T&LSLQ=@M#A(26EQ_>PO=HY,J_U*;&?D,5YC2V34O< +M!1Y2O^CV'ANX<?/G?JUG<DIH-P?,YXI3:SU1[&>DHFRM4+B.4;QXC`2^=1W] +M"3LUV_#)[29=I:=;^`6(GHG((6F]]Y#/V$=?L.^5_V8,419`W^N(G4M'S<OG +M"RL,@TE;:B=''K@:K.6<@6AM@T1N]_A#FV)QP+FUSKUTD?+,,W!?)AK'@&&K +M^//IN2_/(5#BPSN.&<IS76#,0$BBO[RON=Q8IG4RN<H[./L5O^Q\Q7JIJ12V +M["_/$_-CS!SGI&_%EF+6DVP;F@P/0!<Z8S;:GH/)(RT6Y>GED!0$E7;.2V5Q +MH)]Z!B?8YBV))IEEPIS],J4N@/$5>$`!2S5*GMK,\:EB/6%BRBY<.2`%3XKQ +MW(`41T*;K1L[^(3K6,Y0G"3?MI+P"/_V#;AXSN+:-7!X_:>53,/^GXVHK=Q? +MGK`%EAD0]WC?IR?MQ[P]$3I3PPIA5*?\A2(\>.M1*$3\_;;%A"8/$O+%(]D3 +MX%OW[)-B2&-!+G"\/TI^,]"&:C%N]P]<?@@O4$L!`C\#,P`!`&,`^*XC10`` +M``"'U```:SH6``@`+P`````````@@*2!`````$UA:V5F:6QE"@`@```````! +M`!@``.(/<+G'SP$1AE7G"I[<`8D\5N<*GMP!`9D'``(`044##`!02P$"/P,S +M``$`8P",L`Y%`````"XF``"M<@``!``O`````````""`I(&XU```3D574PH` +M(````````0`8```\7%,#N,\!B3Q6YPJ>W`$Z55;G"I[<`0&9!P`"`$%%`PP` +M4$L!`C\#,P`!`&,`C+`.10````"3"@``HAH```8`+P`````````@@*2!$_L` +M`%)%041-10H`(````````0`8```\7%,#N,\!.E56YPJ>W`%&:U;G"I[<`0&9 +M!P`"`$%%`PP`4$L!`C\#,P`!`&,`IXL.10````#<$P``FW\```@`+P`````` +M```@@*2!U04!`&-O;F9I9RYH"@`@```````!`!@``"FBXMRWSP%&:U;G"I[< +J`7)P5N<*GMP!`9D'``(`044##`!02P4&``````0`!`".`0``XAD!```` +` +end diff --git a/libarchive/test/test_read_format_zip_winzip_aes256_large_lzma.zip.uu b/libarchive/test/test_read_format_zip_winzip_aes256_large_lzma.zip.uu new file mode 100644 index 000000000000..5207777b79fb --- /dev/null +++ b/libarchive/test/test_read_format_zip_winzip_aes256_large_lzma.zip.uu @@ -0,0 +1,1893 @@ +begin 644 test_read_format_zip_winzip_aes256_large_lzma.zip +M4$L#!#\``P!C`/BN(T4`````HP(!`&LZ%@`(``L`36%K969I;&4!F0<``@!! +M10,.`,9.Q>#XH1P(BLI2=:?C";"7FN04SX[+N$IX\W]6[;L<;*^%U!JK91!L +MP-@Y]!03"S8@(.R**'Q^^OIEDHX7L8B9L<&+O3]J*%"5O9SALJ1V9U61AP`0 +M9^)V(3\P!:2!.<2-6FJ]#>,YO9>Q=I`"W+>.RO+Q"V$C[G8).<0:&<RF`3=\ +MA*/DL#2#.5_A^8-CMV8(*M!-^1DYSYB[(&@9B??^TL)*]]*!-%A"C_<7+9SP +M`10(7*LH4,.*)ZT`1C!D)?0YEI6LI*[GMJ@AL$;;L%S!5)!;CG!(ERR7ZS); +ML>[`MWG_)F%`'&B*K5K"_$1P1_<_N#(8BIF;,#)?/G5=)M<TPC9QRF,!*2L\ +M,Z6^85/,,Q!:>AKL#T383(D:0S<)\<'*EI?CW2@AL9E7121`;G=9(-,*!!I: +M[PAKD(_205%@)M7'BF@6K59>;.\<H$4<7<@\G')*6=Y\6X$338N!MUM]20M+ +M;-ZMOE/.H[?M<0-I*9.>)%A[M9RFJ(NMQP^X0W^C@NRTIWZ?R5^Y2QLT?![U +M^_D$EA7)+-#H/G:U2U`R2*L[#$N4"W(H_\'_HH/W:P+SGV%2`B"709\7\;D] +MU$/:OOQ]:[1<DI#-V7BB6%7;O$,45!:OVK/1#/YO7=5!23D?5*`AK/7=8RRR +MLAOUI<*/8PM@U7I#4'V(R0SC*=GF8(T>BR0P<H6"#1]PN"@,B(4<#)6_;:%C +M>\:L7"^&6_A8A-ZOUUVJAG+-`O44ZSP3/C^MTK"S1T56+6\%TDJQ&5L7*NBO +MLW)(V2%MQEXIGOV\_(),Y&JZ:98$8&W;2A5BP>/Y4SW#HD37(5=E@.]O5G$` +M:%"%,/4BMLMOUH,@(%9-LVQ$BRI*`HL=LS1B.`^'`C`1/SHVBJ^#G8M7P'AS +MJ%=0;,#6\U"3_@63PTTW=>-'FS)7``XL;P8B8&UH:YR.J:%G!_%H*LZJWC"F +M7$$M.(GX?0J`1A9Z+')['>]J+7=L*3@HWD^5]]?U?B3S`/2J4'N\=^TUSML: +M3HXM"7-I-6;WOAE[M@#`N=E6Q++X[KI8>M,1,RR^=H;?$(,MNLEIS"XN/F9I +M/JMQYP[4^`]KO6"/B?EQR3RPJ5B)NC[=/,J;Q4OI-%N"'N>27>'&:=:/D',` +M2V)-A1Z*Y0'PV;G.MH47FWHWI@*ZFS:K.=0N>5Y`->8^\\>7H/20>C96+61A +M&06II&X?X7V+.C[T&5S>HB*7'XP4/+%QAU$+4!AL59I%\`5YP\=NNK((H9W! +M%K-QM`0L+U.;]90+Z30[JL(J!EO%_J#Q8C4'C,(_\@6]/PR2;FQ/`HS%Q1IQ +M'[F&8%&=DWGQ!G][6UO84;61T&S5OR+C(277R:R.V"H63&XWU'LYJ)[E;DEH +MMLK[32A9M7-Y?3`.'VW=;#)B?PS:]'D4K$$@MCVE_TM:,-6VM0%V(#80O)[9 +M8"S-JI=9&08,;NJ.1]W.-RNJ^Z9TV[YVP-0%,\E.06W,4@#5*&E-&-@')R@& +MSIY=/+C&E-]#2='E?B!`+0J>0K1[]<_)A_J]T")\2)!OA7<TG-&9'OAM<.5S +M>IEY2$IY7**<(5`AI(00'$P<UJ/FX\_]@@0G'_8X`B*D$"M/TP/$.PV'"F=& +M(5A@!X_N+H2A*3+V\S"#=M0D]%)&C*`K/^EQ:;:(X0E(&$-H#DO^L12D?Q-1 +M)GO3<Q%+?]W9:-]*0M_TG:\2/.+`:M$\]M+9I``WBM/#,FI"2(7WBD&MGG!K +M&4!AF+K_TXW`?AY1'_]2%TV3ME9I#78D/9[?ZOYE"PW]P\45A&+%,<$R4(Q* +M?P&:@J6C@7$5+PAU,)25VFN)G#/>70`'*=J"+A<2^>I7J@SECXB1V(]W,3A) +M5"X'!@/\A%B:%L\$C'AA/_T3EWP64,H"2Z/<I*_)Q-E-=;FP0(O<I$3Q#,VH +M.KV'E%_*4,;>!%$R)V"HJC1RMG`(@T/LSQT80S6LEJ4,:`"?^D9C$E/(&X1> +MUY\6<+B4UZ5&9P.AM""YH:X&G[$!''J_G>^,M00GL3HX?7SS%K")Y9.56K7? +MW;+D3]'7:Z$V2BP&]G<IEHG#;&N["FD64BTUNIG(6VWB![*B_=@261$/8'/0 +M9[MM:*V8X[/\E)UQV=:P9DX,^JK.KX-AT2Z#6S+?`$FQ>3,V-O1R5@_M(<I$ +MG_&34I?9X`2'CA)@23E#HA!)%8-R8D_C.%:UA/]Q\=F&U-JJO2I%,&R\V8\- +M?FH7:Y?DE>Y4##FC\OPHT:Y]+RC\B6H_F^:G+J_Y0N%.Q;AMY`]08<:!QH=Y +M1JDDBQ52P8>&@56>LT-_3*\5YB(C$9/)U_AREZ,80_U#]!:">S?OW$+X9C#I +MPAE[/(7[F:TA,S:PS2[LEWL*6NG?35J@GDT,,77OWH+E`?>Q5+K)02^452PA +M@QI?LFDO`)V.4\20F:[T=:/KEG\863>$,7Z4FNHCXS4<K3=:T[G<!`\H[N<% +M%4ARC59ET8/KNO$?G>7&S-\23:B%NGP.-:_D_=<1Z[SB0HW@TD+,IY@6AKBH +MT-0G^667Z8SZXU'"I1XR3'YMFQW2]M).>US'?:=N8(F-MJ3\QPMPJX/1/L1Y +M29:F5KTS8,BRA56B,QI+?5OYVEOP'LYB$PYQ?=G,Q8X?\:II-GH#_ED9%6OL +M*EW,Y<X0JRB!_%WLT<UC3&R+(:^(<QJ:2PE]0#!3[I]MV=RG^PZ97M;!'O:5 +MQ=C'$`$-I$5</P$!C7+ARF.8I#*#!&%3;F*$/$>?7IG_ZEJM6%.9G%UZM@\. +M['8VL=+ZKBP*T#PUV8O@S=7OV&J@R1XDK:/?61<3S-R`TD/UEG<J;I=MN-@# +MX![U-3X<=GZG7Z.@H:9J0+E4J$'RP]XX!!5?FU'$_4PT3S%4;F'K%B6^%BOI +MDDL!D(%_TQ'O6`L[NYH7CADZ\Q]4`),SV&R[NRE>WD36LQ6W?<,G8%3BBV3P +M9-98M\;T^0C?I,OL-4#X7.N_FQQL_+!I?&51R(AH;:,?GM(1W>S:;Q*@[1)Y +M8CR[J@H(5<`%B".D>_I9Y&5^AB`_4>RJGS)$*/WS)]H<>IZ3-1<>B11QM_2) +M&<>V.YLVHYRMO4^E^%X=CL(!8D\7C:OAU\4-QI(O](G=^//F"O\F+IW'6FU! +M(FO=S@CV.&M.$WTN6S&)AZ[1:Q]/QB),\3]=F\2AX][9>YL"C2AO"L4&68'6 +MN`5&71-0,HM!>(UUW-6@QKHWV!5(FW],OR-6*L"4%K3F^E2[+7/'E0TZQ@G8 +MO&0%L4*$$[)M>_DH%TVD(P8!*),=%P2E/_K6BE%WV0_$3*%_@@=;NWSI:(\[ +M&5B/&1J.`/8+V_BG4$[:@]W"_2,N//[BK;+\IU$0QO%PD'[&_NZ-&1H7]N-I +MY_/`'S5_.%PHB$9I=+V++R!@@E:^OP*+M5_@I]N].@5G=9J8W7P!YGQ*/%[P +MWG7N;Y?(DXXM_+O="N?LLM_(V"Z9YK%X"H6MDP,KF(ISB4&W".H@JK6KITFT +M/8G08H&25Z7LC4@I:K;G0;7JFYML9,=&0CO_2Q(=P@Z@1T*HZ<A(PJ]4!-=_ +M_P."V"S4(D,>RPO?1[)-ODN9/KB("+0[?^9U*QW@]8A`C(U-6LL8_[8&><P` +M1)@D2?CQFS9;YD?E`5;9Y_>QJT]%U@7+:26_4*KI$,CPYDJDI,2:ZR2_SYG_ +MM;6[F'97D6%`<$-!OG(K_=\-:[4>L5?_@YPVV:[!<XA+Y2MF[K$CK&2,WK.[ +MN%ZI?!8HQ8H@'9C*WI)7(_:2=`&[>A:_10I3Q26>R(7RD2\ZAD?/:UBOLF=; +MO>7I2FP"'J>Y128JGC]`3M"(I+K(%64+.`*!!SC#PQ=./H<J@VE15^I8`'PB +MJV%\G2L[SJ?R/9\\E,)^W4F5NJ*A^6Y7;ASLAX<Z??N!_LR)<X&+5?^U'Z%% +M'H8MGA0\S2GS"4_+<=OUD[5P=)>#$N78(CSX:&)L>?D\&--0V.-9-2*4*E%! +M>G9O/`C(C`0%X4+U,_Z=\K9=T^%=9:SPU2WH?=E,2WJAWPAVI@YGB3Z979`; +MO2*#RZ"[D'-+N!#1R23ING@;#6W6/V2YZ"PRO$(\+HW;2NJ82:QMJQ-GSQ7H +M[])NG62L@I,%?9G$84(IGJG!H8384`E=\3NPJ.I4^[0&L)NP>%0@4K,HP8Y. +MS&?L7D-E_IF@M^75QQ:%B#.++*?0F#(15AM'H43\AZ5-8/72,+95W>LK/'@, +M[_V]F:;C>TQ,J*R@6.EA]NM_.I2U]HU`>4];CDH,*24UD+N]5,*H;/($Q*/W +M/^F/X+,NH.0C`'Z6FFH>`OG1C7/0!B"Q!8S=;]*O=#\"F'SM\H2$\WW$R6;( +M6QSNMV7;7[RUC!3;%_[B,<A.U$.DT\%B3U<:[$BDK.,VO08?XEO'Z3C':J=I +M>8B+Y@!.H3W)GN0R[DU*R,3<`?'^.BKY*#(CZ5$C?R#<$V$,C<K$#>^;Z5?B +MSC9E8U5OEGQ$TK;&9NL5D,[>]:H4U,]:M>S.*IT=P"X>Z+FKI'&!9E>ZO7-) +M77_O\%41L'T1[C6;EE3CT2VMDF(2[FO8EF/=GT4_;3=4J%LF?>9L'DSNJP'@ +M/$N*$Y"WG4/:'H7Q)X(;^D!WO@1UR8!&1IF0UJ-0:?K5OW68.'J`D"#D6#L< +M9D$C6(Y.9;7RA;=1ESYAN:9(^%]EK"A%--4#>8;K-YPGH(GF,ZLI$X[IYXA% +MR;],3I"&<!,$1P)BQPE/YB"U%S10UK&("?QP["N=TER-:98!9HBTC6/K7173 +MD"&I9%<HY<+!@V,W%B;\^C7ZB_!*_YL,N,!&-_H%<=)[I?<$A1;%(37YN=P= +M\[O[/$GH17US=ZRS3PH/!%9'81+1L6V9X:I"_SFG\H^.(4=,NCZH=(-1`Z'> +M6._A=;4.\.Y9A!E[5RUB$,V9*IZV4%`_@^>#E:CZ>S0'*4-782'-`HC@S[<3 +MI5FF-%:+<#/SZF#'LMJI;"RN5,IV?=>F$$J3<J5?=^N%^.T5__#TI+1'-X[# +MC%%3?*<5&XHY7K_)7=V(TE<?,*DDW-0GZZ#ADP["]\\TO*M0A,5WV1&OOW38 +M;\8Q$%[4_9[KAE=5^I&C]&@;;$M8!:H<`H;[=CZ9TU6W"4>.](SPB[WH[(?/ +MN[=KS-]&OYCZR;%')D)-0T9RJ3U]8CRBHN1*:W\A[X\-FA5M,1_?E8SB`Q54 +M;@\&ITW<^\?45!-TK%;5K3)/%F]?.P'`P[LLJ,;K@EKS<<Q;>P(7\!,7_4'3 +M[M$Y7!]6'-2=(9)2?D@OG1Z2/YY?-1/>!!^R6#J==98?Z&!GW]Z$AY7\V:Z" +M$;Y,+Z7OP%W\M]J!Z]=#0N&&_PMO,,A!N8J_19KTU.W,]]X!U.#1P^K"/W>? +MGAQ\H#6CD''0V?"(4:0(\^7];-U&=]%>0@S[0=Z:JN3V5?L3'AU(=B1.P5VE +M6<?TY[$4@97^<\M"<3%_NIH<UNT648LBW,;`CW8I0A:F59@@K@R`6U'$[4EU +MCH:ABK1%DOT&@'>\F77J%3`+N#!ADZ484#G\S+X6_BS@TC(K?5+?)$#-\_!^ +MMX8UP3HI)XO!!!BS6YH#HH(HE40!TDJ64/0Q'-"(.[V4%M`$>7^XF9)K:QYJ +MUU]_(1<B)Y[WB\&*70-?7.K>JO:D$=7Q!**@[Z4$P>7^D-QK@?+03CA86A>. +M&.8I".%C)_#%SXZEKYIR.(M`"9!>6@&O[D?6ONYN)IH(6W#69Z2%^>_]'A!? +MG)QP6H^Y;Q-X9T'N$=#Q]>0L>C=2TT/ZK";P,24O2]T++.NJ/!HZ+\>NP']A +M7VM(@&^F_YBJC90SA>G+0VU@]\9XH)_OC-.*[T9&MUD1TBE*G(J4"L@R4R1? +M(7ZIW$L6Y3_Q_'L&<)"Y.G8]FUB"7S6PPZG!?-9>E`)CPG$/6XKWG#KS2">( +MOI^8AZ]/[;O-"O2KP-&FBCV0-A63HLES.5W#".EB'@/U:6O"Z`7&HTI9/!>3 +M*$SQ,OV_\<:]WTHL;]<3>FF=GN3]+K;PSYA:"J8-J+T5(>]8<[DL:SP+'Q<G +MT(6<MY`E,;]"IL.)<4_,WL:ZN$J?C:;V6H50VY6I4_EEFE/XXA_/)$(TR^+8 +MZG]:-#)\R:SF?^71G#7$4N-X3&Z!FP_WT33%6/X28U0Q(?54_N2Q>1["M,!# +M,1$80-_W%JQ.VOBU<'86MA>V/2;:`&-*7;36J:<UJ_?3-L#G=/HTZV0M1=*> +MKZ[9RT]Q3.UWHLKB;AGDOMHYAEZT>W,9K?EJ@8L)]SN%)VVWS_GF1A/VGDPV +M$XU*H74\CP<V`^V+0Q%,:H%1\$E5YRQC3%Q/93BHR;LZ!RPRX6/)PHCF\W[# +M3OV4_*])/9H/!=\WJ``_IYQC)0+(V_S4"U9VH0I\-*PV3>->;NU_DABM8^#] +M?<&H#['Y(DB%09-@>0^42YO&"'A<AYPBWO3O;G2`PH9BN]&2\D%T/]J:#516 +M,U=MN.8KFJ>D3/]P5%*Q\\+T>D1KO*;E,K>4Q>9\\N4\^U?XV1S*<H<0!#ZT +M86TJZM75"KXD,WI2TD"AWKK#/WN5_?DQ4;8TPH67VZ6.J2<A6YEW)7Q(J"H? +MGCJZ=A0J\B`>`H=.5Q?L,\$9_<@D9._]@ABB9Z5)25OX%&.W7#$<2^>)382M +M&JTR$)K%KK82B3^PN\>T@^7([>\$ZQ`FZAB:F=^9H;,4KHU'2N:DJ`([YSHB +M'9&SN.))<)2]H[[#YZJEM]%UN.P$)M*GXZNM'&5YOVP<X^)&>07TWEGE'>\S +M<%974G^JQB25?U?I03`%;CH@+J'<^!=`O96R.UKOIXU^.`\-E?HE>RSCNVB" +M>#!LG_%RYNIKNT`YQI-4!MCL-71>#^1D,\E0SX$F<7F+6O\_@5&5Y"MN,;*F +MR,N1R%CTQ]C:^9XS9#-!>IVZX3A*PM6D5.4Y$/4I<9>[_0J[@*EJ!.[HWX%S +M^#V*\V;HCZ87PX\\9Y2?@HG#H'B`P<30&,E$&,[IO+$KQ1/OQW'M;:&)A[(_ +MG5?!M>"&S_+9,<>_`E_<`4J<4?Y>D;Q_$%#!R"6`,;]S@3"FQHC9.C1?!PU. +MYMQ%ZX7HGV)J?&BW[C+S_[G07R'QH9IL$S?`-8K-Y66/+5]O(FKQ1!J7*>IQ +MM+_$:>;+\^B]#&<-OPV9:;DWTOCK_G\G5A)_)"C\9L)G[YMP.`""(>P^#C<E +MENY(7Y=DB%U[IU8T>5EX>[&?8+CITS\K.K$[15&_I(DLTS:]<5+,5P3\BJX` +M*8A-5))K_S?_QL,-1L.#$>MP2TA=L\05X0I]J!PTTG,-E1BZ2FSJDWPN*57Z +MVI<$O7V4G77"U(-B*02O_BN*S([(G)X:8CP:TI5Q@C*/+KE`+;6=6,L;?:-N +M5+FC]+D;LV9RWV=(-4M"HWE3YJ2O39K]P;9'"8QRG+K5.7-OM%BT"0$,'Z>W +MZ0A"YPX5D/1TDF5<&*EFE0,7S_>0\..'V0EEW&E;Q\GD"K08U#;HMRH)&VF3 +M:\O9IQ!@M=D947V,7SQ%2'VQ/=L<J6[F#TN&'U8H]R?ER^WY^,$84`AB:3G3 +M?"!AO&%,+ITV;^(:V"C]<MDC2,<@.G1Q#Q3H+2<+D5;15G)@[UO%-%NXC;KG +MN`,A)RS3!6Z7(]^ZLX?$D0([(*>T%RV>P8YR0.VO5,T2@FRF&^Y#L,1N1E]/ +MACGXB?"+:XG%-QQ84!&R?<"F\\;),]('!]ZN[LS!O'C6I9$?OT]YAVKL@N3I +M=$B"E+@<VB->^RU.3*CZ#D414SAPF7V3&V4:9T.L/3=K7R`4!C](D+<;VF#$ +M%RO2J3"(P`=T[N5@I)?W/&:V56W,P.)RUUGNQ5\DM#SA=D@U8+8(PH%;"Y+A +M0+\WI%QE)TR$9]Z0K0M7*U(`Q&9>(E#F14`/275O)I?.'^%O"]BE3S&O_FO) +M0VK*)7L'PYKXSL+<+ECV>`2;HC-!5FP&P*=+JY*!-`3:"`I,7)E[7M)0/LF8 +M;\5JQ_H'BN\]DFF++S.W#&=%(`,LOKHR!>7FO(-/+(7RDF$,9CG:K-^GL&55 +MDM39PCQWI?WJD<UXM(B)R!O4I!1-/8FSAS"IFH^5KCVWR8^-L8]&?)Q9B&KY +MA(8J,^LDCN50$RRUU9NJ#%@Y,Y'OA%Z_.G>Z$4MJ!HD1.JRVW^]982J,"2ZV +M&_*MF/@ZP'NW@2E)DD%$5EEJIL=%V^PN]`>XXFBG_1ASBT!Z2Y801%Y)&W4C +M(F>E7<K1ML;2M-_U55>OE+:)+<E*MC+]?3:=O+9;&?9]H)3Y-KD!/BRX:7;R +MAMG218&XOB+%`S*_!Y'39/J[U^+^INSC$LB[$H,9-<U3KY.T4RI$>=BPXI\- +MCI&#`EASAP<2W44!D5^5;]?Q+$6VE2&<VRI8WTDH7@=@Z`4^7"^`DR>6H2#S +M*2P4D!J<#2[.47$(_OLEM1QM1D.9G?U[>4P_/-2;'HUX:>N9685%8IV:]`P( +MJR^4?!6YYM*FTZ&?4H46K*F'.Y]84O3E!"O</N4MVP7Q;,=Z:TT,;<&@T2+G +MUE/L0FU9U5E4WC.TNOF'!Y!!FMW9*6UD]<YWX@XHJQ_=`M5/Y;&/Z?4`,*N_ +MI-AU+[GU\(@KYT:0D5=K8_GG(,@8R)_[]O@C=D"A$#P6?A/&OU.;#?=UV;;D +MN:_S#]'4SRG'CS2')!Q1WN7AM9%W2&&];_/>6Y[K+V^0*VE#T-!:(&,M0>W' +M6Y%^FVQ`D46$@JGO5;P7$_)UH0TZ'E@B\K*B+_PCGD2E?#EI8L7LB'OC3'2? +M,#NAUL)XB;I07_:%V`?*TM$:V\H;;=:7I"T1UQ"[XUTS(OH;E^Z--3.A14AJ +MGG0[>^A^1RYD+,P1*FRE\F%%UVWU+!6_PS21<D7\-5WK,ZY1):4V9\_ENZ<O +MU5.>6C+X>%0"Y/,IE^:^;<`A^D4E>,*7%3K1+0\&'@GBV?Q4T*4"V2N,%7.3 +MD#O]E<W02S^&2.DBDF'H'"+T>)KQ=F_/(R*7\?4N/3PJ2):+KR.0$ND9KH]# +MWK4/U%*J]\]%$P3DB6_=C62G".O=0,;*SET#CZ&"4<3Y)AMPEX^ZDL*S:^8[ +M8]`XZ?IES?BM6A>QKYH;%++[VY."`@>8:]GH1,N0`8?N@F$I"H^2=?O7WJ;_ +M@;$>^JDAOV[-Z+3`L>B4:T@U0YT^X9F/7IY#M<]WI?,$KG`C1),I9\YR>]41 +M.():?KR3AM#:`,C995H]E46H:7D_`17"S3%B+Z!V."FYT2(/;)VB5I\:FR-' +MZI:A`E+]-"8]MCU<+Y5H9BX!Z/$O7X2W2/5!:,_J.$9^QR7O9""C0AA(5.=% +MS<%VS!XI0KU8M62AY,MG3:@1"ZFE`#?Z8SGDFS)N8)H7-)46:)4.Z.WXOX5L +M;DN:-T[@C*^NGTJYG=6"^-3'$@XD"&N.FP;5]2ZE^0J:&W)OK%1$D5,67A-? +M%+6;F3L3<FDBC;[5G<7==AD07:BCE&BB(("$-<X$7\#&@ZEZ][/Q@?:JJ4@5 +MX;3O]X-PS$P)KVIGG=>.$Q/\A!TQRYL<1`/PX'+$92MGV[M%E5=W688$[P1_ +M!_K%D)N:(BQL#U:M>+0H+GA$)9T:26RZT]?1AE2(^]$F(5:Q.4><YXHDTTU/ +M.,D-E1D%W%X0;Z]QRAPI:0"8YLH&K!3\HUAZPW?F:+*U84;6L\ISZ8=7S.:O +ME,*:QX:*7+%00:888H\R?7(7PV%]85Z18BM:\>Y1MW,@AM04J`90]3D<;VJH +M`VZW)H&*52[#T0ATU$'2%4W;A?S_@11"?)'.?J0E!VSE^VE6@58WY!+H(?., +MXQ!$)EM="`'5N%^1=N+(2*LDHC77/BR)>A4Q0<L"D9]JB5Q.H&H^"<W,&N<K +MQ2%Z6GH$O6'XD59?<1>'A]P\G5&?\ZND\N+J<=E7Q=VI3$,X9-3)/B`QF5W& +M6N7ZMEX"W4QY^M%5"N82QP9N*BZ4VU9%5/9+=:!F4GSPB1=?92H%GMK*#%.& +MNX1!03R6=5#'"[%7I?6]DE@US$!;8JKX+[.@0'?*"BGWJABUOZHJ\&>U]6'T +M"Z](B/<%*Y"4Z_5N`06-@I/5F)VE%N.\=W\?M8ZI1"HA#"0^&V!L'$9V%3M: +M3/<>$_ZUH$AE,D3?KXS4)6P8,!,"1XPK<PXK\S/Q%K-)8*WEF$[T,1S-N_HC +M1/9GZ33DZH!,AAD5@0$*;(ZC6E)&U00IAQ^ZV.'C(-;EMM`X"[N/NO:R7M#+ +M=C.5';A+[K%O@_[Z@D>>Z[<'Q<W5M`E3OV8+']0"J9DOG76!8Z]G6^0C#?', +MH,TW\-Y5O/51?\FL;I"2RBG&3.CE$RK%;8E'0?5A^!H:%R$4`=0<..GK?;.) +M]B_,W_.1-V1-?`U*"._[#[GW,]"V`'N!?_'2<3<D#_MWCW`Z(@V#<K+A6L5] +M=O.@"OS#JZ$#6)\?BRLP@6`_1C2?="^7)QOB*G]Y_6\@AI>,O+6HB,N@=`,H +MIS-=PXK9NCW!Y^R_D<0>&'_#%.[^8K4HT#U?XQ[5-/.]\MF/O[V&!+$4N?GM +ML=2J,#05#F.,8,1WT%(5HL^:]@X$+]B+%<G=J((V#CV1U843620"#;CG)>GQ +MW=0VC6-%++[J[6FG_M:X/\!I=ZI&O9D2.KE2R8]0BG?:7N1O2.5:<;M0DD4C +M4A%T"?C*QEJ8NF6(AJPW"QQ')M2(#>>UE3Z;R[1K@*KJ^E.(\246SD\YW6:9 +M;/,HWF&B:_(0HHD80Q9C&2F_9W$22AK5!^<J]>HK(XCCQ"&2&'7&`?I_KRPC +M26A^RI))(:7SL.,PEN[^(CQ#R1IBV8)'(>>CZA14T+V5PA5MY:5-/`02'J]; +M>T"D4CR)H`/%8;UN,@25F;:+#;SV=LK8V.0Y^*SADQ5N`3IX?I"]8#%OR.[Y +M[T$EVMJTN[V#07WD"8)>HZ.X]4N/-GDC[#4GL7V09S*[G$>NOR/Y:4P>3N@\ +M]##JEZ'M1Q(^/]O9CGIZNAK&2:D$()>\S3GEBC=R][_`*`SWO8Z+CNJ%U![- +MJ9:_L_V(8M]]Z?'_\.H2ZY5%*T9_ZE)C*/!D_O!^`]>?EXE@OON$K<[64?%$ +M;<TEDHBD867?ZOL&0EC79>NYX&SZ]@;[/2Z`LZ;Z-J;6ST=&Q[F9Q&,\Z9BO +MQ<D;YR8K)C^K_$8Q?FIUBD_@9'H>:>K&^[N\-;G_/0@5K)4XZXV:"H*W-4V\ +MDJ+=@?BE1QK?@77[T0XRX23PS_>KDL'$@R+E(76@@._DW8%[P,)C[XJKUD!9 +MLSK49J=?/GUR,*$^T=EQJ"J/@317<\)\SH6-"58#!P;O4$Y9KWLQW4CTY0;4 +MH0^5\V(.!D.O1]LTH0:2$1V$^%A9+M^:/XO4^ULXHQ2)<N*"J#ENZNG+Y4\[ +M'UY+\T8,D#AU>3EQ)2#G5#=>X&S%X\OZ)9IK3/]\),)]FR"6%I6UO<BO,M7X +MSU<]N3@[VCL^'^7+X$0)NJ+(+\-/(:;7EKFC&SF2KEI"/BL/0=<<6?A/H4`7 +M80+.(:^IO8%Z&"N"X7F7$X)I7:EXNK68F;>Y7R0-M'0_A:EE$68;TL>%OE1D +M?RXD)/Q_]VBL-UC$O5]-'PDN=O4.5AKLT6*HY(CWKX@2>`?%D=Y[B4\O!W=[ +MM@#A="A3;?S\8:GZ-GSH\Q7N<=K6,&C,95F.F;;4.4XL-DS0_H-;LWU7BH&G +MMZXMO*0J,D'2(0=M$SJGR[#N\$RFS"-2ZV?F1=^1$+9^?P;1B_W0S.0Y&"^` +MP$7#(\ZU@?.4AS=(EP4`S5Z]6I*.<R^7$ACS'!0Z<T<?`BHN+5W0":(@PE2( +M4^FZDYR'E^GDIPN[6/V+2;9A--:UW)LAKLJY[(<6UY&&.<S(B:X@0YD+@+'& +M.)<+;Q-E$LD]-#]YX!*7+[)6:M1HVNJK\,!7&?85M=B`-4N5%5O86+DK%(JI +MM\1Q&E&&'3CKEHYJ;$70A!P<UZ=[=00ZACF<X&\`>\@;AQKABC.XEEHM;'9Y +M7=[^(\/OI6KMN:VEQ$38TQ]?^4:M.X1BE?ERGU%)Q[B4FD^Z3]0O_H?_H/IB +M+`<J1VW+93:XUQU'428?JU':IT<L^&N8>24.B'C$<%7V;BM\__0S#/TX4]&C +MH7@DO90:'N._\*_(K?_-=;C+3O4V<"76W..X2H5-G0?@:^+^7RP#-6IG45>N +MQC1(*;9L/`=G$B1??[#_&IR-.+AP(/+L2.5+40JK.._^V^,;"[2Y(/71#W:W +M.&B/_@$Q1PEE+*HN8ZN=<#H+SP<B$#NP8^PD[C:-EMAWX=^?5(RL)K$%G*U: +MN#MQ;12JT;[""0"4'L:+R9M:`#W\:<_.3BI]>TCE;[V-@J$MNT6=U0T0FP.M +M\W8NZY?,MIOQ.>K>+].SPN=M*%4P.CU`W5WM]V^AUB>J+'V.W?DJ90`T4P^I +M6(+2-:*49)N0N0[MGY[0EY'G(H$U2FVK#9V<(7^60CTRB52OCP-["SMUJX29 +MRIK2Y+`_,<L#K76XW0+O%ZF$<U\1"R+`H/O*.H6L3:JLW$6,E:9Z54$KI5MU +M)ZUQ=5%96]`N?L10=C3)]\M+&^5=/DLU&_4NM9!KHHY.'SJC6)+:K3[6'U;8 +M`S-#[9*!!8%+FGK##N?>VA/.Q$((CJ>T)&>DR]@C?+V8[78$-\R6&<OE&R&V +MD#<GMX0SF1?H@C+-:`[B$YHKY<(#:J2]A#Z:TA'(P:P*9=/WD`TPC4])26U' +MZ"Z!K]PQXJ"-65341`T'&I?OZR;D=]M(5:4_Q#BRU(%!QK9)!EI3J+KTB*RR +MT'FO_);T'0-)1K]28F,659B\H#-?'NKIZ%NRM.1_#90#9S7>:Y-W:;SLB;*0 +M1A/"?#)D^@+GMYC#O%D&.P5_]'IG^_502D=QXBY2I9>:X03)I)[D5V,XSPJP +M720<&.GU[D2LX=CW.FX.X]1@L@\]2MW9<-Q-:WCJB..;6\"@-MT3YW2-YNH\ +M[^7W:I_;1=][3=3K488:Y%26G/E*M&GC36*PI1[,8C3LHL4FO9!6>,/:_!9& +MN4^HP$\I>]3/_U1U:1&98!A>9[5<^],F>OF/H)N7@>?)IY@\9=A4X_&K+1P0 +M%84I:#^C'S&ZO5FM7:C-C0_;?FE-TFX#OVY$'?1'*67?)`J)EV&,ELCWT3O= +MC>>8+,Z;U@/>MZR)ZPQ.U3-$B<IE]@:G8K0.9`[N5=G_5Z`MQDR.CPY:DIY; +MM:FTG4+]\M3B&_0I&A'QR6D$IP:"F?;G:1XGK$`K#Q`.'Q"0#W:$E)_8TW+M +M`=YB3S.BGU]A);;QN(0`+0U-8'<UE*KI5IZ<'!B*CRMNEXP9*5LE%`/?MJJ7 +M$R;Z.6ZU[1\3,XNY0/<NNL-<)#K-+_P+]A-;3HW<3!E.'RA+U!2US]G&\"QE +M$_P[J5`D5OPG>EVB=2`=DQ0"-]G/WLS+SX**GVJ2=H)O;<(3:.Q=UZZ$+EL7 +M>MZ'UG'DK;OZGQ$QNA<+P-1;]A]V>VV5,5I67K(N,-TKT-,2/FI:`47_0([8 +MQ!$B-NH&:FZ?N6M'\%HG/'7.B_S,)&#Z!O)S4PPH[1`P19Q+&5S;)CKFI2RB +M=ZG2/.IAYF[4KG:*6H,J)3;5WX:"X?]CD6P-VI';D\DQFL!ZIB@UL!A=;P\$ +MF`7K5*F(&)ZF<6&U'V0H*D-6*DVFAQ'D.@.;C4VW@X.+0_F)NDLIF`)N.'2X +M&5B;*+$UH85DQ-5>Z$S5K].EQC<.U`()^S112O+,FF(U/F._W(=(@E@8*P@R +M+*,?IQ"@!SY+T)2N.FA"E!\4?>?&_0,M+Z_TQ!6,P5)">/KL^7!85\!,P0M( +MMQ+597<8X2AU8^%VN!>H(`J_V"X1EZCB(BV?L@33ERD'"AI]$I(%#>M2TA<< +M<Y,);JA+QK%5;`D7E+,%%FK+Z&SY_WPBITFW+2Z,GC/NC6<B2EAL/:=XG/!L +MZ@GI](^_8\@5H0ZCLXY[I.I-%S@R2S@C[\1=\MK%KTS@V]BB/(TD<K)7<<HM +M$#<]!D%!.P+Q0D#^VD/FXVIEU(3<)!QC9G:[T*\36@B\%A+<A;T3J6@X7#+[ +M&=@-8G-`;&/WKXM/2:?EG+T\F3>IG">*\,LOQMF;GS,<KO%7#(4OBXB44EJ3 +MP^8%+"%7Z-A?+P"F'K6)1JQ_3[4RS'G6)9=?)V!*W<2HKBLX?K3'/6L-QNNX +M^)F=Q:87>#'0Y+LE/T]<>7JR3J>GOD)&"0T!Y%H_>D`E>A*[*'E#-**ZH50> +MFJ1<IP5&W?@?\Z(WSAW^T#]+^6^9XZS1W`M70%FOW*``DS?#3E2VB9N0\[T) +MMSQ4)$,IN;9/DOM-D++UB6E6$G!'>\.085#=JH-;%)?:I8$]%?!Z*6D#"^9V +M]F\Y0N;V'!4FGYG$7#6M\C_VDRPA*RKT5(BKBE`::\X22JU`0)(=O(U/9F5E +M5=06[67V\MB-KEM/)*^>1Z_1=0IB?>6F,M+MKZ:3\<F3P7'"8*]5/]__DJ;# +MD:(I48A`G-J[<53#,M<4];?>N?%6?F`I&EN<FKKW8_<,/D<]9QJSO?Z)"J*U +M^_!>XA3Q<_@>>(KUIH6:BSFR50+FKX7ZG'*:2L(XZO7[TML$BBMO`V]0,/QA +MQV+F^A\0]"SZ[?)VA+UP>'R91!,R+O[!@W(?O&7:WO=;?P`QIGH$4:2'V-?G +MNN_LZX&A'6'H35OA9I!28M17?8@UWB3]<*7$5[WNLR6910@I9]X58-0]"S`M +MRW9;WU`S%');[H!2J6D1;+I5M#AX-Q<V*_!6)303:7)_0%@4\"0[1I'E]7]B +MPQ%=J[I5S/'G0<DW]5P"V#`'>];H($E7TYI")$W\E"L'+^5TQ^`?$G"])[D" +M.TA:#FU*H:-;3RBR$'Z&M2RC?"B]9!$E.2=`-X=9=;0(.I%</U'WPI8I]MG6 +MF&LQ0$(JZ\0G,#N1NW)T\`!X/I`7Q(H*:T]Y<6`/[5FX4NU."O-$--18,X=; +MYJ^63Y+^R1=*VE[D0ZFKMU]Z;RD5)G9WV'J>5W;NG7"2?R<IDF0X+&1%GILR +M17*;2I,8M]1H/*24!XI13,U0Z4ML;EUL4[A=C/J=B*$4YDQJ]UA=3I7(>%)& +MI8THO_W7U(-Y;X9A>,*C+8HB9"EI$16ZVLBKP9^)J]&>#OEC)<Z3$K6GU8/F +M7Z5&$38+#OY8J_I82GGCU=[)#BJ5*=NCL3;5O':TOLSG_)>B#2F2W/-3HA_F +MY%P?A7$6^&U1V\`437I]]:W$!7.Q:_^6H"XY&7GX?HQ8/7Y@5`VZSAM6P^,M +M1]&4/OJ"E<,_B-![49U]WS#DVMSM.8<TN4)5E49*JW$!*2\3-2)["1/[N>>D +M9#(BF[UY.B.`G8!-[M^%\=2?P&6X&"#QK/&[+."[0,$6]69T,`11"3K^GIN$ +MK=N)=JRFRLF'<Y[LT,_X0T85Q66:CA0$<?"P@B71>\S:AH5%/M4]J!A>`1>C +M_GB154=9[=)Y@/O@')FQDM`=_<9=^#0.P%S49'#KEXA_@NU$GJ):!N%I@5)\ +ML.(UG/CPSPL`_+,B*<)CO/3'-HE8$48D!C])P96==8NDT;WR!UJ532@*(SJQ +MJ]'^M.D,;]BQ@D4"87+=?;R$F^$@@<:@OX>11-_*40PG:=B$BCM.FGVQ3[AL +MSBHMWLO7S(C;@F(<2]Q%G#55'FC^U4LQ8WP0T)S_<-K;:T1JE+NY-"VZ'*3Z +MV'G+MW<[L-+TFTFQ%G]G)R2WUAG?4?DF%,MLE<XHEJYWDTH0BEYPC.(P+('+ +M>9W8@P"?NW"L`IC#>+,;'PB;YL=Z\YVJX42\GWV71>K33!U3>1=J&L`OXC/\ +M@X>MVIP\!'2VU$[5]5]JV4,3%S</%C''/D>]GC2?GFZ9.J':]A6R"HP'!=P" +MBKW6A+Z(\`95+24"-VS!0NZ*TWE,`_`R[#ES!V/->T<*[SUGA[S@#33(7T(@ +MC'=/[KI[QO^E9,K&WD[H*`T[3-46GW_@Y'ME?FR$/4=U&-8ORF=Y:O@I2;,@ +M[92`-'^<LPH7E?(3_]LE3Y2:0^%B_[W;(@KA]!T`%,7TJ_;66\J5[RQB<N>= +MQ6,V7QS\J$"4>=];\)1`3B9B/F@FBVMILFH-,2H6/B4+<*RNDAD0'P<4"``3 +M!F#Z-F`I-+7!UYV,:F#I_"3*"`SHEZ#K,#4!\(GJZ)KVPBF'!O/!70.)\=-- +MIZR`Q9)5$/0O)#O-\DN/X")/36(5,K-CZAO+6(P;ND,..#S44;R,TA9_@V57 +M0LQ$F4`O.:90J4VAW15K@'++_K7\/1RCQH#DTA1&K_^"3IPQ"NF!=#:6UNRY +M/9OE>+*C)J`_7/6K\]V"'B?/^#7,X/)Z2V+]6._LE-H"#UA9Y$*RBT&@/1>U +M)8<PW8#$9:S<D:NM5X2!B>]S,+[.&X9GS]-B/S+OX*<5_<1Q*L*?1NDGNCMD +M(+Y>;MF31F%3NN*PR3CO4+^:\%!;_<T1C[Z%=4)K]D-!#6_^*&4`%D:LMNF6 +MKS(K['_V8IBJ5.5'#[,NEX`B7X1YM9B<47,L7YSNYXCJW_"+?'HU`>/CT$_C +MR*,^HX+M#MA@8#*NU]\:3:&5SNNO,7Z-1*B[;>>PF_T19WU6%M?L]@,#J4<0 +MT>B;OZRFN)-O!:W`U@5.3?77PY>B<I'\Y1;9,#30B#"@-((KKEPH0WI8N$TR +MN">"##.PRQ*]1HR*$1V+\8)698B6MT*"+&_LV=#[+B:.UZS'NZ1!=*E>2F%O +MK-$P(28]#GC+1PGSJ&L>=*SBZVOMAZFV2S<LI&*ZUA$#>NOS:X9.0/(M5G=W +MUB3JT\!,%2KE3&SW%J#A6$VF"VR";NIWGS_GR^!\LF'=31NLXD5+G$$1O(W^ +M+?U>:PZR!BEE+5'/.MNOX&NAZ:FI[D4J[,1VL[C>\JQL"B6P@_0,!^2KA<'U +M\3<@8?&_=VSY]B1Q8!K0=<-3!MW]SVX>-P-[@SO[RA%-GI,?/1*O[$&!:3Y@ +M:1G3C5R1C.5V<X]#[*,CNX/#?/H<XT$FL/J_M650['-VA2AT?:[EW4KK1H3< +M`3NYGX-`+"U3]AWC!'D#<KX=RA4+1T4'F82EBH206=ZG_!=IJ.4F5#M01'J' +M@4[\8TFD^D-<W)J*C6CWGG"-^Y$Q+]%/$8BM+8?>C7=;5<X/V>.5:ZT.([!8 +MQOP<-!P)!$=UY;'E9L=V-2^[FRE@X\GD/T6\+DTX/E@??D4TO6^Z[_;\'WYO +ME%JS2A]CX#1;B+M,RPDE1B4Q0/$H%WR#D?W#C2@=^(T:L47K#W#[\YTH<Z#% +MNA)P[<D]='07\<^H;3MQ#3-^<,O4>T5JDHK5G^:9KQ`,/'HQ,S5W,-3HE/4P +MIDZK..EK,MUKCY:JVMN&O;@U\\D46B8\$B765!C%5NMF+!77&2%6!O=I!?P$ +M52(0IG6@6%G3[&<7073,7H&<AV&\F'*\#\8D@\#%;-PL(YUL9)U!Y6XS?=I' +M-E4$<04*IG,!?FB7JKMG!%W35.;AS+9<N5E(=AGGJF9;F=*N,2V29D5S"S?D +M(S._"6FX:DR;VJP]V^/%)X&]HLJ2E='):_4.#QYD(+=!NMY/>=`R(:VW1V)L +M[[+A.I\+WBU)@[H`.Z"O4>/BC;3[:JD!(RBZEL@2]VDH!_.I_,]T/%#@E=PT +MHQOT:R,.-'/[\B2^&>JH7TZ/0C_&S-<G8Q-V?8/*GFYZ"T]5@M^=-SQ)H&7> +M=.,-R&,-5'K):-S$A4AN=1CJY/#*,V?EL?S)_M_?8_Y@2U#0]:%H"5CFV8W, +M5EQO&VIFWZP;V`S4["3/",E;EC<'2N+6VZD;][DT49RP'GG[7G60R45YE)BR +M9WI`*X,N/;SM]"&WN+>6X$DP9G_;X&Q4_A5]Y7])D6DWN0B5[<5S,TZ$^1FK +M2FWE1L^7@+X$U%_"T0'`L81YX^,33YM,KJ&W24G)/OD;?[D4^3#\X%-WA]0N +MKQ\JYGT^5'["E*TV*)(7/A(F945NT?W\B9C:1[[E\2/FN25_U/=`?Q:!7-^W +MV[P59M._\9F>OD+9Q?GJ-8&?9!I[[3%GJ-^F2^?(C*5^88A27NVU[0]1FK/[ +M5+&7L5+GX$E`$OSZ1RTI8LQXTJ=T$?_VU>1PJ!AN"B-#VKQPWI)(8Q-D-G4E +MJ(>KL>G]8LP)\Q-K-%TE%_G;<QJQLA&7Z@3H4$ROZ3=.XI6?.)5.=;B(@&BW +M+XT+VH*^*)RD<?BSI]!1;Q0I&%L824#2]E[J;*Q'+08?XDT`SSYE5_'<5[X' +MPQ;^LS$`S^R:=[IB'A-=E"U>?LLNW<Y\;56;ENHZG&V<0LX:5OU%FB8&MO"= +MKT-5NO[;*QU(Z)6D!$4M+RL\1V*?1^.G7<340JW.:"\,G7^;^,RG,9'A]?B2 +M&+D<%Y,\V-2ZKQRHTS%\H!BR!6(1US5P6\RK5<6?/\L%"UJ8G-WD)>P&9<3] +M$W2F:-C18<M2R,D)Q'J-Q1-KO$O4K$GV8F^9@!GX#.@0M;-5EBB-\/@:[W$* +MN2)WSF(^\-_!R8Q2C%.2/6SII):IN2JU&E5^GIVR23?8@:7Y`H%R@VQ@Y1L6 +M\XW&5R+IN'=*;;!DPQD`4^*!-H#AWILR,2-S2"9X?,/?--??,S=)G@4Q/'IZ +M]%P:G5G4]""$=\`0.\P_;Z>MIG2!'S!TW>TO8!\7\Q`&_VY;BC="WN<WRLVC +M@J%%I<AQJSBO]3HM4?,#:+$P4"$9Z]=#/-8&=OU\6Y74)C5EQT5>1/M3(/#% +M=XI)ZJHR]47.J7')\L=J[ZP\BGY2`<W)L216-R*W>D#PDM?ZFQ"'L"T%A&)[ +M7=,CXP[H4;YW=2-FMGT&7:BPN6V#5P]C?-`?3_??_7.:+'SDLG:!4?`8Z\DR +MK>9:$B>`$^+M$U>BX_9=,2)T"<P(\9VE%Q[,9X6E436P@R5%7M(AR@Y`LS%7 +M+1S1Q6Y`T6)C&N3ZM`*5B>88!^I;M265")+[OXCD.FJ.*8TB@BV,W@S1JO?L +MP+70\H_YD7OA5,=KP)>$P:^GL@GHK%#^[)/R%*)`D^/)`3/HA#[M>L;6%U&Q +M:Q'Z'ZX$O[C5(CS,S0N8&40KGW0).:OY<F=Z.,=/3EX9+/F@&OKQ9MX<HE*T +M`RL*)C:O4M:H`TH<7M#/*HS/9$U]>N/-`TKNS>2"FWF76JV(XUKJAIB9"8.> +MF!I-%NDJ8=I_YNN['F8^*-68)]H\^";W46Q]$POV;?5/E4':Z='-^N2C%K!S +M?8YS-PAU-J[1S^7%_O1B+"2H>[3;/WP)5;SU$R/9K?!JY!(<A[-ODD]XI/C' +MQ("M63VRR7S2XNU.I?1Y^1%N*.@-[HF#84&]VQ4*8]L*'1TSE8J7K%>=V,1E +MBBC7[4?W!!EH\YW`)1CSWWHU];0B.0*5KNL?=_AJH>7E_U<V3)N+^2B/`?*R +M&EKU_O#'![BZ.3:IL90`6[?)5BS1$LNMTE3\DO4V4.6R2\!&-=:R"MAJ7=;: +M4M%Q7KA:F"^<]G%A+I;37RT7=:=-?;OJ"3]@1A+(=FKB%U;BYENW/>!\Y\_[ +MU*%:*@U=99;YJUEX24(+$>#>JG)3U#N9!J3%7UH;:J#>'YIL5`%V](_`A54# +M=7B_!#+5`N'H#\N081GM`_)&R\Z*A(,-66=3WJE0YL)8+FM0ZV^31@BX1?/2 +M4/^'^MY`4R5$0R"&2"I&)VQ+,9EC1K95;!M%)="/P>O#8$CAG_(4NPX(7K1? +MU%2P&UO]]:D7T1(:5]6LH(KC%?`$;5)=(;:J^'<D(DPCJA,D7V@'G_0^`\1" +ME(EQ-\%ZH22\M>@8)&7E_@1RY[(O<6]O\+\7>1=S$2@NAD4^&2]"=)NO-@/# +MIVIZG;]^X6&M^INT_%-$!67F&F[=S:.XTD8W?/^INVGB5*WV1Y7WV\:<)!XA +MII$O<U>0)A6OTAL'P<FP?E*@N:+-U-#5]TUFA?K(D0HJ!\4\J6_#)0PQT9"+ +M<\H%.&JJPDD;7$RS==!E#'4WL!C\[+G:7G0LE+3WU3PT_3?RR.?S-*Q[#(/[ +M6129Q@="MM$ZJ#[>"F]3<2H(..!)*!#H<3&)RJM1!=D-3)_Q>DJAN`("NX`D +M]ZS>D[MTH'!D9L%9=$EB>!U?%EJZ\Y>9`U7\\:@37Z"%OKUV[YMP=5T8+FN4 +M?K@\JH[E#)8B]M1((>VK#2)E<US''FES--Y1Y+9GET4.L(NK6'%ZH1+;'G5. +MY[06H0HP\PT\TY+L49P:-%D+@LU9HT.""@HA_B`@WM[JC>734Q[7!/FVK(JE +M<5`<84Z#C!`R[%%UP]>XN'8JB5/"YU]3TZ1S$RD:%THHGO5U`$])]J[_!\YH +ME2;!-5S7\FL`<46JBO$*I5]*64Z+NY;32W_U$E;-X4DV,Z2,"`J90"-4)VFA +MA&%_JELC=,_3\FB\&,`.\Z#CPKC@2$OU2*>E5U.Y!BTRXQ`^T=B$H..QP%D' +MXB].]E+8P5PUD]+SM/T8_XZHM\1EE)O6YFJL73=2`Z%.$)O5T?2:TUTF+&;B +M&><)WE'L$?.U,2;+BQ?1_Q*7P]X#:PSY3FG2.%%*$6?MJ9%(LR7E<8M,.&69 +M9[Z3S[`.+D:RZJ13.)JK3R0L].MM"WMA.]T=3%./TI&F*>\&B>]$[5H8LV,E +MW7P^'E=209CEQ4ZLM66'[6&8KG9#=5]PYB3F%4#U$$0Z#H/>7/@C"ILBH;M4 +MV*\GLWE\%7B`=)(T"HGC1-MR=";")"]\7N<AH+NP.>J^>_,2`0119Z[=C-+9 +M:$H#B]0V#XG\>2:V1A@#[`-;;:VJ'FJ5P&2?CP:<)2IL7HJC7[17`3'VP[AC +M+\TN-,DLUIM5C97;=+*@_N4=T@+@L^K&^S#=4FB3$532(,:S<)`:>=7ZU*S1 +M!=;V@.YH-E81ODJ5OR/L3'A$48TZA6/FGH&>FO!AF'M8A99[ZAN3FCG$GQDU +MD,P.)NCX+OM#^.`<<9AM:6#L5-TO;OV0A)#@YPB,5JB94_7#DH5$GFV%9,8A +M5YF3)>8CJN.FZNH/Q^$8()UCY4B@#9#YYAJIBZTBN'VL^B4[A]UGA"5T_L;W +M$X]=J1+,JF`FGW8>!T6`)\)*_PX2LE&]C+9_Y'D.K%P@)XVA^M-9E^RR)/+? +M_RT=NIA1H%AC@W3PQ/A^D<0>_-AF0@&,C'6RK9'(TB'2]C=]'UHS!5#F<`3+ +M0H,]Z7JF5(;\2E*I(\$8+);0O_G@ZV9H>25Y768MSE?LY?,O0'@X"KE+H,M< +M_K9TEDZF/UQC)L"M"/DLLF7V(XLF_"SL9O<H\5/,G/;4%Z]/"AI1[-,SD2W2 +MICC_I\#XBD01MR59DF8?F:>[>]WXYJD_N/>N<YD:,(7)Z%M/53;YJ\?PEW`) +MOOZ#QJ<&@%W<H[I\JBI#9](W,)<S$>^337P`?7A5@.D,80M/<J[<:'^LI;6* +M?KKOP/;Y?J:SF^&&Q(^9-B'BV0,J0H'196#\DD)5,&KN)A`FM)`*RI`$.N)] +M2P)@2:;X4(EHX#O&5WQU7#(,<;2/A=M<>(9-O<H@:98,L!B?$PZCL:WWD$;P +MNZF(6T[0_4J5NJKHZ^#ECRUK*ZUZI[,G'#0G[J[#WC19>(D^F-H`N5/[Z#&Y +ML7UR(."8+_)FLO_O!T#BMTV[4CSJ21X.&H-Y_*_8'$]`K"6@EQ_F.R<_S$Z- +M]4M??+R+M^GB<+=1R(:QG(G)-_DGK`"D.2;`LLX1FQM.7T=V`8O9Z,K&/R)2 +M[+\T<G=<"B<D[WM@SNV^\H.XUZ.GU"&^MR^,OU"-)V=*I&9M`8JWLFSXWV\5 +MUE6PN5=%29E6*-5:"HJ3)<\]THQ#WSG[V]^%/+2S[P@E(O0Q!&E"U%58>1*? +M+M8K/DTO9EUOG87:7]-5X>NJ"W)94Y01^L[Q"EYO%=?UE3-PD-Q@I2-8D&M3 +M-K^@5E(F&I-XW1(+2C$!N74N#!KRMKN8"5D"4^:+)^,F$K3SXX73)>BJ/J87 +M2<(+8;>/1-(,0!X&ZJ*#N$R+<4Q^``[QIQXQ#Z:+[0BTHD"H67>`*RJU+:'< +M/`72I[-KO'-$5E75.C@6TO:RLLC`_)X^!!<SNNRW&S>MYZZ<J3+<!0M@_^/? +MBG?5%)@OJ(;J<E."[I)%.(76`HG[)>,VGEB]:+GPT3IE>H0P.CX\"._YZ`@S +MM]83';;'CE`S9LD4`[F?MDWYD<^'N&*BRJ>Z1U\K3;AK<C2AX(&5N0$7-G&7 +M">!WGN-],CF(=ILM'*=SW[^4F/EE+[/\UE;^#5:HU6=\,Q%#8(/W]!FK>"UE +M8K;,(DF+C/(&C3#]N+KZ32U&<F4DW6QI*+?I+4_=5_;?8-7((N`I5JJ/NB@/ +M?LCY,%K]/_02E!#KR'4H'6Z88GB58V)0])Q&"&].Z>TMK&.?$DD&(.8R0]LX +M%9%%%JT9;%O_>P\)<B7S)L_Z!=,#\`P4CQ@3#/UGSOKXG30B*)*#ATKJRKZ/ +MZ>BWYBSE3[1+AYMW,Z%HA'"1;/405*OSWF#>JOD:+LZV9%HQ-+T-D6R7XB87 +M*T1E>$!`0+><A979&R')<1J,$81ZV/CB@6=?7_=2GR"7^%<8&(/XGLB[W0+. +M$[_RCW61Q'(KH%$&I.S8>+;U;G-G9)58,.1I\*%,1X0>Y?'"W[C;1MQXIKJL +M;:>\H_I$.9L_/D=!MX+I=0;A6,$Z727K^QH[R7?-2-!%4TW_B+^:@HWFGK9$ +MG:6?:*^R:X7,'3.1L9TA`8&Z80&=P+XFH8"11XE4[CNAX`=?U]+@-"RDDK0B +MP('JNG*PI6MB9VV);16&SP'B1JQ;CXQHC8KJ8MKO>3Y;-O910^?(W"T*F;?) +M\]-[=/K5V8;FOK)^^0L1(M6<D(HT3V`)[\QEJA]O+=$8@`I`USVQX[3B).7_ +M3ETEH(L/8/WK6_#2D#]2!/*-8%UEY/<`(!Q"N2Y=W'ZH"QTC-RG5SE_6KFR6 +M(O`IB^NYMH[7$EQ(_`#BT3N0MY^*1D6R60#V&;YT\7*<"9C-.ED>V+=Y7=6/ +ML3U(^UB38\DJ\*0)A[L]AN&JI:ZQ)NSO!7E$U#U#>TN*42#?>@#@$1EM6N@E +M/O%CM6?@$_\?`94!'7X,NTCR!X*0_:E.ABU]J\H.A#=+5>T*1:'T(Q4]N_AT +M;[?$H7A5JV1*RWP=)S'T/A5>4X7P@3>O6??.1GD)^YR;B:3-/L\,C@F3^_J[ +MG6\E7)>(3LAKL(T/P:Y2CRB0@9RZ?Y^Q+O(Y&*+":@.7U,NI[=\835VMT7?C +M;Q/@6!TW-;!7[C%N\62W3@6&AODRZ4?BE1!S>-H%Q!I=3RKZ.0U.52(S,PXW +M[#`]BA+TZ[9T+A8:G1CAQ2-#QR8LV$A?$RZ>S(]C!PRH/:)U,&@KB:B:?7.2 +M+5R-$>Z9(FH-6'=67]Z)3D<\_="<MNU6#U5H$$15)"1ETJ[$0'DE4U)48/-! +M^/;:P6>KL4QW/?H[N]3*Y"4XC8S,EA2RO!\*#X9D7WL@"W_7QYF>E#4#6)H9 +MKE$(WV#JHC=_A1MV^$[UE:V,]JF*W%^!VJRMJ<UA1LW];W;LT5Q[1Z5I'.<Q +MG]!*>:LEV"R`X9S._MM^>5D,5:=-ZMQG]IJK-'6V(RPJ(`Y=H!DKFN&?^#,/ +MD5^RB&@**I!D%"P#QA@`AA%=>*P<L6WK(,UAOBT6O00%SYB9G,^(AM:[1[35 +M!332PP2W8/("7H!DX6`R#0!T?!K5UZP0T.PB-,LB<!,D&1C5_L&B?0'W[/D1 +M!"D_@BS#O.D2<.9(R]&PHN(BV8,&1&*9S&YXX9\A%POVR#5)G6C[3T7_28H^ +ME6J8?*H3.'@[<@]>*'$E:@9(%_@GEVX.1&[ON0R_/0N_#%H,JYI4U3+)-FB_ +MR1.A>[8+A=8@B+C-D'^2^48@U=XOG70'SC$[4U8&,NQDV^KS\`PA\3[(JG1S +M/U3S4S>+8P-)F!@'T)ROX=%O8EU5BB=F8$WU_=#2O27%=B(94V]_79CM@EQA +MF!_]A?OS,IG`GK[7D,UQ$]PS$V!X3NL+8*TX\\\<@3+]<W\B+<-'UQ/(+Z.? +MDDLD,Z?9O^B$N2"L>O4#(8&Q6Z%J?M)1*CR("J%=*H-IL?@'8-CEVOH^G(.. +M6D-"MOWFW!2:\WB/!T[M(&F9"7?`>5?/F0"7E+E;[!329T6YT<C-M^;0^BF@ +M$RIC(CW+@2B;WJ#.QJX9/WLSD_H>H.CC;[+^'04G9O"36F1*SIZD=9KE9\^^ +M[*MVA?_T0RLN6SI<IP%Z]=<`=7?=)VUT=5`XNR6XKRE)2X3GJ"(T]Y=5I4_J +M9LCX8+>?_?U#XCS=;^0KBFP51IKW<#[V/]]H<YNS=J$0XSA/X#';`L\#P4.W +MT.`=O!^!C^@3"S32M56A67^Y&\^RFD8JJ.E1BQ>,&N#?ER$\L-/W"RK1F;C6 +MLA(Y$5;K?FC9.`W^;:F1M3=-7]^,FB_L4H>2_O>#;K&>X/H+854*F[`,X$R" +MK',-63(YYWT`UB##OZXFB49U)CC2G9[;=2TW&+L&XO1D-0U4M>*<*>Y7+00[ +M->WN"FFB8$65C&,%BD)K(/P:@.<E<ZR&;(@O#7[7>-%LCCWF.?OSZL&C?]3W +MYNU!6:J@?=->_J3\$3JX@E?QO=Q;4U(4T+[&!A3>7#/,^]8LWV/%L#DD5Q<V +MSI?3`++"@ZV)-'`YV2?EWL1G_!H3:XW*F]",^%CI0[]P?7PW%<(MQN7-W +MR;$TI@HEG_KCYKS)/C%1#S!C`;P4A+A^U$Q?3[Y7^O&CXV_1"%+Z0D2@D!<% +M#3B3*5M5?:^2HCQ>E]@YG:.3_N>K5B"\:\+\@K1=<?ML.V71>6ZF/!%``:C% +MJ?A*$AAS7U..#"HWQU]`=L9U%'Y&W0)V<YJW/$M+TSS)#),KB@TR'*[Y_@W4 +M&QAW7867IT0%0_Y/ISCS_R1DO*BTM[#VW!WRJH`]R=Q4F8O]!^1L%I?5P,-) +MB;7N#]#LW3[0;CAA+VBTXXINS6YD6LN6R/\^?3W>?CWG6+LQ1$EYCR1L%OMC +MC!!]W-+/*;49C3VO&^6`:ZU3V08Y4)4^SNK>V><X,\HUA&+;R()CJ%7Z=^NW +MV/)5*>M.G%/T79-.;:;M`ZI"TGKK(Q?8J_?:6XXR2E$+=3WD&"J=<S_R.U.S +MZ#[O>T5VMSMTVWGG[8YZR:_!VK(^=";B-J=K#""O"TZ/33,L>4IM0I9;*3,@ +ME""R>&<I;<EI7`6;*B\QF(15W0\!79YY5EU>!8I%]&>N.M/:HL&Z9;(KYG%M +M'>24=R>@/.5SKA[G$7E]723^I!C'\>2*Q9@/OIE,>@]QDVL`\Q8W(EKF4$40 +M+S\9BXM5;OVR0E@F.O2/M._2.(#X+&5,.J`P!`M[C(.V8&ZFN)H$F(Y6&9D= +M]VR!]8TV"('L[A(EQ`]HY*]U_VS!^-31X'?->I^*M\U,TJ[,"7?QNVVBQ(-K +M`C0#>S#0U2]15Q7UK+K`IZB@@MCE+5MLU]I]YY&7!\SOROR_RU04Q/N\'NQ_ +MQ/Z:GVQO@U\[N/T;H+MZQ1<;CCI9M!+H^^6.ROCN?G*\'#49S22NHN58KJMG +MEMW:1:GE^_E\=]&<-"F;TP)91`=3#^X*"ZP1Q:Y#_-0("]J^7D[:RC236OP8 +M?L5O)"@H@01H:$.CRQM5_W6X8-,188P]U""E&XXY1:^$>>)[$GXB`=@TCV:2 +M`(&6>0(?)*\DL5<I?"^35BK%K^B0`$FH98OAS9E;%=#/T9&3RC(;*E<PA+2] +M.<V2\<9M3<Q"E[$=2FR%+Z<7O,5<PH:2SZ.&D1NR*G=/WT0/T81,T2H!6Q,X +MVN$EJ/*VBG6RQGQB>X3_PP#HR[UR=<);"Y[LL!!E.R63&W<.7EXG+=EX>4%& +MS8&T\44FH#*98AD*;H<*C1!R9N-#"4=9/^6)&'8ZUCAWY<RA,%/K6S,>?*1I +MI*UO+"X;-9=!?/^9N(@U%(*/]^C9=K+:I>&A!=+/Y8`O7I.@J%11CI%^,B'\ +MQX:,8.$C&__UN<8N;"OX&^F7)9GA:NL<L(Y]JH%CR[=J/4!79$JPN1IKX,(D +M@#E@\J:M;+*6H<Q*UN0SR,K:?SQ[MMOUIA$NB$.S2!C/'M<7?QC]7;+R!!ZO +ME7*8)P3\T'K;J9/KGG]M+OU-DI35[KO@P\?INR5H@`)<\[_7%8Y4RGE]E>1= +M?^\,/UQZ=3Y*BFTT#/)<E?CHZ6:LD87GA=G,:/_GHXT=X/027&N((9\*,FZK +M=@<<($C3NJO'J^$)\"!CBBTS%[5L:ZY@H+M),1K^DR8'9<IN/VM8R>A4J#][ +M5%LB/$-Z^K"+<1)^6A-OF%W4F:!=UNE&DX`.R5<$[0!ZK'DG96I%PE=7IEFU +MBZ?<S_$;`X"OEB^%HNUN]WC"Y@\RVND2OZ"^1_T_^"+*N_8'1/W#"B@A]&"B +M>/LQ`4SHCLV#H*LC)X+MT$QDK]GO9LZA(3ZI1(*;PBC&01)#SJ@K&\H30BO@ +MHUN<$V:.HVNYU=`;5!?/NN[3L]/W^6^*\;B=R6=G&E-J"]N^5?;($[;4[QVR +M+MQ9N`]*=7!@_1:);OP0NC<^TB#\0KJ)R<0;>(S;G9_UB,K/7;AY@G`AAU<, +M2CJ;Q2T]);W..'<MV(9/)$OR^'"9U&<@9Y7W^BSM2Q5I(D$^/&KO>%NM8F^( +M_+(7\+?OD,@Y]%19FKI(@[),W/B`7EL_WF:W<YP"0M3*;6:]V;JC&77I&K$_ +M"W6IDRC)*'E:L7/6T5IUZ2[&CW-<5'$#9=NKR4_UOYZ."9'=OB"J93_H#J\D +MV:XF_64#S'YPSM/5WVYK9[3+8C!<SQAG]#8$?E`NQ?C\'V;GNQD;!;)[+@W6 +M(`'I,JQ!4NEU%$S7>3OIH+GY'T3B*9N9;Q^LZ!A!I!G+=RD`_J`P575[#IZ# +MBS@?_1.NPEC40/*-+&,#DAKLN\TG^:8?7FA0"B&4HPH0ZAC74@7T4:W+>T\\ +M'U<FX!;3C/V74(/?FU]02%333,9Z`%49N_L8S:L12#[<K6/%F6;B<=&^+BJM +MU^ACB94&4&4@=U`%8!*5W0VVS-+N2EYW%\16CV0:Z1['>?;GL'MWRHF_[X9Y +MS_6[S)A/B^;$+J'"EH_\=E&7]Q(A(U/%!+BBJ.1@$\8!DK+[WYO\UP,!#FIL +MXW+5"\*]&@TVN%!$/2=?O9(4Z<(S-+G.S]PUNJM"Z8O*2E+ETYG*0!%T+72P +MO_3)HRE3<@7LP"GM3079(@PH'5R9FZDMH7AA5'5_CF61G98^O&4?'!99$D%; +M5G^UNLVS$.&.<(Q!^S9GH57IU+M2BL'=_3$U"68\OR'/"VW,X!(56_V9P*&J +MD=X3T"=8]0+<<"=<&_";E1-+H"Y`\4E92.];$?GMCSSX"XD.-S[6GFFH5J_M +M'?'[1CX&WR"S&!+)4<R39*W#VB4?WKN'M3V8C[7#<@CX;L(1$)J-$_S3SD-> +MW[F&C"C4EZ$R='R*=F)Z>"LC49<G@!86GO4\^!N[3[<*[J0W`O2:[6TL`+'P +M.Z*\QED3Y6"`&A?0W4:I9#`*]6P$F;W4L/#0-"B36I5X"NJ/..12E*F]UY5M +M3F!H%VT][J[TD?_R5RC]5?NJ]*A).L5DSKJ3T5"=66?9X=AMEOUPJP_.7LQ5 +MDK-$#QZ@6\KMANX%?#0<IP"08O]D)#3Y.T^JSDR1PUH:3?D,`$S1`?Q[+WTZ +M1E:9&LRCI4GA9$5"@>&B=DP7;-$&EY:A2T?%\8G2YC7!&F,YXXIRN`]!M#28 +MP9:7<U8J]S*7`&X+>');R^V"6E87V(ZV_K)$9P+F!A`D2V-\'BO(/RG5YCV& +MFY;R*C7F)RSOM;",L@#8*'-S<?\QSP-Q#E.0AMO>(!.U15E#R+K$1YD"$%G6 +M,@1DJ[ZR`RFH)6]3D+*3ZC3G6C*Q#4\$#[$-G3WR0XJ1YR^?P9*S^X%TMSE) +M6",LL;VIN69KCP/S9GNN\CP]>VDL")CF&/+*-Y#7;D:WZ?ULA2>>^!&4`C6@ +M3')S*8[OANJC^698]]'1F7+I0K!X,FKF^(T!`503"CN@($B=/U"*5KUR>S?Z +M9N0(6)E]FC=(6O9%NZQS)QJ]C(&D@[]S,3S+^M\-X&<)4*OR/O/OZ5HK&<QL +MZU3^IQVY#0`1JK+OIS:.P89>C`)UB0`:JYX=[JEI>A9B8=TG`<Y$:)@WEY/F +M"7N;WY[;JF-;3\=*8MPK99J(K#F"[7:IW'37V;=@5H&4#_7$0]*).`+2KBN+ +M1#<FLNQY08)'LP7&#'EK#*."&7&X84"*B<=T2Z<8Q"17S)"#L3V3$VGA.<C, +M";%%SF(/Z/4]SCW1Y#<D4KV\9.1QA$H:24A?UV6Q10]I+\.]$8U&5BO(AGK/ +MY1/$*(*#L3N56`^)RE_/)$712!-_<$*<L'>5>$WY!9S@745#O[-7`@*IUM&? +M#=Y,9IZ]EM+4E#[^%B3*[M"I_<4[IXG#B-IFI6E7B<JYRTPXCLAK\7VP@8LE +M_2-EY)]S@T"02$ZO!:2^]`^BS@.)+201/K7L6/K'T;7?:M9^+JWEC7I'30EH +M[N[>PM!_;6AURGH//C<AY__#Y^<&)SW8[`;I_632%NAT[(+99I%D/4T([V`0 +MU"^Q?/2[UU2P-@5&T)]=6!1L2;K)DP_QR'IU)R29%S#@674=*U1P]EZCG37@ +M4-_N:A\,*HF-J'=W+'\)K<1E:V\?HZS3HX)#/F6J-%PD^GE)JKC@RZK%\XY7 +M/CI.5,$)W1*N@(D$O`&G$+^HXQ;*Y*KC/I/URQR&IYC9$S!A[`=O2V:L#MC4 +M9P*K>2.V6K"'"@;S[U\%&XO^/&Z#E/$8*8^#IX&E.9C3/Y7>.H-5&Y`%,1]1 +MB\L9*7.V&Y.-PKG5<CB5*X?P3&O[>H>*0OE+XV+GS[(()%MA(<-)@3AS::QE +MC%$^1O,;':$#BDKK4)XMQH#R9!9TKOA>#`EEM02]_T?/XF6B<,"-!K.B$8Q$ +M=S&);%SL114GWA?NJ[6_X[]D45<)U6H))C>HI#V6_:TVX?=/(I!),J"OM9A. +M^3NAF&5D#4DLHX+=]<DB+L3X,2]@`15O>2\%),W"+1!+N!?;?5)T0)F!0[J4 +M#S3(=IZ,'7E8O1!H<A)B&R+>=.__R<Q'M'E7&@;KN/1.V`6'^Y9U^*2JJM%9 +M(&2QKLOVGKXQ-9IC%N0@#474H&!'&7RNY9-OY(`Q<;.<J$E3P.8@K#O%M#-? +MHY*&:E/M`.XRDE"9\\4V<UZURK3["WL]KQ7>2COZX$E0C12`UW<U84<O[CA. +MB>[.O_CIUO#ML=";H@EZW"<HXJU9&\EG]SD(]2$_-)T$N<U"BC)06!6CX.QF +MNM&_#CW"4B*YW-N.2"OVR'X/C4T`FBI#6Z>TL`H:&JD"L(Z]520QES:*9<.U +M;M!_4.0.A2DN48J:T(Y*F%DZ4C?>I?SQG!W5#CWY:#F!TP_%ST\U&;QC_B_N +MCB9'%@,5[!QRB;P`)>MKQ[_B$$:<\M;A,K+A3(/_"1#.1]^O8UO_A$D)UD=U +M.TC79W/"VKBU`+S>[%7!E5J`\>)D<-*">U`A[I+P)_D&`-#BT-.B/S<WEQBZ +M:G]9L8C24IT3\`B-BR[&3&4,^`)YSX">0,;T/%8G'Q`*`9`165C-<BE17M#\ +MMS;/^S\)!P+>?=.<S54$0>$!`EHU]0WI+1M1*6G7?9%.(<V'Z-1:)4&)2"C7 +MR:*Z,(OT45"2OC:B`G94/]7ZPU_:@`*63,^P>3)<5!<T3K"/-4%]KRQ\AKSW +MQ(OY"9N!&^<E;N,YAK0<$9S@M]/98ST!F.:`C`9F:-Y,&H^=E7:$[,F9&`^" +MX:O9G`\5U8+USBN&9M]>*EIS"=?6'Y)<3]]^2W/`)F(I[:)4UUAY"`L'3$>) +M7$/C+AIMVL/YI8^'T?73/JI#QXHLE9,?GL1IVC4DN2W@&66HOCF$Y#$6:_)9 +M"/7E46"%%6;IR+DM$QD,!-.'&*@(!R]\2JKJ$GGE#R7TL^RXGS)EF1`O;S<` +M/K$+E`)S187.$5J_D&%3.FH8"V:E`5EA#S/(E/;'F-D9C<XXGDNN<K_^0[*3 +M&JTBIU7H*+)XI*#42OU]BC&ZD44[X:1XW:@4'H1M`]ZC2K(^X.M"O%_[=96V +M_\_\-H3]2C%A#MERJ_\OS7\U#:9#K.;5!G^1-O[M.VPY%(<#"&XUIF@DS.S5 +MQ)A#01]Y/RB-%3V.X:^S-!^HPYJ$'/R7D@"XX&)M)F-&N9>"@=];3OY9V654 +M7('BZAS9`A%@[EI#2LIK!/9DS3^K2I<RF-@NAHLZO\(52<V0H",]6(9PI+2] +M9!T4A1"VZ[$,Z1.EX\]C4)8&=MJMCE(Z;@+4,_:>Y!$.F#25\*U.ZM]^,DM3 +M=;>./6@$G<%!E@7?1PIT9V2#,%YUX_TRWA]V37@[49JUW?[Q`;75A-8L3;>& +MN\>,<((A*4!J(W\SWQ)PLLVV/ALO=S8-U1&)F:"=*3;L_JN*NVRF]Y_<[KC2 +M+8/MDE,'6X%<F=!7?882P]\\&_Q+[W<?/?TVB_HEOR[<T[5LRZJ@K*SRWFS@ +MFAQ[[3*"\TKUJ_Q"UMA/X^B+*U@NZF)N$0"'HU@0Q/TR9H?H3JDWBM/^$+J9 +MHD]."?W9T8&-DXD_"0-X%%.O3R*D0)_D5RR*)E5*4AA,+U>NW00P(7'OL_JS +M%J=8/<GPA!L=54I`C.?@S%R5JL6^Y@$XS&`M$_SS$@2B#CNPW0%5$\B77]&M +M(>J#]]++ES^`2$B#X&)V9QQ#,UGY'7"JH&%]#$T4\5FSL9_O>GW"D*/X\8X@ +M8.\(_T_D+0W]/+4#3XE15FK\()!BD%;M+/X3H'4,@[465(W+ES#XJ/:8AM'9 +MRI+S5%O*RT:QJY,79=NJF.)4\IW'Y?&CUMGJA'/=Z62(VG+XFZ/;#-2Q;_E3 +M&4*`"<'\^:C-*[]MD,&JBCBXL*@LM=0,<%,B7P#UPU4GP/,`J!'`5&DGQK&T +M95R`M$$GN!VI2$$5C%*8LP2^WV.@)@5]JP%8N)'58Y6#TB[MB+F<;[=:1&8) +M<X.H!DRKQ,CC[Y;M[(#+G%G85VSJ.OB,VWR@#0'U)*4&(SSRW`9C.H)WD*8. +M4*G_5$R*722QSF[`<4S!U"M]@D:);+#?)I<\*A&C63MY`A.B.KYU-+S?$Z$C +M*`MPW0=B;_R8&E^CGR]58T3`K.W=;_E9/55TG%N=_6DY@0",MRI,1L$H=.:_ +MR0@3'\1UT7BR23AT:/$%`G,DM*U.0#!:YVYO1S9WM-^*0]4E<0W-%EPV`K5+ +MNQ%C8W]03C;WNSFN1G1.GY=_<&)<%^+)8`CQV>:R[#A6E%X[LF[9S(BRL.4Q +MMPU(';P<!HZ?=BR\OF07X"'0NG1I=0GPZC*IHNT$/W]+"HSR[5>X](\1X+2R +MQ3MZN\JHZFACG<G/LEW?Q?OIR@-_[-)F98K12*+5#(K);.A^5/_C.;98X0=" +M,[XV4X(V9"L5HWHRW6`-Z,.9ZT9&$PLT\O:FCWP)F!I/>Z.\47;&R+/T,*Z7 +M?XGY*D7L>T;U<SY._@\,M<]_!\UNQB7EM0@@=E#F$?"#>`A2G=N-0[&DLB!L +M94_9@Z'N[GA2UVG8E)WR!!M2R(VL+.A)>"#"I9`)&>9W-`:V>*+3,8.&5J8` +M2_;,B:4X7B2SUE56_U=D0WGEORF&RCY:%4"_AIYZ!1(J/#B$Z!"WF%,,&0FS +M"DE6FP$BZ/X1]Y?U(95R%/^R6\Z;P7\/R4CT3E][^^\P-5ULC7^PX0788M^\ +M001W!EKTD.X<$&)N5=<G=[:H<JXZ,GUFL_1FKBUX7U4#7OD>W2F,\0ENT>@H +M$@-80`.<_@!K>R8(+U"VY#N0M_-;!SY65#0$JJVUC1+K%G?26_C<,)',I<P$ +MYQ>5=$G0\:EK5,*$)G]YT>0'OE3@"['XF7R`!V1R/*O^3V-OHMR$3]<:9D<^ +MT5/INA7<9ZX4(<.])KNAF)#C<>7>7'"=MS"O<D,/SJ`TQ,BQIQJ@%9!9DTA5 +M=2DQ,WFW[5V.X#`<Z7(J+FAEC02B7?<ML&<%P%\;9QA@4V9MY'+G+<@:>"/D +MVJS]Z6,P&*NS@#SIH0RJWL#I@2IIMELQE1SK_7,C^,/Y&'CJ@@0N#>@F@[9K +M!]<>N4*WT,?_01]HUB?'UH@7@U@^R4!\*\#(N3EYB<7I[-Q9L_3^7A'J8W+W +M`27!B;;0:_E'TN7U=M*MA[-7[;9K4'L)=<^N5B!J,96U8!\&K@B$/TV$,Q<( +ME"G`R5;%_H?XWO(_Z$5-@_9WT>;,DF6BRI(@[G-;[($*(0!<%T/C^Y9DG6>+ +M,9VA/_BHL/!LE&_=-=]MP5R^@S$+SB(PFY<FVITYU\?5D9"E1`=SAO5T@5H- +MBQ<E%X,2X"L&E0D'\I)A[:98/28ASI6K<)Z^JYWBF5-R6SU4X7B0K4I!3(?S +MMZ,::@O#9*B&8R&A5W#R5S+0M[B\$3&NO@SA77GOCI%<#,7#F6E*0VNMSRMC +ME6'Z/<0:>-)RHI9?(IVC]M5H),#S@TFP"?H^E*[C)>_(@!3N-2(#B[/#BOU0 +M!U#)[_/CED^ECE]#[[3QC((%A<Z?DFJ)M>5-T3*S6'=HC_,$OZ`P"CJ2IOM+ +M209Z;<VWMF,;$8(C3=2@TT,U@70PEH#Q%<L#BP33]=3V41#A0\"B2LUW_I;" +MBFF-'JT5"]6;6?G;?:)N9%"'\P7OQJ\D1SBG<-ZHBL?.J>U\NT[J550;%`=^ +MV'!:P)L%F"=(12UKHIE=7,2'T(1E>DY&A35Y>O*_)H4BLY[A5%5X$3\#QIS) +MK::SS,F[%[9?@P:)\_-"WP"J3UV/N%P'\_D])5NX!3`.JD%B"NY)"RN>LDJL +MTP;Y8%1WW"'BDV-@"%[-&K;XR\2AQ..1BS[%+Q5D#2Q4YE6LN*#L@8S@:3:] +M$SD!VA1I;XW$+4XMNA'N-8-3^R_101?BBCYT!7C3ZI_L19+"[ZDR[S+L\)AR +M;.D89[^S=?6R&=$FN6DZ5W_&@9D*-E>20BV";",@F.#F8;:M`@U="S!'G>NJ +M&-<KK:^,4"@NC5$B`SC1QL,J*?K[JZ<K_FYCNC%?"+M9@-Y'1WNHNBE,O`A3 +M#=Q[CP5Z=;06F2[:%U'*JFX5;]^92`)F._+F?==Z]T/!7D;-VS0'T_<\,>ZC +MC:D2/1D!BC-?]K(GQ3<M`KPH+V>I@%RA2^U:J:_!"^=YMNO,?L\/1-#<6HCZ +M=^Z20B#$G@WYZL0];YJ\NHN\>2XJ="]XJFC(S?FHY^/8Q%<VH,<DQ"+FLU3M +MMJ>>&HSL0J.ED2!/[=9O`<2-#)K9].U`L_1R:VC(S5R"X=`C.)QZ$6VO6-_9 +MJ&QF?GTS+(R/'WM/4&J\[#$6`8J*%>!:I<"T\(28XC-ZC&V_4HO\K>!1^A0T +M6!7[C<DJ%)TCFGSW=SNN3@C3WS\5;$5!Q4H5=Q44LF["6[@1@D&&==G1*J`\ +M:N^<-[V7NT>5.,6*0(8:%(E[7M+:1=`Z_N&$T+X!_ZD[A(5.;<$["`'\MG+G +MNW..F-R/ZRX8XS@B0(R3?>8"EGZ6LE4C8``%Y^^205QPKQBZ70SI0ZF8(QZ; +M6D.^XUFH35OL@*I26A[1/Q+4I18*_-WTM$-SD8IX\>4[A?-%(+VLQ<E63JNU +M49./O(E.+IG!)QD5_W'7W:]S>MUXN\6*X@X":PSI@$?QJ15X4P(XU7ZH1+T8 +M\F#L6$^:D/EUGHDP]'BER^&A<:9%O/G^-08*2.M,0V[[>&.B%\$$="!&CUF5 +MSL@0&0=V/)IEV2,YNM#S^&%)[O$76FE2]@-Y-_:>J*73!HCKD*PC>V(P-+WS +MALZ,NYW3S+#3Q>Y"4KSBS2@J&Y;?61UG=UZ+2JPW:Z^'?>\$5SJ0\.J/$88X +M^JA(7"J7J\'V2N*A*LK#%HQ(]:&,\KJ+PCYHO;Q`$/[5"<<NEG&RO_LAN-N` +M(VT8!(GGQCT87\$@1O!8J;IGW3O*%9Z2B';582OPX5%329G<E=KUA',4GRPR +MT&/&I2_9`'8AWN[H)-Q'WA:`?-C"_OO0#^/5.:?U\[@/)O`*EV)R.]F=[-=3 +MGS',*;JD>RQ),NI)1>]*\Z9UJ?\3*:C-YE8!0CSAN@[DB6$[4W!V;#]'/_-= +MMS:]QO8DY*UTI0'5_0C;*\??&+.M="<&W-V1LMKEYD4[(5FO7U=1=M@QQ'/? +MQTB^Q,&>CB9[:2\B..YQ``DXQ2YMUJM!KG1OMB?(J:,:"BA4AMG!*4Y!.R[2 +MR@HWYY`G*C[T,,P$;)#T$-'HNL<&E/G#>">=W.E9#I?B5C*"17X.-?LD!=SG +M$R`<N&&(&`@)34PILXNC%$&B!K&O!%\JEB:GA1V+J<4:_YKP]L>$4ZEA78RU +MMC(K%1[!ET!""<'S#D=`)?A*&GM0<)!E.[H\7Y]%]_Y(A5QO0',WK#%BY*ND +MM)H5GR$_GT0S%GY7V5(<JAV\E4NDN-4B#!27.C@G&N$&B)M"RS?5\TERR'$> +M@C.9<:BC*;QIK8I$X?TW@R"A"^.BVKWEA4:6",B]QW2AV,^WH+:/L_#--+1= +MG:9F#EK$%77K21!*PX2PD0IMEJWB5#TM@!4GTD?&<93;?O69IR%_O?"ZT>/: +M.R:\26@/-X7:HU_,(R^N4G<,'[O848MJ\A@5F(*?Y^M,HT?Y=LN3DV.23RW_ +M)$(70H5:"`[>&BAC_YN?95EU@(;M*,65P4#9E(>^H!:CA8)1NP:Z!F#$]3W@ +M&YG4FRJY'U@`_X(,>W73M5N?:@K05Y<>1#RPN-56O$*"C`YD<N6E?*X]IFXR +M8PGI0Z*Y<XXZR4GLE$;Y/YGML6+H\@S,A=\SZ2<A+W#>-NYJW&O,OV%RFE[! +MIL<!DP8#2K4HK%NGIVCN*@52R,HP.\	NW9U"[=_\UW\:@S00ID->3FT<1S +M%V%*JJC-:>RB^`33N:A;F1-#.\#:4O?^#Z\$Z:&QE<M2IU`C'^:H),2(H5%% +MZ^*F^(A=`UF?':0$G.:>5E%J,6F3''%S0`GDE)ZS+3\M6!L6L:(W$;@8.10> +M>OBS+]6D=H'6RG'1F1_A\0YRN<V(U/A:0J&X=W^7JB)AR4W@,?6>BQ^[*7RK +M3DCL67@G;QCLXM`8=?ALXPQ]*@J&YVBZKPE9NQF/6$5!<D)V6Y(ZFI^@0XD( +M'G.&.W!RT8;/X))O]/Q11S-/83[CBJUE,A=!J>H;'ZK.$_6SRS#[2")@2\O9 +MW^AP#1[]+X8B3`>%2<1*JIY`TXRT*=E=M4JUSS"`0.77PSE.U#D`<8OE2[[Z +M^_9D$:GP5#4.&=)9R9_IPFM?7$Y=_UUJ*)2[-$O_^;"V;,0F9-F$K"R5ZFY: +MDSKU+$R%J3'2I1[]B9F`SKD</T^X`3;T$!RSKYHM$0G2]W0<JL]*[BG0$LDC +M6WKY'8G##+Z@([,X"/(U@M*K.US:;_#$R[!N'ZQY'#H2A-;!V44W86!992"3 +M97["0?WEGVP7PC]*1QM_`=MMCA^U*\3%##C_J1RF"A4=H'#8\;$%H9IT3&G/ +M$MVU9H&L)Q[SN.38]+2:;\#LH;$R;-=U<[D5=Z&?I`M4$#J3)&O4\ADM6]@. +MQ"^J'C"^BBB@GX'M(U!5E-22WX79A4Z\DKBB85:DZQ,WU@QQQB'$-G_:<5HE +M'$Q"4U574WMGQ@>$*+@!7>`U^#.)8%[C^LAZ1FB1/L`MS0UK](A^KSH6$/15 +M"U/$R]']HM9"?>49DLEW*!B@3*_OFTAQFDM:F;V7$?B.1*2]$GXE!<B$J#7V +M9<W0=5:[`I2[;'\^7`N"EO%K;?>^ZK^8+]VV'FU<K_\=-IHX@7*]I+4X?XH% +MRT.R>$([<>SN1+,XF.DW<`KN4-+D7C@0$8#M@?'$&U[#1?:.6TES*VOF8`CI +M[>P%T-,>YB"O$W"L?W<Y?/FAB3$F7_NEBO^4+1;XX$0S@Y6$3Y,<7702.BC( +M4CP*I"\6WD!J,9RFY^`?H+GTG@9I0^?E_<`UIF-C"J=B.?!6A%I.5@`5[S62 +M)VD0*"J@Q#(BCU5]7$E<]\2N%5)?V[#>YY5O!B2*X4/](3(-(;CYU,FV&9'% +M3Y574>"1841GU*B]^)-7[I5"1E#`I:[IXWT$>UFC&J[4I03_RU*MF_(@W1M4 +MD_L0$E9.[=-;N9%G)E]=5^<^?3KE!O(`R,/GA0"$??<Q-J7\VN<.GZ>9?"L5 +M/9N:475+W&9>#2S^O(;VU4@EB%;ATJ*O`>O,S&G%5,KP;(,#0GY+5#_8VP78 +MPHH!G"__#L&\5@=(V5A.UI,3&=*B^FU!,M0=0\OFWSM-,)_X1LAOAWC1$X.J +M5@Y`6Z%;)YN"IJOS6F"/19,2\CV[19^5WDT,S\G:#A+"C,SCC16HY4KO>@OC +M7\V1\G>`M-$,)>-0F32];VS2(P2P7WGHZ*X91:/P!.0]@F+G/"[<#<^,?X=5 +M:2$[!)#*(/>EWQN79;WK;VVL5V3*5M%KRI0O:GMP%,"NWG8!>CT:63B`?^`- +M?L7KP#@]D=8/4:5]%HQKSVJ>P/JNS(EV>!'NMSH!K]OA-=#0?T3B=^Z=$:WI +M7$W:6$@H^1X=S!I\UHMO[`3ED%+_?WRYN:GOT(UU+'[F?)\Y4(5$C=E^LBY; +M^9+5N$2'^!EL>YN(Y4`@9TKLM`A(0/6=+^3L'."*8<Z_CU^;/GE?()_NZ<TN +MT<WY!&UKNF::++@[`A&O')"MOC=`B52G'X5RQA)3^(&'`10S*R?13F2;S9\C +M#"3]7<:`!"!((%;S*XKB-J<3_5BS^DGARWUYNR99D\]A!;%+VDX"$L(<+TP, +M'%"W2O![M;B+D'O"<S33Q=SG>LM%C,R<Z(,,.+5PW5">/='L7OJ+6,W9\,ZC +MCAFFTT<@O?E1$[(KSVJ"YX09/0NYFB3Y>^G1+40YL)W"X;PBU`6-69`4H,Y: +M36_D8]W9S2>$CV?K!O<E1!028BBR$3X*J9TTVSOR'*$5,;OT8D#;3L^1>K?/ +M^>A;PXE^4Q/ZEF,,;+M_,?-/5=G90>JSZ/X3<YK8R&'8N=T7H3S3_D-=\+__ +M[12]$U(*G3N^5D^#I<Q9;@[HV>4Y7?A;\;VDLZ9<(_C-D36+5\GA`K((QX!G +MU?YU.7GN+#M@G<17A/"^=X?I9^ZGTDNH2+[XNVY5\6V;,+W`WDI`#R+HE7T= +MYYE.#JAR=\KMBF[U-_-F_5Q17/B'D]C'EEJ;Y;3!N+XCL=2UH'PAOE\UX=F1 +MIIU\H__/!O"/Z)`T`+06O[?`G*.)M'D+@57?*H@UPN3Q)TP>MD;1'3A=V$-O +MD2!]DD'0?I8D5N9Q!:A"KX.:I>*KHZ29U#*UYZ4-/!+G1,3N2QRBF$53%>3P +MS!Z^<F?1-!(Y@A$C!`_S$45W0NI3N#(YAFI'Y;C4D6#IM(Y2[ES.;(X25017 +MOR<Z,J42IANJ_93]KO2#"MNPGGW*YL$S;Q[V1ZC]BU)^X1]'0WOP;2+;>"0R +M'3!BU:,5?R<UBQ!?>Y_'3@^`8,@9'Q1/(F8!!J)2.(7B?O``=J6S"=/6N;?U +M>^)-&%A+=!CWX\6Y"'%(E.^7PEFOXIE"3_47.K$E<8E\(17:%&_![_E2CB2V +M\Z`"5I']LMUBYU60PD\W?AGCA8Y/$(-:L>3=[@3G/+YE-Y/=O*ZL'11I\Z[X +MEF=%O7;)T$3>+9<U"(?V=&4^(75P!E0P?<]\M[ZF=7P81^:"BC]RRJK)TIHU +M8Q;0H]X9_DCF7PUJ^]:I@4PJ7$AT/%D,D<5RN1-:][%L8!S^F2#M&NTIT45H +MM'<EH\S]:V__V2#]"O>ZN-&86I7`$W@T,*'"6(,X0[2\MQJM`KA+CW2'H@DB +M*)I]DN?V,5!>,,753466@)4V$(PGG@LK57>#IK-42V4E(7Z-?,8\$4H<JFDR +M\Y58U9%VO+_&Z$^.>0&-YTG=7CD4-=5L^;I;KW2*>=NN(_)$A(^9ZCX)P\7` +M/NZJNML24Y7U\&$83G?U:N:-JA>Z<Y,_OL"B\_R>M:AS\F>X7<(ES+PZ/,Y. +MG28"F"$N+'0\2'E,G^"(V!'X/\Z12CI4[B"1+%)]"Z":`#8(]5=7(<6*IU&6 +M)?KBZ'9L99Y3S)%!@#5Z@6?4V3@V\,XY$'O;Q1@WXA'/HFJAN"R\1Q20^]D7 +MM/1/1JC&?(LTQ-)(IR5BFY0N#`Y#9B,+`G/6=:8$WSIKZ#620@XY]K<R;$KS +M0`<-UFBPWNRO^K5RK%T4RO*@PYQ]2M>8\6W,.8+TWN\T>Y#8?X8I0W,R<C\E +MH;8]F6P50[3A-ZT9IO#?C>3$,#K;UC297;$\XJ%V'7V]N_5<A!"XG:T5L(FW +M:E!A1.6!^#T#'F;G5HR%>1+KT^AUUWJ'!&B/<,"F2DYSGBL6)0)`<-C8\^MR +M6S-(<P:J&#N'\KPIWP'&L5C48P0VP6003T32$DS3[37_/UBO1V;NN:'QJ*>_ +M9KI[2WGF&Q@%LY3[*>CK'%E<-HS-1TG,B]7;[A\;9-.?&)9APR<8S7A;T,#G +M^-'0E!%$P*_CY,S/]37R1;@>Y_IQ#M!*:^<H?5&'GNGPCDYDAA0DV^01C8^^ +MG"1+B9@R\YDB/WXVMQJ?^KCU&L6.+_>!W-*UWSON/3ZV!OB"L<,FNQ>N#QA( +M:0>U=)4',S(U;1T,8)/L1;EWI_92Q'A>[(CT>:;!5A+/:+.I0`/B&K2WC06( +M\Y]C9F"7B_./8:WQ!R)2W`'F=^IJ^.K)?$/2C[)$2:O]GU41%M8GT<MWQTU( +M!P\/X+UPI^!Z[<27X&8JS%H44I<S`CL'.H/;KQ/7N[44$4QE_N^-DW$AT4G4 +MXU[%<7$SUJL/VHN:"H\9B3[KYD9B+.4+HS<OKJ=M.PL(K36Z>B&GKE]4HJ:A +M;Y7H'FJ.6B%TBL*6FF,4OD!(=AB'%G@LO_E?8V(3$48W%Q3BXSG[,!`_P/>! +MG1S*7BD=N2KT%%2UGR'J/MS.8#;*M*"#VD=<S.C^W#DU!-0XPA%)JG!2^D5Q +M6\<SR6L'E+1A;84^L31@?6ZXGO"M]2A3P;##/6/=%5."5C(&#&3P/`PM$N*_ +M%P_^WR(7*0!GF,E%<@5/0[+!S1$A>W56P]<Q-B]!9G?X2^=/3ZR-31AZ3(VH +M.K*@VFJ;55WO9<B"(YY2$J&@I@R-(K1MPBJ65B+"2;7-AW9-U!SUO4EA'58J +M54AK=AM(+>E>6O%Y1=@%;3J2$TU,0Z%X7.:9N^DA):P5T9]EW\OU]HT(W#Y^ +M1CVMJ=UYPR2[:XLOL9[%3$'P3WG?&`+77U7%N6A/K@8.2H:3K#;KZ4'$V+W* +M`V<T$DNL1FV_=B"Z3P(/GFMIIUYV;X!US8)7>;,V$S'8`>1=):(OO4,[G9Q@ +M\W_25[BBN7UVI1M8J&R[>`7,<4F=0_A%-"[<9.?5=^'80MH**21UWT9TL10. +M/X)ZS@%9!Z:)<O7C1SX>YTG@@A))9=2$)ISSX\>R@#U]OA#A!5I)#$XVUCC) +ME?K?I_:3"O3=TZGAC@J)A/BPS66>=-`Q!1.')K..+AY$P!`>O307&3\`9.6B +M67*KB[!OI'*\(T&8P$%!KJ0[*18N5L^E(_KT_DBA^,C@V6/%T'@LK]O%>"]* +MFQ)O7!0_R>BCV1`51YKJ%NF[V;X%!ZGC(C3X0'_BL#F?[2L4V*Z9E<FAQT#F +M":LI"&_:-\X?72A51OE`@*7R%50#P%JL:]F^3N<CX:BM\7;MP!M=+TI\8QRU +M\G9F>K:O#>&'LF49,""T0^A@0]<Z\7-CPCB_HAM;[KX&=@,,XWVHKSE<%AK& +M$+3M.Q(^H:!F:A\R*,Z8DO%<_[1$LF9>0P,Z>Y<29U!#R3=$8,8</!5:!4S& +MPF5#%D&];N18&TQ^D.&R'E(MA>_IZ%)U'U&MU&:&?U,3@&`#=+>O.DR9BE`P +M56C_X<FM;-7>R3^Z;N7Z<W>"2S8F^JX^?XN2(=%X`QT5M:P2TV#ST?_3A<:T +M'DP2+-"MG#(@05Z[E;S!70WHNSL3Q(`<F`Z79IF-7Z1U%H:+V%6T@W=ZWXA[ +M6V]-2719DY],Y9@#0$\U?3#@$"W^?L2P#E2IYX9$)(6[``W2B^'>"/^WM=Y? +M$G(M:;=(QL!OU7;H6#WCL4@K?J,NXL46(30^'V)U1)"I"F\2IHJF`QM*I3;T +M)9YL`IQ+EJN'#ZTY*O77I+*9%>+&+<R4T]7C<0036+\;P?,5B@T7:;BB-.;9 +ML_3!PZS[L;V,.CP=<*QZMG`Y/AI&J7\D@!9Y5H&(7''KXXB[C;#K0@=#2HIC +MZ,[Y:44D01'?ZTZ.F\4=R>%'-PR*Y/^.M^M26/K9)3X4IDF,S%W;+/M0\)O] +MEB[ROH=][H'8H:X%1XH\^M&<1+R!B>VTMLK.$0:=O<N1Y+#A(1KJI'TBGL^> +M<X66)5HI^G6VFG_AU$>&-9<H^R/';;0RE&,K+_%;66!W\P4_0.8$37*UJYX2 +M.\=T,>_IWM[^;][CK.,#=/?='!_,?Y"/<AF$!L"3'R\:!9SA3@"M1=SRFI!# +MS/[3V4^9P&^KT]J<QB#=P0PRK";N?C>6>S;//.[I[>>I^BQRLD,==QK$'W6\ +MZ2X4,4\S],@300Y\KB&U00E$B07W,4ZLQ5$O%=HB8C!E`3=\IXOY=7;')*33 +MCQ%>$;-;A_7,#?[D_PY@JR3W7)02R!.9U9@`-Z#J*?XH?9T5(CJRU,B$D%7H +M5/'F6%!UPJY[\XCMQVF`.2%NOK!]L<2'14AZEWC32G35]NAT&M;P=M0XJ0M2 +M6B@G+D1"*0HB0MUUGVVOW^^AY3WD6BN+:B47#HLY-<R;L3S+G0>__<$J90*W +MPCZ\FDAD.8T9%K*RK-(::G:8/$D_.P>V3JJ*$:8A/)6<PN#CD#CGPJ`IL``& +M/"?4^Z`JOBC*C%IW4P/0X,T0//%#MK]P8%&UW42>.H,N'6RA$<JJ:\1+\EWH +MZ6A2)%X>"6R1;/&\V3-GNTB]=)+5A#V$_\X!BYQ8;(N$3TRNR/RE8&@%D7)C +M$9R:I%5%,5U`@2!RAJZ+?@7=328-[\;,,Z0ZA%J-!;037?EVTCYAKP-I/Z:S +M0!)>)M$#201JLW;%P3<:1XVA(H9>$Y`3!F%V_0L2W+D&UK7].Z!X$3:W5'WB +MG96^-C-6FC?;,0?(3`>ZRZ%E0C"DJ?2RW6'96#;"JE`0-/H46B9?L/\QK]B, +M^G*=``$&!EB'/9=RO$Y2;(<A*PWIHS$T8ZE4U))36N^LQTQRJ]U:O#^U,PPI +M$4I)R'5D,()D[P4V5=.5\?2(6J26.01Y^;GK03[[#\U^`E#-9Z3`6I=2*A.= +M[M:-/>:<YRA+O?:/5FC\-__'R+EO`Y=90EC@KZTO?V((*1$#0#\/*+TX3@Z1 +MS8D=.">TBZ&H*(T[2:;F)+A_TXQ(R7_BM:'7?]PNK%W90#!B8I_35)M+\>3Q +M2+NI4R828U67MJ='K5\,`A3#J"M*\2-60/*&T)2E(2P7CJ<:'OMT^J,B3#?$ +MK_'("27DFI1HNBP??)7$[L2R'<U."UKDCWSLV&9F.Y"S#.,G9:5"\5*$6BRI +M77RJWNXUG5@DUMBRPXBO'>!:*"N8]QCR7_599K$EB>C!P-SU\C34#$B9_AL, +M.:J1&>G$M)HE^\:[XVV$BW35;Y*:3*^M,2;L:_D7#*3X@DI;C/ZAUKP\R?21 +MIVP70@$EZ91=WE,#B&#%]3;9>9Z_5XU2L'_&M7=X":_D:;NW@=E@E>:,FSOV +M\@VR$`Z1V:1S=B^I]\+%K'N9Z+8V`QVL4DU-_$,"I".-Y6I%.Z'^F*E,/VOB +MG=G`P4N'5./)%!DT/XIF5EHW'QSF[N\DNWB7P?;>%SSYM0@CX)$\1LN%!BE[ +MA\E8G3"`.A,+F35D!]QHWUR`8B%C]9&M/&9&-\,C8N%?.8+J5F@PP?GIUMZ@ +M!>MZ\;"`)?^G=,KII*Z"JQ22O/!%\NM?JVXG,2LT-*(P?EM'BS1<EA"\I#0E +MAK+J`#]#5U@K?`4I;WV"1JX>N!RC,6%87NCF/^A`JID6OCIW<&*;J9$65*B. +ML4_#3Y<::?VAV0]L0V%HEG9OT2+Y/-.`L&X1W&GM3/13>@>0#W_BS7\9@)>T +M%[_4<$$T`\+&$PNW./TY+NP\2$_<]3_UFQ79(T&6@W0FIPQ2"><>Z!7,P!L/ +M%RH"-+]-A#SK>7*)6;M!*C\V^R2'[FD+8S!?O&++OZ(6Y@A,/RN(W?)!E.4V +M?1/-6D5(.U;B'<S<H=%L-A%L`=-?2]3V-T;1M1HE2'#F46="FQ#%YW/Z5\$# +MQ4H]'XUBKU4:(G,"*J-C+2K6=#$0EZ&J/F2T<"S=&_+\T@SWK]8+ALR.,(4K +M9D=H.&8*@T8M!>RKWRU0O-E(Z3>T^"Q_PP8!QYC>!%_IZR*4JLG&V,?%C0]L +MH@2>1E!M52.&_"B6AJA5W=I'[<$8EJ0"WX1S7QZ@<<)`VK^'Y1XTG'UG#3L$ +M$(?EQ\`.EY`"-+/Y2FPD4$7H+4!M#HNX??=J*PU\K[MGG36N5=$&LWN`AZRK +M?:$*,1%+JZF<:$E;W*IQ@;1T9PU->*!4>+GI7F.3B(%SRDS$`C6[@I!/'X<R +MZ%F55#U#,Q(4U\!BNT5TX<*PO7G^:Z6QK:NB:D`8!KHJ;1/S!QN80FF_81\U +M!V2`:Q8RD4IP6\STW4I45Y.[C9C95+K*A@[SO>C#J@!2>C40]<;NV!/'&#T' +MTK":<`TNH6I6!L(S6$"=J[XHW'MQRYV.RGA(8!>%WSE]O/L7RA$P%F1@^MED +M)5=Q<B;[2H`R"4]O=O1E\O1MGG5H.-_];8.B-FHXXNY+KE#L`GRO4FNX@,R] +M@U&>+0VO1#,)2O%*',]+P?ID-S==QQ%EJ(33/'`JF'D>@_OSML7H*U$_`1/A +ML;-`("YK9V"R^:^(?9`#44@JG*_?M/^H(N&!*.]:;3FPIZ,VRN?3)WPK?Y1# +M$LQT0-@EYV.>#HJQ8?:+Z5+,P#<OEH!X][_.(2_7O?E7I"9]2RC\+@19G-QW +MDLWB,!X[=`C=KC;"1EM"(4<G?>9`DCF+&EP;!1@E(C7I#I)4L</>%'29P%JN +M%;.LON/'K8&)F:GN0,&S#M6@@^7[>ZK88`J2?Y13']\7*:8!T:WB<R7^<4;X +MK7@M`(@!&5HJ`9[93O/83%)\:/-#:]][3&?O;9*/2#K]%*%HJ8+<'UA6M$__ +M<'&$PF*IN)X26RO7H-D>K\2J$L*UR6]-X($-%=/:[O5_SN`.9;":WGC"!)6? +MM;21R\ID_"9FJDPP88AG*T/WT"FYW)@['%`@%:$JDF!G0ZJ%@QBRO5@>P?2U +MK'7?J2#-P0!2!.SM<8(E#&A5R>=3"MS3@7V!&9)%8H0AL"HJY<QK<GQ/`-,V +M'C#-VY7)(FIYX:3^G]Y:E]OY-/H,XUH^P]UXF60SGW]_T!GFV?76PSJ4F(:C +MC<*$N^L,08"U4TWH.FT#,G8);`&;A<1EL?3JMH=YJO2.E\1-9SY6=/%OC^/G +MNU/L\D<08$H?"[QF.+*/=M:(+:)]*K?*(`>O\+MZ/OI^ZI0+O?2[R2?PKR$_ +M']+H0>-Z@.RT$CY94`!H>.XJ`[W(/';5CBK?IN9*XI:8`\#H<B/PP$*V/G[[ +M)9!K;KPX?R*I)1^\B2YX':TK%@/@&2/G69TPKM`-Q0YKXSX.1K@NY]>#7-Z- +MP5F>`R_^J.DJ+O+-2$_*:@+G8T:*.5?#$_-(HA@')R)E.9V.Q9E>/E/#<1$] +MO]VFF[U2>^;RB="HPFC30>@!3VONZR;D07ZY_?$GB?\A^FCV;\@'K?(320NS +MT8V4ON%X\4/A^7.FQV5&LF+9V0^%,2?F'0"X*&TWNQ;7]`7_`7O('+V%I2"T +MS0(!;P7CV8/^'B.[A]2J(<TI\'@[H>([FP67W\=BB42+WN9`%TEBW./4-8,D +MOW.!<*Y&%)$#_'T2F<..R((#SR)`2,C'CS@DS$WN`;0,]VM/L`S/I=7?FO@* +M+PBE$HIZ9^>RC4?5O]8\,K^I5'+&<_Y0,;0\8I"!B/W6.H7-<W-PAW)OZ^?( +MD(OL"?R'&($(J2.?V;YEVXWXTT.[RGJ\*LE#B28TBDO?L'YP3Y+MI<XIM5>: +M&C\>NN^^TIH'36T'DK)^Z0Z4\QU;3:,C#FDE(D+-1H-[*O1TZ2%V[L6@4"6A +M8DUFXBL0M`%VWI'36B#>ZJ49Z6C(&9'@+SJ>Y21=UC>:[BQAA=S#P3<TTRTH +MJ&X[QMI6[KK'X!]DN6-XO8I,=V\=0Q&(79H"GSUOG!U1-TOV_1DI&P($E)YJ +M\,..!UYZW/(U7GC6)H9:_.-8[DW$B^;,43)"3)7]F.H0+FZ3HN%ID1I5(5(7 +MU.>^:(/OE!6@%$Y#W0+;+V1Z3"T#J0CV8TC<EQ7'>HJZ5,&?VP\@]T7+53I2 +M%J!/V<9V^\3\)"\D?*6Q/;V>NEY&XABW05@YQ9(8"]V$]8MRC?:,Z7513I/G +M77TU/MPJ5EY/-PX`+KM%0K-%)%[L5M![U;CMW;Y,K#*)FXF&,#R;M7S6,RC4 +M:<(@!#6R[9PI&[)RKX6L1]\HJ1P:K`S8EDR_"`M>K-/_]_W%#$'[@GRMK?._ +MK$D`DBX(-DKVDY5D?"O%HS1T[1D-<?B[TWN7E)P*H'1$&!Y0!N<_\YG$$5FJ +M8)`".\L'X'VI*0^!-LY&2H9A#+OE924%XKF_U/12-R9(*!+T3;ML\S'U(P!; +M]M]QI<1<[)XJ=75S`$0I3$%$?B-$^Y"KUO2R@"Y-R_@)-+<WLV=B_Z+SIS!B +M;I26&@_H(0IG0&1V'D$[_/"H^M=ZW-H+U6:T.$$5\1<NWN[RP.8>OBM6-TX. +M-16?<CG.T]%N.<R1+.6LIHE#GED<<2J+$Z,9I!B!DC/.Q(]6M]]NJT#6UURS +M/&CW6S0<"6*[;!X[7TR:RQ13VNI%`PO["Q+7%S5*%/0$ISMUH28J:1EFW635 +M+64N/?(T6$&N6FE[V\>4;2=T4(`3FU1][\HF#P("O=,<C^3\\DF9*H,X2>9N +M.N,Y]W%2_Z,K[7^(#R<["HE',&3-/T72"-L":EYI>/8=>K@&9B=<U*$G9=P% +MG+B8W/I1:]);;N%`4F]J77C)_4E74DVH\,YD+09@Z\V+DCLWHW78&%"2G"9( +MFF!>1D'J.JK1ZTE)Q*@PM9&$$_\OQ>?FVAH4_A;3G(7OGCFKGQ!MQ[G<392U +M-%N$;V#NWBTB;]2TR08J$)MF?MUBN^V(^$3M:U@CC/^/-[Y\C8CSIGI$D()1 +MX7QKVV$^ME3I6^UP)GO^XTW8V<4ZD3Z_?RF^^\32NRU@-8+E,53JL!_^'\7I +M:_\4,6&`>%-%ILZ!(;+0S+_H:^XID"D@ZEM9J9`?!C1?R)I\W#&1;M[$]#XK +M,HCJBUW9&JM"[O?1,3H\'WY30PQG)\:R^>L;;DD$)VO72PKOYY5U_]Y'Q\HJ +M:;+^?.3L:^W.YW<;G]O4&B%S%9M2;)2%TFF/\8]F'WN]@\]6W^'K*3M'AI<O +M"76*U(C.!2"073KK&:;+P:C`I6VDYZVK2WP-4]17_+V'O?\`B&+]GX9[/7[* +M]!)"F_H9%?2Q9O@5H+F1AYIW'($B'$BA.SYUNZ5C/G\MUT05T)!VK8_&MI_T +MI3E)ZZ:+-&L[_!_MC9N(1`7"X=*4H#-1)%D+D=T-[>3M3096\"=T-13.>)8] +M6>G>1,\L>YTL1O;-9\A'<U?I$,EG\=+OZL&/06@YAG_Z0\P\Q!A12Y!PJ;,E +M/C9?34)]:7V/C@E4F84GR>-)!B6(BF,`UQQ(7I9#K=&H%0_.M0L/%]*U@RR$ +MQ1)00'P^$W2)B09^[!TMA9>.G`FY?72XSVZFP!<$#X\'23@P;]XC$-E,X<.K +M<*25XB1UWRS`[I>7D)I($"D1FP=CE`#"(Y*I42&),!R8;3KM6%CF-:2*</HG +MYA-55P-P]ZDQ2-CU(J'W$77L?3GO1Y(4[3+ZMO#U3@F%BC&D764VC1'<CHC7 +MF79@TZOL'!L>.?!XEMG?Z_B+I/@;CHQRRH3(GG.V*V@,K2E=YC.:M%F)\M/3 +MGC.)[N*UWH'#DHE98K_6Z&84+6ZJ@\!#@0`\:)70U>+D#.$MU%,@<ER:+1.6 +M0!T`8AZB$>P$"8#4G)6O@ML>,.1@,)U.=GU=OM:L]Y.B>ZA[T"\$DC$F6/:6 +M%T?'%W.$OZB$G&Q.Z8:3LK<[6`M0;H-KBY7EXMW*;1("F(DF#BJ7P@!(CU%! +M?9R3NX-#,S0<GH1=6)S!6P'4B6(99`((Z1DWC-SVQ#?=X`%@I7-G+#@-5I"L +MS"`VE!"3N+_F`\:\[J/`B-W$)N,G;8,._W;J=JQ7O2F4E0,AIXOQUL0:/;5N +MXH@$[U-E1W(U"OCN3MI(WQ.ICOY(X8Y)G1UA.Q*]XW'IAV<)=<^AT25`<A;6 +MP7:77.@#CU%+-%B%]04><PAK)P%_%\WQ#"I+VM".<+DQ)1.DD.&U,U:<'U$# +MH^*X)6U9="_%BB%THGDA$G4/YNQ8*GXV,L]_67+V-#2IR3_B.5,&``2Z16EV +M!U9,>%I=X_HKQ6[>QB[T+XX%@8_?W&QEG3WQ-1#9_%+%7>M3FU0FCJ=[*W0^ +M.`I_)`4Z),-IY6F-Q@6Z+!]>^^H_T.%XK8KKWBQW&C!V[,$US'H6;UDL&+`. +M4/1LM/BKF,E4"N!P>_1%X6F(FC\T\;48-\ZE8-LK(@#U$),(X[^GP:%KV=Q. +M6\BE4G0CW'G8QA,R41U]&+4/2J7D?EQ^`Q&>Q.HVYW,[R*X#$V4"?AFY>/.' +M^T`M6<$==!:`0=^+\J;+P9QB83/M;A^15&/64V#N073NMZLU-;F>U\0T2VL4 +MHD[C)<=;-$XPY>&Q8:KZ43:_\JLQ9/K1U&?5E@E`9+PCK",W9%][924PGF@S +M1N;^<*RI[AUB/W58S4>>0[A4++LQ#!I)R!.QR;\K?1[*":8\W-U9S^8",QN& +M6^#J"ZA/;W??]'OY4G',6)LF7D$<O]M`BX*563*6[X-M=N12_%PB&<,#-5?: +ML0^!"]:Q5>L+CD]*UE_HP\;!.(9VB>@QDW6_*Z-M4@LLQ?;1M7DXJM>:$@1J +M&>LKW51"_I^QV.]I,^<=AD63#^86,WM:ZU\FG5>YWE\8?+E?T?%\^Y@4)Y4F +M-Y]RO-AEM.3!?4!51H'WMPM2&9F`;<)C76%H[9M:E@!H&<^*8TC$U,\)99[P +M*W@BV'!N%VT]AIVE,>E;+8"]S>!\FPJ"_ZH/TN=*K<WTRBD^MZ5XP3FYZF:7 +M=T8U`=+:S_4'24;7,3#X?9>D'JYJ.H"70,Q*N/=?E5G_1:L_"^*3E#B?ZZ09 +M5L0"#,S@U'U<'LFFT58NJT@4<)FUD05$8C2%@$-BVJ><H%\6KC25!6$)JIF3 +M'-/+>1WO!7G&.WUEDF`NV1:3GK-$\>^G^WGLQ9Y#=66^G1-\SC_0%C7<?M@6 +M-1QH?=9EN0QGJ(H?GP,F?\J:OQ0Q^."QE<NAJQ^8;'@TH2/S6G0]'X.),YNW +ME?-EXC:ZU6?I,H*1G2'V!"ZZ>!R`X5*K>>'066^$:MB7.^B1`+-;7=1YFZ<5 +M4N`J1'-<[43FDFIF5D1J+*038'?JO[-=@O`APZ-1$NF8Y)P/)%T=?:";&HNK +MX>A<0%/SYJPAF#4`KC)#+[#CJ=58&.R&))'72@NAZCW"A+/$PCJ8_%$+H.1. +MRX7J(^!&Y*G;`L1I>BD_'?J7G^V3+D#E#?G1>(:M`\10>(A;<YLCTDRL.Z#; +M#)KG_$34\G5L66SV4#TE.D/>NKD$&WICT'-Z#ALB6'1%B2@W(W7M5%$OS*F@ +MG\HRKC1"2$/S*[@MGE3!.(^VL</1(_]3$_;V].R=8UX*TD=7,UXM[[;M+(I. +M^5O^N0JCMQ.QC]YBB_]/$E1]9V/'Y>,IYS@U@V`HO_B^)YM$FHHZ_;S>PGQC +M6D@HI'1R<]WFSC_[#P^6@.+I.V**\W#(Z=46N+7'5K`YUCWF2`S5A[6(<4?V +MO_55>+L]Y&-SPS?(YI-X:)>7*9GM[<:][2A::/C),;+ZEG`=)G90P2.G2/R> +MR<7/$,?]='IV9A"F^,Q:;:=A,?=&_OUZQ8CT\&+!QA.C!*'7\@&^O%"*@'ZX +MU2X*P$\56Z2,QM35US_&HR\4^>L=&%Z=D@Q[DT!CU1N_GN)5>^]/^E!P\5S= +M[U0%^XC)#!C2#0)J'O>-<\G[?)E)^*JKT59]V4/Q'QO9?/J;FJB]2[4W-3*` +MCEY!5V4*[T`PYT5HZ`<RF1ZRN$9ZXP^8YAR$AZ$1_/TKE7A41I6F,*7M^/4+ +MBD&^$/&+F($'9C-CO_0B[=_CM_%EP$AX*`"48)*S0"Y@^P2C;<E7HC]V`+F\ +M:=Y=/4TNAD!\!.-`AP:[Y?@<$_H`&/Z[,:2UU`<]4T@1WV#S*/L"[;J="GZB +MC+7@(/L(``-8)*%UORI'X-USZ!/A9;L'-CB&;>7K=R*O*&J)O11CT7=<".^< +MVK)9"QAL/9RP31):L^L1,8229W.-(AW&C.]@^<XN>.7-IJ1=B^^<<M7,`50X +MA&ZSRUZVAM)VJ_90YN[0DZH&!C[O/]!W7R*I;W[R4_BZ#U#$7>_B5&1X-.FU +MQB]2#*ED*=+O1LDWG^9##+[%#109DE&V4B1A6K(!M1@%&AYL=(B:<!$Z'X`P +M>`]WR"AT'Q?JU>O,UCW,^:7&9=U8DS5FP+I.JT9B,1&8ER73>(%\`3/,;X^W +M)1FFX?Z'6]7@MQW_MX;M$"M:5!-EL3!'#$E'^:3=K<H\'ZM.'!DGZ2G'4%LV +M8XR0?RU:4\_+3?.MDEPENW2Y<CKB9AJ9T.Q<$.7ZOYYND%''VM)VD];*1O(@ +MPV]9O?G[TNJ01GS<;(W1$/@&(>YP#F_/$H4?.4W5;1(CF3*?6!K:"BKN$?QF +ME$.(?V^`JFL@:4/U,Y/;).,JEOP7[Q1S_$4L/966I)"^G#&_Y67C&!/B05/% +M%B4W*RYD/O9@A?4V+FQ-G]F^0ID.MX::EXD%]C'Z'1=_6U%+AF^G[HNVT0SA +MR'(ZF<PAK_N\Z._D@\-+,\J;XT="8'[6G[CSKV<B'II\*>_'*66O6LY(,N(R +MKJP$!RR<$N_>EX%!ESJ=!/=EU3UDE+:!%#,WK]@^\V8*(:V&-R,-E$)+^+R/ +MJU#@?(=8WZ9(XF\/JN;,G,UHDKJ8,GHI/(%N.G-(C(WCA*68#V+UYG7*R;W^ +M!<<_ZWU4Z#1U^JBM>V(JU,DHY[=!I9]WX+G(ZVNO#;>-=C*H889EV*I3<4N2 +M?O#'HJW2S0GEMVR_=A<]R'LGS\F+L$.`T3\(O`&7BBS->]I:@O`D"@*B^:!W +M.;>+@_K5HK55T)!%R,#F37WZOM1BS]J-6CLFADG%BB`ND2JT11_E.,*B`[OD +M17L#3"%+I:@IB/PBDL0!3"X"DB6IANH`@5H=O>'U?-#YN*_Q'V7Z!`]I[(IY +M<>%Q<RST#U_<8T^,<Z3L*_OU0*A$R1R^%Y[R\8=>FN7.C:M*"W\Q)*\8=X(C +MM\@@9P\`[.3^-(@_-O@-4]8+8N7%R:H)3&V=S]XA3'W7JQ>G4_W7,25@.Z%I +MJ^71CPV]F/8V8BND25*GBLXD_@O,/0RL8(Z3'G/;0\73B:A7@L^'+Y&[.:N> +M;5SK4MY#U)&<$/H'WYEKONY?8-MLK,(N8JQL;UWI.N?2BI4FQK13S:T^<_@S +M7TP_*4B,X4([=$K"'%KNJ:F'F4=PSUJZUW,O5FC-)`_HA<B%T$SHV17E0I(\ +ML*W]1L\H$-3:?R243\]+\9*P>B0(SIG0#*+!=<[U$/\6:'+2`^CT_$'H6'"/ +M:>&7T5+<&ZWPE]:!;Z8*AHTI7J;(V;+O-KY/MD,BDV0$[H21_(FYYDYZW446 +M'C]],Q1^\^_M^;0:(ZTN[CN!:.)S(X5ZX2-:DX'9>&)V_G(:JRE#6+R82'(] +MFRS>.(G_C[G26"WO#$3&7E2"B<@ZHJK+[(%3/<'Q4GN+M$>X8\`6X_K>RSG& +MJ2]&5)4SY*R.1$K?I>42=B]I0U%#=2X@^66V)GWC$$9\$@%'[EZ\N4H>6C[P +M>P>6H`7Y:3/G(+V&G?D,^QCX0$I?*0/FC#RV12W(_E1AX+-G@QXC>#>QQ]'V +MJB3*RG>?>(46B;O/^@'_WDS$F5U4;6JYI4H='C'OQ'=$9!%WP%*Q0UTOTNWG +MLO52'9&FF$Z]"V/$6?]H7%1IS4`U;Y7Z4=R-?7UZ:R$]$>,)5;X?8[?9CZ\I +M?JAM[U^<4EU(G5$NF51-6H^`^BK6V+:B%Q+A@&:>72$SBO2&E08C`0*&(/S: +M\PCSO[M7>3'#3!&Y1_%)%TQ^$,H]-'&'/)<';O.JE;:`:A,0M&;1J\W$.HJ* +MY/G<-E2W3V^/P?[C1I'I2HK&]2EY)-WYW";]<SVV>OA,:=8O[04$H4Q5_6\G +MN]Z7:<X-1"0ZTX3+,#H&,`:C?\WD2F`;/HIT%A2^#9>8EW@66E1:%ZS,\8/F +MJ4<Y.$P1`XSBO^*G_L5F,6\4R90N=H=7+8;-UXW245'C::]ED3-KHQ4YMZ:U +MTP9]7S6V@,,QPRHY":ANVM!#\T-OC;.`3&J5QQ3[4];,\)A?81B>N-?9^S)9 +M-+S8X.XY,ES!\],37<57WQ60(C<)W!M$V@?.5OZW*4B?@/]I;C1E;W1C60/? +M1\^"-5)K]9J?1(4;W&#V8Y2YCO/M998W1H1?NO+V\._@I!*R"2<@7^YWQC/_ +M_IX+7J\A/;>2_XPU3[CT78OQK#ZL7_(*B\S=_*.'QLA,.>;*ZP(C?'IF3`@K +M;]62@@5B^^0Z1,RMWT6([2H/]&\`*6G:3@</8E")C#Y?I=!NLJ7W!JF,_)+9 +M+?THE5WG*)7%0O!7W;2U!5\^*Q^Z=WJ9ZR?IQN7#S[!)^K(87*KE^;88>**1 +MYR/2K,(#ND%BH1X8WOAU7TNK"11CXJ'U4/$8-ZD<BZ*PWLG']/99MK2#D)F& +M-"I!,W^B28U%,M0AYQ,^0LX3'BK]H1PIX#1M.ZF_"#>DB:B#D^5T!%T#<\1H +MKQ4IK9E6>/YTWIBQ.F)S`05*:\I.W4:&Q6&?Y[2?L=CU&3&1S*VZY*0Z%"?I +MH>]L-CQBX=[OGW($!1>/'ICG:$QD2\73IQOAB!,Z?A_!3!#=,0=*Q?2W`N\; +MJFB?/30^V>F0]>:U&$/=]<7$/*1?\O]O.4,N_8('\ZN;".U:^V[G_]E2Y5F_ +MS_&UH!N?J&X;<`<:M/B-L\&TY@P*PN\B=_J6*T(1B5BJP^S/H_+3LZQ#$;Q+ +M`PK1M'*HSIPH=T##\@#IW9*]IK!L-"3(@9G13$8<J[K%F^3U9@J1NS,72<,' +M$)-FL\Z#%S(9Q_T5`0IG6"^$D)N^O5EAW%DE$;_()U'-8ITQE&]X&ZW2V9$J +M,G\W\)O-7O'5Q'&[HY?$3K2,VV9JD&BT4$3JYK%$S8OAB[EDE%N,-\M0!$Y- +MTEJ>(9`/\E=LCDP:9^7?&&'Y$<"*.QBBFB*]TD2'LL\=ABY";5"Q,/)?";H9 +MA2^8+M<0CE$9\]GOZ#!S_K[_";Z?[`2%E^J/0D_\-A[1$]=*WBG<;K%3$E^R +MNDQCF?2>"!K[0D?_[YNB"O8J5[=Y]L''IX+LC8/V04;"C@I?EU:4?`>#1LGH +MIS$G#+/Z?M$S?+VVP\%Q'?LGN/(7*_ZP3Z^D;L68C""\.-T1_\\*"D%F\:F_ +M3L!6I20'N\,8G&3!"^QHO>1!A]V",?=81Y^5WC%M&5!@8A-9=Y%E"[UH-M&9 +MM`O'&6#2S=58`/]G;`79SFHE\[O&))301RFR%X.8L\%[I#`.<0@J/0'1ZIJ6 +M=LM9>EGN2ANUZNA-4!$6XX*RHSJ&-<-C<&R]@D'AJF@;Z?0\^7-4T.=DN?3_ +MU\KDUF<GYV=$.(\HXRC+#?-;;2KA`=&:0XN;EI$`>%YY/6U!HM(,&7=QF))Y +M4&NMYO04B"W#FT1!O&7OP[;(PQ;`*>V9<V>_Q$ODC_>ND5*VJVJUD[D0E_X? +MYYZW4G!@70M<MX8&O3CQ5`P=Z^:J!^<9)Q7?IKX]U$0UGF&P(JE<\P58XW1$ +M+=;M>`_<?T*A:-N;]ND6='DFBC5^B2O85Q+$!NJ.'SOZ0NHA!,V,\ONKR1A< +M:F^X\Y'KV0!A0K?Z``<MIGGN2,&7C7\@@J@0<I").@''*8#=L0!6MSX0B:JS +M!V-4&!5+)%:TO!ZDYL.N8$@!0&>'==4=;S##UWFR?N'\]8%JJ*2CHP8O?6I/ +M/>Z9$Z"@83A/=T\/N-'\KZ,T,_W93X3P&F2>DSB*K#8.',L&:3S]-OAST0@` +MB]88`)E)P4EM*&$LT&QE#0%G+'%OHT-.K9[O,DQ;K/3D4I'CWT2],3O08&(9 +MB4@Z/]*RQLVO1$0,FHCENO7=E>?:.#TW&)?IKBPF%F[V'8-&!V._J&AZ$+,] +MEV('^=7$*7&]ZLD"O(SPQBS#H^>%HESKLUXBQ-TFRJZP?;<$IA8(T2@4..J1 +MQ2FI8'Z2XO'9Z9&?4(;*1'PM6MCS#6AT31;)H,IW5,+8N(F8\#(KWJ@$$UDN +M-O)3+WR3O=@3!\03+__(*<`JE6I$IV=NB#QXJJQY+SS/175C]7?1@'860#31 +M5"-+^OI[S!*G8\D3?S(V@:['`!F!NJ8`:J5(%;!?5W/L-\F*Y,M`K^!B4I-? +MQ6O\QJT.DEC-$P?>\XTL`3H?+#$#+:*_.<WICA<4L%'!E><5IUW$$?X+(=;U +M0#A&9&@13L2UR+:UG&.%Y3EA/^RE"U]QN2NO9V74X->M^?5BSZ%9V5ZEIGG@ +MZ[GTF/2!%2@+><U$AIW45`["-'_O(`.LX&5!>`;K^LVWZ9!N;!_ELN4I*L0U +MM%;X8_.'^"/VA5T\2[MHT!#JI!*?4E+D/^&$+L"`J#K%V<LBCBC1R@0Q_O&\ +M@U9:&D,2^`T>68/^,5=A7TPP2W*^2&:"T,2LK<CEEH&(++S)(-M9,E=`A43# +MQ`AQUP,8*S+^^2=P6/:A.`-!2"7'G>.+6L8`Q^<*3)23SA$SQ5`'[2;2\ +MQ)#5W<81=85994#`S`)^U1$$5/G3W?-XJ2<\W=I!5V4X[UAMOC'\$L$9U1/A +MJ>63K7!&^H:[DI^L<GP(5Y>&`Q@#T_)W,!<4N-GJ(R#/0DL;SH($EQIZ>5VB +MCV^H?Q"2U)VX48A/^2M4]7&X"HMT9.!&.]RY"U%GKL"2H\"``>^E)T9I2.YE +M)$XYH68MN$"R&W[-<8$\.`M\G,(I8Y-ZTX4]SFU'#*VSLA2K-Y<1CR(K7)QL +M9Y13;53@>V*=6T-0%$1#NJVCQ[$?(A01*/UV'-WDV9D%?G]2Z2EI>53K;A&] +M04VK+@RJ%"BY!*Z)CRT+RR;%2]_M@V=F*B7TK&B+*,DZ(A6G+Z61C39HM3RQ +MAPT:!X/$%A0YK?!6`5L2CR3=VFH17?W>W5?D9NP)UW^*++U43T\PQ!2`^#ZX +M(ZT#ENG;WN[@3")"IZ%@UL[OT_)DG"$R6;QH:YQSJX$TXDC=V!4R_?J9I2LM +M%AJ"3&E/:85FLFO-'SG1I+R[M#1DNW6SVXIMVV0"86BY:MPM'X3"$$DNKE\T +MGOJIMNGOAP2NL\D[JF6.LQ/?3Q:PM1SA+K[E!J;)A"A8,<9FTT/&[EJ46\*= +M;T--JI;>;0&*D@U1$N7YY4(5+X,M.HL[5+SWQI6@OMKOV8!1]DUQG/A.L\*3 +MD9$Q*VZ$9Q[@8P%8'R=5IUEKFZC+N3+NQE\^\!0=^YHF];L^%<6J^*QQL-Z- +M!&Q$[5YFJ":9$1]3;M;Z!?(H]>7EL*_EQ@/5`\X@S^"D%X$##)^M68K.N_8A +M;+FP7%5YL%S*U>CE@.Y)CJFW.P.OWV/T/XF,]>=`6NYL;#9'WC2(:%GN1DX@ +M*!.96Q\V&=#@@95(*"-\_+0IU0'G$D;+%XM)<:W:)2+T;EK8%$\/73^9*9XT +M,97,W+R?6G0N]XQC_R5*;VF2?LIG]P40Y?I/@>0,Q8H]'_J_BX!]/^O<X^=M +MA`>')B$*C+[_[DS^"'&@3/(\TN:.-DS3'_L3N)76.,4M73XB#AXC;?9Z5S`> +MTCU3%9_^4%OG-0^%3'RNS?#MH0.[(7RYC1%"X)/6@*1+`<?B4M>R.J<9,60C +M@*;@?&)*'&^==$:#[_XS]V3^Z4:(Y>ZB$AP&-?-D+']Q7R(=WB44VAKPO_AH +M5GOI0C,9XHI)E1R^::?TT,Z4YEJ2<54UT28(MT08!6E*E'M0%$3L:K0>"RC] +M@+$O*BX")U8<Z6&0F(`[X(N&[T3M"3,`CS#@*\[O!UGVJ"VSZ>;J0E)$P^@I +MI"2^6TVC</M3_#E5K2"#(4T*N-5[NY1=(I.!*A]4A1N0KHA@M#9:F=`U_?@C +M<'13P"'ZJQZS'DE6O4!LQ`)XXO_B'SRP968'X]@R'\C.J72-^R;#TH+(+$3_ +M*]L&\<;L.'@()#E/+MT6*OT:I3$9]APA.M]7CZ-#-'?7JK<2FPE:V&03&P#% +M"^F%WU[L-@*_,0>5+,+6HKP%@#?R4`_"Y5D0>N2S-[BF(J&,E3,92(BD`]K; +M<AR^IH(TF,2TI[S"_DLXK6F5>F@28VUSN&]!;1K-;;0%Q;UNJOR]XTPWW8NF +MF'RS4O0!)8N+$=@BCID>._N7&XY?_%Q?>YI(&\44:K+-[(VFA;B_0_>2GV73 +M</L3SE(S6$SC)NR^2J66D]&02^DB-W&5\%NK4\@KV0'SIRG;6,A4<;]*[669 +ME.!_NI<+*1<TJCQNKR9U3*:.?3<);3'`>WZB*15'R`_RY'Q@+*CDH](*K#PD +M"YQ`^`55XB5$"9"0-.;R])]8,C%<2<5'BV\XJ?]W!_"$['O]J<PDP>MO$;Z^ +MYIO(>AJ-)9V"YF4=_9F';&:?[7FW*`8S,226FG,E'=#O[B8V:;(.+8#FT&2" +MM_'O3P[Y#N+4DH378NW[$&VMQXY%T^GM#C]?<ENU/M3=.=C6U$]RWX$BI$<G +MA(39*$,>F5#[MYH176N`I$4GS@,_]/89/&=VY,/]N"SEG7%.BG$8]ZF`\G"] +M:,!_C*;)\3[Y:TU_SPTJ=ZH#>RARF)<;6)VEI[<5$S5\;L1A,^+Q5FWIDS/D +M)_D82@IB^R2^IQ:IK$*[>9>8?2`W#U]=O1OZL6RU/JSR0B&^)K?BE=HROK1P +M/_1FA/Q#X/WNNI^4=@]A_AYFAM'T,3+GSDJ#*4PE&%RUJ`Y+D,`"1+\12?RW +M9I)3.+9<D>F@I7162,)-.)/G/^R+7J>+P:BJKV]F9BV5L'=DWY$AWM*BK:05 +M#!]CIN*ST3N;S=6=Z0WNHNZO9)`MJ1.!2.IZ^B:3OGCZ;3"60%8VORA[]*M^ +M`J*`%NK29K76TU\J)%9H7?B#CQ#;Z;),-E6O!RBK"YND8'(/P1B>BX[87<SE +MJ[H%+NF_4"*M2GBNTG`NJ9@A#UP,JB>$:!$1$G&"S6F5M>:O=NF=:B^ST)R+ +M$F\XSR@.CW\;&,#=%0'4S(`?'9%P=$=[``I&:M)3Y5RM_;#"<-R_671D\K@H +MFV`0R`U5QR1>6N87ID@__X.@GOP';@I130CGSW?EY;PVD@Y#]*+2<?GW;]R; +M:[Y[UXTAV>"CSOZ*M-U,B9J]LMILM*ZU_BEJ$V)!&P@M:RG\\2A<^32+G-KU +M^TJP7NPD[\/,],N^]T$F/O<"/U4IA^4SPF[[!1N$SK1=*,<U%E0S"NUQL&<E +MWNI0BQTR2MHG9P!Y,N.1AB[&'RN?F'KVC$_PM,-$3O-8KM.U.^#!7`;#&*4X +MY"W):Y(5&`^]+HB08O:G`2W1JTD'B:ET'*&`8)X%('S-P<4#58#7R\_:Z6+J +M#9`G1X(M,T97)SY:[O4VHA3.[P:<_F@D*8*F[RE;LR)C>)9>Z^H'JQH68JQB +M-"+></'H="BR'I?C705'(-]6K#9Z$I>[U@^5K7MZE:KB"*^?'@):83[>.UAF +M6WHM)8[6LH]C"YR#JUAC3/PFO('UKZZ.%_VSD;E3(A(.,\O873O2$)U&4\F` +MJY5_:!$YGHTC@%Q!G-',BP=7E<5P"AJ'.<"W.;52G4-Y]P"3*R-!L`(,X-&3 +MH@-M;N8/&5&:#9M!%MS*-_.^++.`Q+.,D)M^;3T($A>:JEBL_#YSU-K?UX++ +MWMSV!MD8RQ+C]MZE\J]^=KJD7%)#+?A7&]/+N"2N*5ZE(?"@TYS[Z;U'3*SG +MO0'/69J5F/@Q6`45Y3OQT31I6NY+=[\?!Y^P>/U*^W.=>=5B-K5,WARK*<S; +M04+ZSMU5<+ZE]Z[YL?CTF%&_S^,4U2A&<'PWSU^+F&UM!WC)$6Z!Y#K]Y]UX +M#S+1M`)ZX<37YT(0R>TR0G?K%>':<`?^[5[.E:*5)!LC7N&+P=[TIUR=/C%8 +MMR]=3JYG;G):&"VYO<;OFC]G,7:BZC.*@MPTP<TKXT&@+JC52(1!0AU`:PH5 +MFA*.^0@-CI'&V_Q5<B_9*1[Z(#38$C<A'&&:7(Z::"]U_)Q)$5:H_O;V&PNL +M<B\C\@6'6.LDDZ;@")/5+8/GTIP-MH:.O:90&B*(CI%`T,?KQ8B>[<`S&<(7 +ME`5`U(EVCQYLN5WV3[RP0EM(0Y=H9!1=\.-'!!I(.15KJ7_:"VOET6$+L01D +M-F1@R%BS3"-EBY,(#CJ5MD5GC8I$!6#N27R^IN-",/]LYM+!TSAJ(R1CO/@E +M+9]69?PZE#@T&GIZ<^@?])FJ3FK=U.=EI6")#LI8\6Z[>,T]KMY<E@6CW6]< +MD'F?PZ-M&D6F+3Q+E">#GI'E_S=*2L`Z4R.]2K0T852CP?,*F.F^-+;%QZ#> +M/"LG\=I21RS\56"^+-UCZ!=ZZ#*$(XD\W@QB*C/VDD+A#@"]J=3V0HJ;AG=2 +MQFG@Q-J3LV].\"&9/VO7<41Y?*(<"4)6IJ5=9I8$0Q_)M)EC&+*^EOEK*'.4 +M"9^G@3P.V@_^G#>%HCX'*^]QKXY1@")&QN31;H5A=WN<YSC0S/$5&WO,V?-D +MI8)Z7QM1]#3BX.Z-*8T\2DVB/W]CVG7-_"W-QXI0BM`I?@C<JRCD_<^@=]UQ +MGB[:R='0^X"H"@.S.EP5[\-,-"@@<>7],]7%..C/E2749+_H4I\"!:EJ\)4@ +MYJ^AR'9V5J$SYN97;JT132$0\:$"7TJ2&-W1,KNB,[92ZVK-$0.'MK04$?NL +M#]4Y^]I`3;+S/_2@6;A@6_/10B;W[AC@T]FF#`7#>!&+./B<9/$9ZT?/7I(; +MDB$='\UI.M9ZP$)2M_JA8UH@5R3]VL[`N\KW8F"M+I9_J(_[]9[_]3Q?M':% +M##?F3ALN[B&*6UI.A;!!.4^:[-6(A>#V$(-S84?Z#/?'Y38)"1-4P#*>C)7G +M_[ZYY@"#>`-3DA]AL=Y#V4&B2PTZSHFQ,H>'H_'ORG8W0$@M+@Z%IQ&)]^DT +M/;WYK\`M+PY,DOL5,(=C)ZZ(TM"*P@GS=YY7:VV@;7(>^"$BQ#7\6*=B3)?? +M"IC66MUNFS#8A>^^QGH-"</M_"&B>Z8U>W05-,(F()$:O'@A/9;49-!:%>+C +MX?=DN;%/-7E[7^.][HN)HZ$M9[X%GA&M(VG0M0HOX+5SW</"M'H'3E*$)4=_ +MED.?%(`S3I#Y6*+=ATC+S<`](**T4'Q/>N@/H/YO2H*Q1A(O$:`'L%M'_\S0 +M6LM>3Z_[_&N\E\-XB>X-:04F>A;]/I#*@<@-_0))>)OZL>NGN\I1"W",Z5#P +M^HF@;QA13EUG-W2"E+,CXW;E8"C),D(SXDS$M0X^ZT-J)IU3C5<JC04XCW9, +M%+"0;P4R%'6J1`$'*>%D9Y2VSVEY?`PY4L8D(S5\@'F6WT8K^8,'Q?.\31,\ +MD;QU_D1=?V8'$;4#W#MYWY[N,#O9PW"H35$9L;N$8%4ZW,)"J?:7).KPC/_: +M&@:9Z<&:=#>$I/;3"(RMRE%\!QMGP8FOKV%L'F:!2PYE<8K&T"*-^AE2`/YC +MMFZV7(L@S1Z<P&W>\"&S-:_-F!*TD[43O7X^11"?-%760I=_24#A657/7L'@ +M4F(<*S`#MJQ<U[=?]Q@ZXL8'V?^)M:HJ7RWNULZ040"9=F-;F/.8(.0S$B8; +M\A]K)BG]S!I]3\X0R8Q/9?(8=ZBS_`4&3`S;0=\RP$2WF6ZY(ZAMSQ*D6'@# +M\',GI]H#GH7:.T()K^)$/*+=/QIM@Z536XS5#U&L_AI,W6/0_/0FZ7`8<G[. +M@M]T$89A?D)/8('1Q*=:+7FV_>:IA4Y5=.;X&J"0+&%'K0>(A.S^9TP@2SR5 +M9K/#53!="6/='H>929+3^`\ES]S`^:7H]H9*P,(7LIN>/]<':A;<S7;</0LU +M?G`>$]W9TH--B2&)".PN.YF!A&O.UH#A==&*S3NT#\X^[%TU0$7^0AZ4XFI= +MY/80:P?TP2-$HWEEIASQIJ%!_`_"09(KO3KR?8Q"W"^"NF=1-,9_#MIV$O@8 +MJ?CVH59E*#IEI,\6-,E1)X"6I[>EI(F):I'=9SI1EAJ\>H.4Z7H6<4*;!>'G +M(X6T6G_I,KW%Z=)$/#C-U9D?E^R;=*A>'N1)'Y4<B;2(0SV9S`$>9RV+)\EO +M9D"WW80UPE];FRJ75M)MU$Y>@$49(7^.T4^%W1;D%FJJ`TO-CBX:CFBU(I]N +MRXR\Y_F&E1Q5Y3UO/Z+`3=0*_Z9PSXZ#A\X.#3EM9V=.WW1]Y17EXG\89PS6 +M437HJQ(XY"/BKFW-=ONSVX1)$*-WB?,88NTR,;[^7&Z(MD3[E-$T_%MSP:?2 +M8KQA$[UZZ8PIJ%^W>A?%7H)3?=Z:11W<^S2-;:XJ!XJ=VX._ZW#J7=0(/4?_ +MDG8W]UL7H"+,WT</DE2`'-T4^V:U8J+?EDSN7(>-D_OC\]X,+%[#Y<);;5O( +MJ<(Z']&#H3\C_HKQNM4T:_7.R]^B:^9R!?:7*9O@(4F&<B@-?!(1,-)+CN.B +M%5@O*PC)H;>+!$\6;TIC@&+XANCXQ=HJ!Y.=O<+\Z[RA0"'V89=GUBV3!`BN +MH)":X;=3W=U2AX:%4D--JPJ,Q_.EJ`4CGW,;Y`/48\S6[XH(IUQKV>MHYI,_ +MJ6=A_+?(A308\#YJL6^^=L"C,<HE#UCU\/)2.I3<H8[Y<*><-+O00+Q.IH,[ +MJ#,"JQ(R*MZS,H@3'R-DE3&*TQ09N)X)RG/`B=A50M#_JL8+@I>(024MCU30 +M.PU1I_@GR4<+Z2\AC+=&VF:<@T;Z>:HJWARU&G5/R0R-Z)C_NBZI7\%M-O() +MB@#;P]4WH%?BUQ37-F-7FK9<Q7<078]&RX7,5!#A@(`B#/V!G?#)K\Z?V\/% +MKJI/(3.`1202;+?#<LYRN'.:$L?@'XUZ_F7Z7TU3_M,SW6P]*A&85,4!(78& +MR:!<X^@[`=.[^LYY@?@&8I)U#4Q+-#+2:5"A!8F4'C$\8'0?FR5`SG&1I`OZ +M?=+_>,-DQ)*&4_3P"J=8>%Y(CCV?G())\]JSK7Z0CI*2-_J-MQ4]N8F>I)_, +M4[0WD7@9VG`$^W\SJE@P_/^.[+@:P0]GR+'@E0AO2N"W"IEONH"W,WR-RBI= +MPH=T"*;7`=*O]%3ZNG`$ID&,`[=#F7//_#.CYC\KBRS?/&Y3<^`&583IA`0; +MWSMY!,:%H<KG7_A_!EO"ST"Z?MU!KR?Q,L/+LX"2)].U&;:&;!='I>\QF8!H +MY3M(+2,RV5_)<K[GP/TG;5X[DB]V4+'[><A$"#+B5%D>N5Q=7I=9B]#CL@\, +M[FE1+>$$4GV^"'$WESCG#TM<./[=@=D$Z)*HWLC9I3$2!EY0V4X*#/=<P7M] +M8XP,$96WI-SFR>MCCY?0L:)P_Z!T6/N+JU6JO2/;5,4.L\J_4?3,+_*[[6N9 +M/3&_#EGBQS2([<G%5&Z^_SMV$$P1<WGSZM590_#<VGNI2`*@]D;VH]UN:]5F +MD/NAI-/@NQH/H7<*MA/A<Y)Y-P,VE?X]V09"W\A(^%59KIO/<?1V/*:7[%`' +M>_Z;@.1ZE"1(?JXHC97'8_0YS2U@D:7B!PP4NDK/1?Q0]8AQA8\I#[5>:!$5 +MU$9E1,\RG%15P4LU*![O7\@?Z5"/@$9>T#LO+C>DSI9BWEC>Z),6<O?`YR.T +M0QD<Q<S()`K)YO?QUUFCV=J`X5VWG`VUX5!(CI@(,XHTU3Y(%:/TBY"NI9U@ +M;LT+1\,'4\H0MNN%TJ)=+M*?ZG;!E?C^O-ZI9T!]4"V@!3;,R8.PSEM7H0=. +M3HEP[YYQ2G(_"PK-FK7!O4;8\[=1F[B4X6N0A2U:48ZJ]D^EWWZ"A3UZ&?K< +MZ&^#!T.M7=!0X'RBL]ETL;J;J?<3?^(Q<U^>[-GUUO0QX_`5)<RS3G_N.>E> +M`0>C'%>XWFOM8CO[6_P?Y1I9D*JVY-&DYS[B#;@%E'T*[-"?N1[S@]47.@I/ +ML["*XYYNTUO1!UZ6?,MX!MIOR53]-)&8KS6`WM]Y*R#D]M^#+C&@=U:^E)/K +M8LUB%66)-5WCQQ10VD2\::\=0PTBW@/XYE!F&O`&JG?IM''+)L5O@P`6$@N1 +MVW<%<V[_XI`\^!OU<$=12U2'I-?*Q'-*9:_J.(EK37NA>G<[=T!=Q]?T\=?# +MR;[W!9>K``@=Z>'R)UPO2'Z:I:%D"Z@A\L`,^DB`$4D".+98^2C6)E\XF#3K +M-R<&KJ0**C0@L:[K5L#.-IB&'Z74*>LIF9;*AJI3$YEJKIN+I*\"^\G'&:/^ +M$'U]8Z4%'$<($\SR^7@R+<O<N_U2R.NN[3F_%?[@\'269;/[2)6S'\IW57E, +M[3149@S^?=E5YRR-J@F*@G6$TG(;3T$T&'S&*\RK<UF;QXEYN68I<_:JIYI+ +MZY2TAN%*FJ2S"8MF4F#;O"N\2<2K6:`KX56DV/B9()PFM3J_A+X(:['&E"`A +M-+F'/A7JM^.8+[[0D$ETVB$323V7[I#U*J++(1`?W-5\(,R,Y&DLMJQZC)QA +ML-U@Z7ZW;%@70DM''_.5YD`XW4:6+<^+[API\8TJS(-Z^U-SJ'(R"3]8_9SQ +M;(/N/49Y4BLP1>:!#\I:9J"%"D8'E5$%O>A8&U<OSO,;1)(=U*^\=MM8VJU9 +M,=@STW?<_$*0?1[QU(WC5,>]JT.H-3V?LN+"Z,#O)B7)T;"]&Z"4@E>W1%;[ +MJ^GMMO$[J08^Z2POBS(O!9>.EZ`\I59#K1`Q(]%2O*A0@Q707)7YG\EUK5N% +MQR!^AY%0E[*&S\SUH5*SCS05]&T_488SL?=5SL:<_[6C4IW*>([,:)S9Y<L9 +MW_;53^/\8[ZP&ZR4Z]!<*G*(>4</VN`VN#<%$RP^*CFDU%0US*.0\U[_"L$` +MY*`JYH,8_9#+?$?Z;_/>#S^KM6HJ"3@WT5R).I9MIC98Y'S7W4F%SWQP=6L\ +MU*.6L;Y2Q=)NC9@:GX$TC\P"(/K*8`,WW:EA3W5D[=4.8`5CQ^UN\YD(C]_U +M[W@%;TX)G^C#C->H/V5@NB;QE4.VFQ,N'Z8+>:DC67_62U/Q#*!%456!HUUZ +M:T-1\LU=I;NGT=1303.FJCNAFO_T?9!([_:(8BM@L,8W0CW^G)_`JLB.C=(N +M_IN#[@`.X<'HZSJ0AM9T>V'XMI7HJW;V\14!4IKFUZ<28GC?3,0Y?6)<E(PP +M=K`KU+Z,4_^`=)^9`3%"!Q;*'%%C@!KXF1R4D^'YB()FPKEOCVV)D>&[;0I0 +ML'[3`A67!=3#</\1>9PL>.$TH_;%ZJ:-I`V3[M"(]@#D@&?8+NFRKTM2<5F' +M_7%"0,KDRC;&%T=ENA$J`;/@;J22Y]TOE].^;QD;YIN@$TTS'C7^DE_7Y8Z5 +MW<MC1TF*K\8H!0=0!.#:`VOR;;ZA;H>6A,*:FEB!DK\AV+O%5IT,6C,QKQ2N +MK"]I5\3[)3%7T7DN1/B3UY[?FI&J*82H01KVU4?I%B2DG=QP<QG_,#\R?%&Y +M7(.6ZG=U*$EPIV>%KH%U6N#A'V#971FR<9E]=.$:U<LH[1&'2ZG\-\,K9(_V +M/6_PY0G$)7(YUN*\4[+YCVS!2&HP`'[$B^2X!V[O#!E."E^Z\M]C!Q)1P+:9 +MCZ/.76"7D,&,"-`Y(Z.U.9<#S9)$.@&TV`9*(M6O.ND8+3VF4!?;.RG6U@[` +M"1%M!3XA[\.6%D_!!3X;T7\D#C@'[R&<'@HX0]R/W5T)TE\9Q!P$T-G9LW*( +ME`$'QZ:-`*107#;LI)6HJIW&I@6FN_X-;XO'!3QFHJL@?B`G6X&GA#UF+B!^ +MXD@L3R!''/O$843N`3V`"6Q].^MNU5N;&;<$.PZAMKP?Y3M*5);2+&FE!_#Y +M#?@_RR2L0UM=(+U;:N3RM9TLC9ND:L<(<`<EAAY=,7_NOWJ12:LA(B=VR6DN +MA#2RY38U"6"]^I(GTQZ3!IK$+W]^PN!I/)YZQ@'N;MBK_$C*@#(G%^,"Q.M6 +M<75CEQ\+IA`%*9WZ1Y!/6T>+6YBC%LRKNN1`UL3<I4L(<YQ^]O1T+ZZC]F3L +M<?SE62G:<X9_YV@^:)IC@(.%P)NWRDOT^N!<GEV'-])M@""]DZ7L./(-44-* +M=;^12%2UOA-VXJP0O4H&667[J4)XMRMM\>U`9-S<G8CB=7^7_+T4XU0UQ8-` +MI2LW%P^H"Z&O6S4Z:Z*>MM],%``+$8%:&$HSM)#.+V9;JI]$SCTW.YNZYC8; +MI;I]5-LM@ET%)Z)K24^1#$ZVFLV'#SYH+94Z)H520BM'^=:L`]/*^;YBTE[X +MVF2$,"3VO`S"J]!K>'0HH^@I;^>2\/^&I,=U`VUEPN>@880;"K\2JIRN96P@ +M/]B!3:&)28QKKGL9^GUPT0(V\]QU/*46O6@B3WH"]S(HO0L0"^$U>&\F![2Q +M.;!GU<<^X:9+VE:R\+""4FD6^:I0(A0:[$6.Y=QVJRO<"F8]<]C1OMX]WC]3 +M4*)J&9#EL$XAY%2>L?[5ZP<O_R+A"A-%QA"817@VN:,=V.X#\J'MWQ1,$S83 +MYQE7L**.Z\+SVWS(')/2\L(_(Z?PRFF,=5UZW1$6$U!ZIZ-<^.6WS/.%VG_9 +MC^),Z;8[YDAF[(2CRN!9^\?!&OG#[:*U.L(N789NV*T"KW*R%=L4ZDR%`<3S +M[[X+3Q=H#F44UF=;P2WO3Z=]C1J`/%EU<=G6+EYUE<\3(Z>KPZ<0`SE!:9;R +MMI`D_K<B/\Q<8CNC.'.GU.I&MVN!97(99VLB4>=B(;H6KX'KO)>HN>LR]>P[ +MF&NG^Y$AW\T,<4_XBC]?;EM.WF+/)HP4C*C9N4ZT%,:"-GX1>TKABKT_-BQD +ML?2S=F9GQE@`_+W%PA6N]*Q;88(::.6/_\E7^J%ZJ8GVDS\YZ3COR$D3L#(( +M#7859WPS;UQI`+WMMOL?3GRJGCH$F=Z0PVBL_%.V0Q+`C)&3&;F)D5D:4R*D +ML6T__?5G/?=8EB*WI"0R]%954QY;6J[:HM!:^(.(/DC*'"7PJ/.]T+/AAL"Q +MA-(!_4M(\UG)KVOI**/U&CTZ#T:FE"US`E)VW;7O:I*J,%75C/]??-(5[7,A +M+CL<NX.DN)N)F"%[V^;WS%82WY?_EGPUG<L7$JK;?)QKQ:M00`6-?"\%$YB$ +M6%B^N=5*`L=TH/`N5XJ_>1J/@X0?Z-A/'XG*,&3QW-[):_F\*Y&SFE9'(5?D +M1X\0Y^-1[(@O#(9C^G1$#7:B<9!H+97#%[^/INQFYR)N;/\C,V9(RH@MTGBN +M'`'8$?8RZ&;K6@$N?@_Q"MDA3$DFKTMH3W>#O;>'1?`*'BR[")C=HG-W<^W6 +MO?"SPL_(B]16*EHX?.S+@M3`:D7`#25A9Q7<V/[$RH%E;\K/!YED3"ONJ\2G +ME,N>G=PH7*I&I\L=M`-"V!J%DQ?.6MFRE^YD]'$0856"/]%ZMOJI4(U)?%%T +M<3;G`B+L*]$:\I&/8R;_1185<";#EXH=!_6N@/SO!:>R@`/Z-T!W.8WM,#,: +M6WR.4C\!65>I;7H<*[G"C07UU7!A7D&;EA+!>X^`-T%K)L2,E>9!`96^:FGX +MR>RVA<3Z9$#5`LJ5;$@`<S+(+6C7O#0I-3E=E**MMT>!#_HJ=.!BU?3T`=<4 +M-0#ZHJ/[(,#KXXP-[2K%%AU'`_%RYQ*CX1.&W,=D<<!;'CB_>S0#RFMUXXC0 +M_4<?ND*DG/K+3C:Q*'\ZOQ="6:5V&:.^P([7V]Z4)YIB*X(O0:SJ^!4J4IS: +MLW-2"\+*G%2Y=U.GBG5'*!(IF%0#5FF?'T')TC5(`/]RVI.<O";L_PUJ]I0L +M["#`S[8H<&<S:(0$1$72O_48C;4M0PFC^T4B_).H.7#T1>APN/[(VW:`+A?] +M[WK3T.W0X1@_KKWB-R5G!I=7#^9AM7T]DS2&=I[A9W[("4PPE?]^KL*8G[\K +MLVI42V33><-*+*_Q:\:5+Q2L<RDA57+.'(QS6>R6+#*3#YF,=1F6@+A#PHH\ +M*V&SDO5+Z2.4!(O;"-V=`C8T3748KQJD109V'OA#_J^C>QRYK@!%^8/@^9[U +M_>M=U7H!^!_3LT0V&VZ@"@&<M!K-V^&FK@]5+Q)^7/*\/:<4N>@:IJK=>YYZ +MO:Z,N*00C95.&5H\_5=YW&;:Y;'-#PUUEF[X1&5*\^$/=NUZ`^`(SMS&M2V, +MPH;A>/82//MF3[#AK=_0%JE\48'.RXV*7TO-5Z`\5(4H1C&UM$M,+KB`NN%R +M[+&%=2:7H,22'^933-(U+]-U>&YH_V[$R>FTURM^1NHBT3IG^?OA9I[LJB3< +MV$I-(Z[87`AZI*HR3!)EN..Z$"^R2S\TO!8X`#>S*56,L[6I%4*/5?$/)KVK +MQ?J2"PU(D3SXQ:%D7NG%II1!Z47FV]DK1?<"9YQ!]#6:S1-U@6+'<C\2UL6G +MV4HGVCZALRM;H$YS_PV4&?[:3I]`9S`GI@@,#)JRZ,,.=<.;;)07N/3Q8[,A +MY4=QZ1>QCB9%7)$5,C,^1::RZKT-R("8F;*2>:1FAG*.LO>.4``>NV]MT1'_ +M4F,;PJP_9)UD;2=]9D7KB_Y%NOO#F!U76$L<W\_MZM?C`$Z1@2D\FL!<O]S$ +MUC^(--U"G6UE13,.#,("A?6Q_,!5;2)Y$?F])9FQ\/DDZN`18Q<H)MF.CB\= +MG5#J8'XEOZ=]E,SGT#KSW4#&MM5:SR$WX7=DY<^!G72!;WPR1A0FMW7=A>JW +M[H7$@S-EP01IZ#8E-`$&",S\QN,$-?_"._RMI-N`65.+A/@S27?A.;7?*#VF +ML@MC?!;1!"TO/!ZNPT'V&$9%#I;I;JSU,RKC`[=!*\QXWWB^FTE@"W/@Z;K/ +M)=OVY-`XZ%MZ2IR%&L>(_VRQEVUW^5TD/Q/")9Q&N)EV[]=M-G"F32/J4.4( +M8@JXW`X_<M6^IS0K5<C@+TA?NRI:[>6&,P*1FZE("C;9*]7'UUFT<1CW]WTX +MDP99PM=`$?K:8IFF/2QO?R-`D$N?V@H1\//6R`*A1,@K5@#V5M!N9X1>G8RS +M);&,.48IF>[GO%1%3$U&HB?&G.&`6*K+6V)3*N_$!I8?7L3?G<:'S<KPQE\. +ME4V8]0)\-N;$,G\(2ZT`D,-D%:E>3TEIKF65F#&4C,@'K):?F].O4B`:TPU\ +M+SYU/(A-%XT_"K4#G^5]W/1;#F)O3J0&HS41T.1X)447`-]G$]*Q:QI`C:2Z +M!"%;GH+WKM*=PC=CQB"S&H9JA.9U*=)I=%M^75##B[\0=21DU[;SENZ:'+ZT +M<NX;U<B6@NZ"4RJ+B1$#XFWW@26'T^PP-O<<EQ^[#7Q<\`7!!;*8!T#1#B_D +M=J'8^$=1W&<EQ+R*XJV,XV4"J@?(4L0R27Y]<$1NAYN6R"KI#5P#%JO;"5/V +M);SI_X$@Y@*+>+8,J9(*=B%)F>+MH:*TH[W\9E0WBA/;HNRR@@4,&]H5=UPD +ME&M/S'>7/]`LQ]&2.4':GQQI*UC$7CJ3/<G^Z--00>'56(6^`TR4<@[O%I=U +MZR=S';SV.'=C[2>`?K<XDC&D<L*!#LF7B/&U"'K3X$%Z)?F+A<5-RYCD/J,I +M+=L)!@EUX*E(3^2>WLOO$9G&L@SQV3(_%P+2(,(0#,J^6Y<H\N+N]))#$+44 +M\KY:O7(0RZ`06MJ*\/$['!UB&0.IU?0QA`6*&7Y9!V8.AY[CA<SSA2>*>XDN +MXWVV,PV>Z=E@X<C+DR&DKC&OCM1$WX&=_BF#YK`C1_\B*GC`=:G:D:^@M_-[ +M^A[BK/G%>[;&$54A"@IP>YNN(<VOM3O:[,$;&X_QK2/Y:2$$F(LW!@-/#M3Z +M0>PN7T;2CRK(HP<5B94UFN5-PQQTN=FY01Z:8RP!17U.9Z5ZEXSC=MTSY4&9 +M.<PG$=[,"#3M8K3@-NMTC,*/-4!O9@:SKTFO>5H`8=QU,)/$-\U0(SC?/W3V +ML@E%:]HMJJ+KNMVM.CS:4GRC6:1S^?;G(RL>]Z*Q2!%WTENK-L@?:/U(6,"N +M(U?[!4U+F<DYW!W9\!LFEE([=$VY`'6EQS%W5TRX=[[\-ZYC(0P(7=N@X_'N +MFZ1GY$H9-EQFHUT<:GADN<'YZ:A]<9^B1>3L2PT#-NF=R4>`=$!P?+[]&IZM +M;<L'T+T=*':LI*:96PF'R,%PN]*G>,F'?;>3.R-J1\V;4(.97#0UHF.>R-9\ +MNN$7XPJ\&P7M9P>=T?[$#!+Z0/FF<TPZ7VV1M1K:3SN(B&43*':?OXF*1'H' +MP84VVM8)\8QZC7(U-&`G=M%9N5FK5EJ\CIS#!NRWSBK`YT^Y*"W$FZ:%J..# +MU94LN&>R1B$'O1^VQ<5\.9#Q&"G;4>CF3_R`6V*K74"^?AS87+;"=>\PTC'9 +MQ"4%VU\!@@`:NX5#PK)[M[+='].O_0]Q/>R$ZIDT3=A+]6#XUI\`WI@/"COY +MKQ+BF[65)+_YSRA5,CAXQGCY/EYY&4$=M#SJJ*U*48?0[9$Z-D0^-KFN<_=S +M2RZTJ^;,2TXM.573/7'ICENV60V&=QC4ON1JR[=/&@B38U\/`BGXW.8KS^]T +M&0J<=_*A%K)=.D#F]P'&8-D*7PZ,I3!3O>69O7,45&"PZHQV"G!&R1OF/Y5( +M]*\']EG>@MB#@)M_$[&_$X]6NLN-W+^HIMTPZ`C$70D0@,"-`;_;1LQ>+>R1 +MO]2KQGK4&,1:J..X[R0N'V\AWPY==7F`/H!R++$ZB(>"N\X$4M_+:IB2ZE>L +MHY:+=M2A5>(EBK@FZ:H:E`24LH"B=%*",0+G<$'-H[_-VQ2+C.BHD3/(7A48 +M"98B<#S>)0:0Q+&EC$($=RS@":Q>]^K.E&<5N2)B>W.>E&">1S/"4M(RTS<9 +MGO)XINFPX+B<[?DE?LW.@-M.G6[5J<^WN-.22?=P[B2YH%,6B)1OZ2DCO3Q" +MS]XXN&@W>/%^_:7H5?+ZR'AA3_60('*(0@6'0>2M^]D\3[YHW27C6)\1[_U< +MN@G_K\KI)`"WH3B$NOYPDJF.?/FUD#TZYZK,,34)-V'<L01TXUE8<D]ZB$<F +MO@B3$"77AFX`T4-S`Q@L@2=N#$+@E]#:+,H-6A*B2EGVR"2_J9=7Z-*;G<"3 +M^[67I%2L](</2M)RC8`,%9S7'0A<<4Z_S<K,?_%X-6*&?^7W<*H_PM"''RKW +M!*F$Q`:,B,2@Q0*2(B=OC:I<EAD(U5GJP50>/Z:IQIA=@@D>"?+_37;[U<[C +M7C@F','FAC('M%KY#-*%1V^1U?.6P-=I8GT*H"8C96798+Y.D<\R+#8>LE>` +MN%]5=XGXQ3,I#6]_O6_L0_]LM'2P4=RUFY"-5H=FHO.@`.NX'9W&)J4OEP2( +M<)*)3#U^-'(HE*7U=24S@^F8V+,"JB5%@(N<<10C.3%QHHE#Q:Q!O%^%9UT? +M8CX\56]"Q6"ZNXM@TJ/%@,;)_JZ[`^56UYA)R.B)U_4B9PX-I%GW.96ZRED' +M#<B>&A+G=G.#+@O'`[G_5]4"[@=BKWX</U6X+/]"3\@_%(MD,A9/7.R4",=4 +M$Q;H#IIZV_E4(@$19@W>:J%^<+G7#3WR8(A^PFP,DR#SI12DO%!:5$`14^C" +M4J*81(E'0FGC=Q=>Q=13H!2-2,I?6F[(M>F_N(]];V9C78N6<X7VM?D@,H>Z +MC4UIKWUT(!DW^%X8:UQ/Q!%J&#!-HQ'5X;#]YNN<)7#6[)`WO<UQ$^K:FT>' +M1)^D9U%6&"80D2O^=$+?&523;>0KQ.GZ:)/ZO6W)X[P*"VH!F`G20ENXF?-^ +M.^I55;?N:<)*AG7(5J.-8=`:`565@3!96\[6>`W74X<\2;C2W<<CTS:EX\"V +MC#7Q3,4^9DP'$C^T!3Z*-+`3/BQL?3+W&4.WEY_!NB]958L!$I6K+&\A%L#9 +M`+VZ(6P)A])BN:D=33->;&A).DZ]X093OY<B9WL1:+<\N7&P?HT!V@(_R0<^ +M(B*97ZG!LZ#*3.;X%:!?F,UGAA)IIS5G*>\-LYZ4@H5=&*<@5%MD58"YM50K +MDMN!I`PC9X#FYNO,H!6]@0'1F[)LB?&0LE]##N?8;%4&J.U:BMPP;+%0^/>X +MXX;R`$F;IM'"MX1$CI'+W4^$"->)9?:XZV\7!P/2YB-MTGX\D+9;B1`/5$@M +MU26R3'"1Y]Y2@`W+[9"UQKL9TW*9)H*4M429R<AY)`;L:&`)ZET?\`C.7FDM +MS"Q8RM[F)'A,O;1_YW:3FJ8#-W]OJY]&-C!KH[&8>93M%U3_,/M(]DZA(B:1 +M(7/9F`UB%<)5BIL@M6EI0;PVM%G@Z)VP1*=Z-29D%/M@0\`4HNHR>=SG]Y(1 +M;FC4#B!RD?XGAGH[&3"62P''F`<!Y8=G<(&SC?=_ZVQPPPH8N_?EY9&+6C7_ +MY"+,52<0M:KG.OY26&@R/?,`%GGR^22(\,HB*R.6;:ME0NNOAXH$!V)=IF0P +M:-.:\W++)(B!^ZVB59K[X\@]@6$Z'.5.?S&K-`5SO4Y'UWI4_,"*3JB*QFCR +M8D'Y1F(;)#)3LDG?_(@`_KF>0;:PV*7,8&!#C(!J;U@:_D<AM/;R5)@NB4+J +MG?03LE))FB"#P*(RA>*]SQ"=9.+Z#MFKC%W[=T1EPX@Y"T*-?G*("M2NP,OL +MNOK4G8OA$^K3^J8JBH1LI8.=R$I?]-IW-:M&:06NX=Q5>M$V2XAIM.`A*C&& +MY#L!E;_U[SC;J04\($P(KQH%QNA=-(!8<?FWU*E80`V&T9-U=.G\KX"=LD') +MD%KG[9R)F($1W;O$I-M')0WUU/,;GT*.H`LL4B!H$IG*'H7-<`1(-87P^S7[ +M[;X8:0)$1WF0P1`>OOO^LNC2=X8HORK'!R8;*A6N+>=]C^`+D!BL:`>U10EQ +M1/J,U7)--$4HE\IG``=Z!=>[\8'P%CJ=IXN9++M1W1>PU7IA9^<9FM?CA[Y@ +MP?&W7Q]W8#1W$]`,)5Z(.3IC[KHKKPQG=92]UH1E4<$1CL&.O65/E-BT+G8B +ML<OEZZB7F_U@F#,C,)Z`TED?BJ#RX`K\RAELB'-Q\J>[AZ+AM2.UY6)8"W.6 +M9-99WD6P)8_Q[U#-U*1QC]1AX;O[BUD#:0K39LLK$HKTB`BT*5RVIO?*&*JZ +M@+_]T[BK-CA];8_?[NB\Y!)64UK5H^IV^:R]^3#]<=Y@A&*=[W7.WYMK#3@2 +M4E2*:9Q:ZNVCJ;?!(?`=C4@-/Q^8HK)$I@U9_(2U!EM"V[OY>3S,Z4C2W$=! +M2B8;@QP9]5XQ=:;E'(X\_%H.J`2D+:A1'LRT`M(56/J?R]MD#[^\WM^.<>G, +MD@L&&^-K/@VHPJHOG:XGHXVIM=5&KIFB#\G0GLR28B3/U]%'6!8./P)"V1YY +MV:_F<9\HVTN+TN/`.7COS0CN"&H`=^W4]EQL'7M>?U$F:5AU8Z0I,$")TO(5 +M]'?T!R571H4,"_8)Y-PQ@=%*:S:^60?_'Q3%6=,?OVS41_5OJ$/]RJ/ZI'05 +M$A'"\V`$@117G>32'WTVD`5><'J4AS[@&E//:14=$1+>37AOY/`DKMC5MT<Q +M'[)N=]3Q_NXDA5*K#U]JNR5`NAA0Z[$R1-QR"?BH\*"'<+]/\J&&]/SF<(N5 +M1_,!#\DQ`KC&SP95%^L7&RL0U+B!LRXM(@T_B1A."]WX:VAK@Z)(!D`J%Z`) +M,<4M0K6D$]!ZX+5H>GIUEO0RTU=%DR8H^A.@42*#0=ICD3/"O?-P8,-<S&\/ +MP#+P>G6UB(LT.1U)0X0I'9&0^`%JTN-Q.;!&!,/;Q'<0B`N;V:$ZUEC<S!>S +MC9>@-LUX)`SY:5,?&]XVE.6E)#\;J:\7^I.RY-JL6<=T`%=AGP]6F!H=A\0[ +MK@10WX#AT8DW\G'<A<*AQMBT-N2"R_D0:=-KC=P>_3-8T"*;:VGEY<`IIE_0 +MX;UFQ-INZY<?&N&^PW'@VYTFG=/LQJ(NSS=-_W2`.F3#M"6,E^K!\`RNSVF4 +M^\7@1W]9UZ_78U,M'?6?F_OG/6?NLG&$S8T%ERL09?^(3X!MBB#',=V;#4/3 +M_#<W*0,LNJ3@'8.VC/6W5C>,1)ST=C/IF'45FN=*^FL`1OF%3=(6)14Z'=:U +MA\4,PP/RKS2-NXQ/"5%K"V@C#AGH;:9>4R5#'B(J\K17),CGPUE4@3^7#*JF +MPX&:OC=HD+AK^C\:7+;RCO4)/0HJ#;9HN+($FY5)GX,=O=3GI7/)_=C>R?#2 +MM!J:50*_L#O^3UX>:FV9(FYMMS*"8M(EK1RZ]O<F`"(4))8RJ,'!IRQ`P14L +M]'W(O\I4IT3QNW7NF<\P#C,F.J.U,BG.^]F.Q3#5HVX3C\?.I&JQ"-A*"O(` +M/@2`/&$K2"^/?ZU,SL=?RCZS,1N7ML]+D7(8C!9^_TF>%'DK3IQL,86YO/5U +M1UT=H<(WO+*1E]O8!E_7`194A<UL=T;$BP$#,_9/+HPKR/0"4D$D6I6GGQ59 +M2Q_MC*LEB,`DJ2&6`/MS-X%VL,F4R)11+>WN#"=HI$TYP[S`U?%$!?D[>(3N +MO^I(.W[S1N[^BM<=YT$<]^`T:*."K]62%L=38OR<)`61(A@M<<LV@%8OYTU% +MA3RP%L>)VL[LL/V-2WNN-X/:'H5UM)9G22>4'TRJ>'/@+?G+=_!)D":7MQO& +M3=*=0LRVU82:\`MFR!CI5,7J:>8-)[R&<('B0=YE=&%YA$=!EOT9=FD280:D +M(JI+3V7`;/R:Z6V['SV#9GE`D*03!0&GP'&+/AVGT?\TZX1KW2M+\+G"T+M^ +MRAABBK#G"J&L=.I\2=/G-MDWUY1YTEF5P78[]HT%FD&<J1B>53ZLJ(L]">!# +M1'<+(HL;:0.B$/3X9S;+=^%,(AUGA[ZN"14(K!9H+&K@*)EV'R4"<BGZ4<X( +MB@LB8S"45M-X$[9;7KT$+S<SZRU$Q&-8G5)8CME9=<Y(D3$)5D/"":9'Y,/V +M*JK4T8D,YML;WSP5W\NP,I8/G4U;L6@-.*'&,8\,QNQKM;FA%8*ZY_$$J<+U +M_N59)[2-X'@BL$=EV#@G2\MS6=O#OAC6.*D]Z'8MP[/50ZL9T[^KIK'=3VV= +M8X\\L^Q3]-S>!-3"O'<5Y#H;6-D0-`!1M)_YXY&E#L_BU\%6)LW)_I9U._8` +M1S9_99F2Y21+(T<;BLL)`9"=XWUI$TIZ,O0C]XC=.^H;K)]4241^6*H&]$N" +M-R!5H/Z4996PYQFSL_&1?B-LF(3M2;OZ[@-2U]_J.IBBA#N[YD1,!N.@TP6U +M':+I35SR$RI_W*1U;EEF6O+78[")RG%"NVNJU'T76KE$B8Z56[ZBT8L?9_=N +MN2@\S]I'TN63.ER*ABGZ!4&FG>!Y=R'CCQ0+L93UX"P\-!^_O6(,,2F=''?( +M>X?@*PW9D5S-JKW(]'>#>UIXS8D.1"1A?Y%L6\JU=8J:VTQO::ZC/;W)9SA) +M^:0)UD__.9Z29!"S9,X>?WQ[S]$?JXWV<ZX]<YW'0.J[T2FJ-J59;@TQ.J05 +M)/L@(5G-XHD@+4)9NU[?/>K6AE;R<?%L'U9\,(-]'43A/,M<X.PN/%;(U27O +M`JYI`2:N*>9Y/O:)"_38\?T,$I,]=G1C6GU:L!"*TR7.:5^LD/LO'"BZ9>87 +MN58#WCXJ(V'MFGP4BY^^_$;WC$7F1VLD8EU.VTQ]]>9.!MAG]Q>Q24WP`,&K +MWRZ2U8-*WKS_*L*%K2:@$*D;68TCF!G*E0^V<4*H4R46F2A56%;NF+D[B,Q^ +M,R#1]1@"(G;@,0-806ZX]J^)P]7T!<@9NT[Y0V:(EU'_B%C&K+F(BKT!>135 +MBG@,2"05AB<XZ":YRHQV,$L.ONE+_H`$QL[ZP\E@[\(N[!(]>2%H."P1C0%@ +M+-P3::TY,4D.DA^,CMA(&;O])%"*"(;FM$KT!`AKX3EQI8T8^\1OL(CF/'"9 +MFRK7'6-150]\K\-U6P'C0U_\=$T*].X_IW*.QZ&2>UQ"8EL59LL5WR"D9VZP +MW.2N?NSM.41&2MFLY_T\2\[EA@6>M-O6M\V\Q2I%S:QO@=XEE#B6$4^*TW_" +MS031OV?T1F5%34^;0*[`!1#.T[]M2N)`+@U+5Q"AW$Y5JE9#LGFG^>OGLLST +M"$H@PGD20-O2VDUSU+6&6/'M3W"_&*%M2F,V`:_R$"Q7XW+&?:KY5W"C2!V# +MR,HKP'"J#H"MO[G7/(5;R%V8^L$F7U^&_]7,2>0?MCPRPXKXNM/_E0RY[O@G +M7PW?>/*Z>PJ2[3S5]FB7?LGOW09/_]L=(3AO:`F6-6)Q^=>,V94,13[3RYL2 +M7$8=.N&Q+%&M#>O5R:B700)KRI;XJ;Y.X2,FS])MJ?.?Q28>\1TG:,26M"A: +MDTU2/V28:Q;YK)>Z[T]/@8L'4&W5KRB+QF%,#6\@IX%Q6]0H]PJE*A4D@.#C +M#_2*B6`Y;FO^'(E28JF[)#4@VM=$R,H]NMT,->>K(0IW<$@XE3&IUQ*M(K%M +MA9F<"RF/LSS&$](D?\T=880Q0J[_NC]':A%I\9>(%L21"D'1+:DM")YJF#8< +M@)(5/]H0BJ]LQ/-?612?GV/[Z]<0UQM<4O2LVQ3T$<DX^H%!XZ28428)V+W? +MN8KP(5`>[<I,2YIS%G$\Z0AX=\._4<<-R$1?KM33#=(%\[A;'DH^9=+/Y)&B +M4E.X)H2H63-K_+SX7ZTVK"YD\8FF4U&OHR'$8U(OY$,CMK0\P66PIH>,U:'0 +M9!GP(4S:158Q*2[4X'?@=;09)U=/ZGCB$MTG[MS29[\@LR)1YI]`&$K*$O-_ +M*Y!U&.EQ)!6O1.P2:BORK`KI;N`6"#_SKJLUK9F][?%Y<*/"$[&%^T^9B^4D +M:,.F!7OT>A5\%__$;EAT]V/\X(@E-YN?OX^8S0F0^,EVE(F8`1,7]D7.8M., +M=YY$6GL=-0$TKJ["U;J^6?JHTM3;+3A?;0)5T![-CPM=KK-W.@S>#=C#BMM@ +M5]B_=E_[K*9]C!1.:=1$W!<M>#VV_B!J!W;'\.:"$>^#WSK$F(3"2<SZ$NWU +MFFB5_`U4W:&4AP_GV;BVWNQ\1B:_=-_P-7-Q)!7HA7%Y9].UKY(0CA]\)"R* +M:74,V#T0)T)_A1$&[]B-X.&/`W+]>A$4P`M7`_P:.PYP8%7QJZ#Y7.QDN?@? +M]`G[WBX[C\"3S^T^+[]W4?FQV:2GNI1^3./NH('D,JVV@\@D/F$Y_M;)EJL3 +MN,YU`I?X%E*_TNI]YN&V#GUV>\:!WZ<MKXUQK%>?#RGI?"8,ULM?0@ZRH`9$ +M?=H1"BY9%7!R1>#T:)J*=_6J@.4R^QMB^&`IV8NMW6>T\YY._(;GT^CA@T"C +M%?\6D#M@IBCW]W0V'H]7CEEI$8`A#([AB;)E`ZPD1]];SJ6K5*(*AS]2`WEJ +M'N,!O*'02[/LU!CO>;@649`7P/<1HI"(N&9Z+>-]J="+(OP^HX+3O.W#*)WY +M0$NEC0]P*[G94_B^OER?#<.U=C(D6A?]5TA3;&7Z/K^X`/@1"<P!)%S$"`," +MWN&(5@WKF?6<3(;D[S<K%#5=2B*T\>C&W(BZM3`.S[D/Z#%J7N)V7I5Q;;Y. +MHEAD#53@89J$9YZ"6,M9B^:-B_IATHOHYQE283Z(4H*_QY'!.Y-G@QR;6;>D +M>+PQ<VI;T[>U0E''O'?CQU!GP9/JM?TM183#?TM+BJ<7T'8UQ`>(/9%",]Z3 +M=.YWQ`5MA=-%AMM:91ZKOR)+)H3S4E-(H[0&ZJ:B)&0HHUZ9PRPU=DCI\[D= +M*0U1M0[F@3CW/7<MA_>X8`VY9Z_61L0NK)T[`J"3W$(,=F$^V!B^>WU[QC17 +MM"<[?:LVT;Z?.\O(,%Z>J_)NBM.@R/]%^9U&>+#C9NASW"GU5P]Q-QR2D'.7 +M)9TD+'&[5YQ83;M_??P)))'BIO"H&&(R3436[(=O=[')N_W-@C;L/?@`P`GR +MK_Z/2@VG@_7%?MFY97H'5*I"]$OUW[H+9`7$O<N3\0U;($`0CO(36YQ!YXK( +M>\LU3E0>[$)5CGS]77]PEES'M..*[B]O\9SD[81Y6+AB8'#A5QEVZ\0)F+YC +M<QJ2P#U#F+5QT+QP7E'.9L&Y6\`BRXW#N\85;?[OC!+D79LO+4\MW1;/SG\. +ML0SI>?+3.@"97]1R>T=Q551RL_5:96I7'-T2]?WS04F"#7:/1?WUV,\46]/K +M4=SPWT5/3D:+8KE@`1S2^U6"M\8EU#A<6N?3$=#PJIS=YQ.*>YHG@&)8N3&@ +MIWZF@8WJ+U*%^;^ZSP>@;2JOQW]4OW".!D'!I&]+5UZ?OF0NR===H,K&DRKC +M:1K:42&Y+$*>>%D"GY$5!Y<.C8.3HB7M]L#XKM34XD-R\ZO6XHDLE_%2&R>1 +MQ\!";_N;F,M3^FCUY`J6C73\"X-9YN;XT1V\1+"J@W5E0`?^+VVA1_/A$SE$ +MM?D@F&Z.S7.F2K%Y*JPN^9^LJR/6$F899UF;<K,J]\-(?/Z-"F\K>&:V<>P* +M$7,2^Z;])(&#P*/@+BO&0"YD48_JALJ4]Z74W3>!"DLXFC!QAZY%N9WAE+:X +M&\B?SUFV,4\]8P*\MLE;]$FN%9ZFNNYNSHXD/#78@"6!Q-S:J@%!M^U,7Q], +MD#GO1*$X=FL_;:(4I5BJKX??Y/B#-.>E>FD48W//$]:(WK.B*_JH$@[E&Y]4 +M&?-\?Y3RY0.H`3I?H\%*BAA:Q.=N<?#]/))Q;0("S+QS>"*1%3<)58%ZI-?L +MK/$14<R,+MAYH]<!HHI$JEC86SQ4I7[L6L3G0_7XW0MR&T]%9(6R):43?DYA +M7I027K/M-Z]H!+YO["_WACSS2B3KAQ"EJ%Z)Z0\93B6IMUK>CKE-0C8T&.BY +MC+%Z&U#47^EQZ;:HZ-S7I9+<7@ZH`8D?%]V^E#&49VP`IFS5=#0<<2@2R;>\ +MYA7_AD!]8F7U\A/MQ0^/:S84:B.S&`@,M#+:T8!S1,O+\@B'A1+Q%_@0`?65 +MH.`W1,^?C2'R31>%X'9=@K>TCT&DD_U+!X5DK1K&5@<#N/1=STDF3(*F^5"! +MXWJU]'F5N9%29CP24W(S"%?;U1I]9<%^R08H.Z.JZ'F@@5;RX&B_G`Z=72U' +MI2@6*GPR4K'QDN3^=P_V]X:OE3&14=EJ>:+4>LP.Y+_W7;#-@:C4TL%Q`5PO +MKU=SWP(@#`9AF`U_7K@U/@VQ[`R*$Q;GILGN'PC#=F^AGEW"E++\7F(2W3$& +MX^EVO:O_05K"](SG(IR/#>.+_*G,3I.H@G;H`'?>""BA[^:Y1XF:<^5.*%U0 +MXD,ZA2R4'RAZEM%C$?8FL\2]CY%N)JA'R5<\Q@G4,<",WOU1:"<8]G)^,JWP +MP0YJ<^^Q,3Y2C\4_^9#3";@MEE,$OL[0AA54NF)[I_)<S_JVY93!'_0#P([E +M^W8G)-V2);][AZ5E"\UDYP:6$ZG;SR1SR%;C^^2!@UT*Y>_.__]XX0DH#^`L +M7-DCUO2GYKG*ZS[T3V\NYI[//FQ8WR!4VYM=]HP9R34AKYO@.'6ABGMB,+]7 +M22%)>HB(`97PXW@!X]V!K<J!O!7AT:@E\8*6BL]N_T0X^2$+]SN=N3;1;GB\ +M-:V)-@@,X9'-'C&1PKSRH8SQQZC`O7,S)$`V=<:.B!>>^7S:FRV$.<Y;MT?/ +M/8N3:-F71E$KIQ^A,#S<\3S%?O!8!TEDN?5"T3ZD;5MC*UZDPI6@W!\F!\OE +M(VN[6M]S&,+=1N_+A2ZGT)1"G^_"E9[,AC(C8SQBB$R'<(JGGXCIF+;@7H25 +M>3['GC+S<Z>X>]B+,(4N3DX+'JEL)E!C(]_:_6*E3#?8;>=<*4",<[10W]T7 +M"[9RT<*=9Q/39N-PMT7*SZT.R&EFBFFWH0'`#ZBVL8KR8_[XA]"^CL'H5#2[ +M"3U22LOK[0XUR345G'WWQNHMF5<1*WNMXQ'([(1I%J169:S&_68*E%R).6:[ +MT39P2WZ\A<FBP`!<DBT4U;%!H_.:,8#6V`P*0E2+V<>W\[;/O)%R8[^1:%H+ +MZ+3KBCNEE&NC&H[\G'HZWNOKOAU>J"Z6M^;C&2`)+G&=9MRC!6;9\F=.EK@W +M-M[$B&#TR;0.@:!24'#O:T9WUL+OTJ'XLP2(S\PYQL+V2*>.,BS''+ZU5:$& +MZZ'%58C,>%F("?ADVDW'$?,\`(CXQPW_]YN6`PY"_+=)>W0-.(&Y8.5#O+GB +MO]$K$XTXQ4!>3G[7AL$M86>Q1-3+N%H4R3&>67]\;%\L&NK/;\MVJ\?2?ZLF +M2<DTL3EJO$7F<$Q6[K_BTDMR6FW\I`?.#6"#N:PYX'FL,P,O<6IRFG,7CT7+ +M0CAT99P6W+QC-X_N1Q_1(I8Y;.=U]MR8X1:*E"R]*>%.Z$;Y.@"0PZKGH)8O +M`S,Y74"4T*IW6C^2WT%!>U):#`O>NHX*&HI69/>05?PR3>.B",X2T&UB[:ZZ +MO!E=@.C%)Y$+9^S"_PNY(Q3[(M=EPG<T\3QY"L7-V#42^N<%NOC=%(#%ZXI6 +MY/IV)59E^8-6$@$8:P4&"\IV/P12PL/YE^B1[64/-/8-"W;NR><J!#L(-A>3 +M^GK?=M!>.+$978,%.]#?[$+8K\`VMP(53HH?'19)<P>HP$3\YC!.(R!865=% +M6=;YWH4_]#M[1T!>$37U[VG-NN%8&,#.*1S'`3`4R[AB#OC<D'DN&Q>]J`Y0 +M.XA(,H"3:RG+.NYU`2.X-G^Q!*BB)1JB\=+-?*GQ"<V`W\_!N`WPH&V4VWL6 +MH6(6*&E`V_2?T16,K)W.T,\KH\)/`V/-H`ATM)Q'5)7T?<M.I$VJ0X.$CZKU +ML`7-3)]NQ]]`+(90YWZ*09I=9NZVSA&`"*["`ZER&`10=,E?_%X[D_)F;9=X +M!J+M4+_OT=A'H3"M+2#ZQK'W3IIE)PI)Y7671P&PN5Z,`LL19=D&@W?>@BVJ +MZ^IPDG6BG5)M?[TG%5AQA/X+8"02'&IQC55H-V1W#QG&R,^!<#W'!TOB*4I' +MXP7EM[3!\>PM.VI249'8E;GH;*(T;;"N#_(S$X(Z]G[IK/"_2-N/2)0]08@H +MXZQ"\RJ+]2;OS9;J1V!]MYJ9?5%AQ/TEASI(3UCS,MW(^'MB36C'7W23E#", +M9<N=3F/!)%./DU#,G+/+8I>6R(?)<6N%YN;!BY%L\`9WP@G_.R/$#[]B93</ +MB]?V!3]9$42Q>7DD\4CACXO&IZX43DF/_S4-#9[^M;&MQ,7?S/_GO&9!KE&K +MO:S#5=5.B>8;5,7K.%JH7WT5N-DCG7=%5SE&82Y&FF]MU;BI&?VUWJ*MX!5' +M/E'K[8.7/6[^\1%#B_-KYV_A+CN9.11J=AB3TTXCF>G*;_@RE!!E2#D%S%2" +M7+C%,M7CF]9&*M^Q,XYF*Z>17123!&QDJ'M8J7AL@DI9=7EG\-O\%3RZVGJB +M1B%\VR9G6K[]6HIUMOQL2JIFR.FEI[QX)I0F!)$?](&._UZ"W`SKCH\UJL[M +MO:UARHEM43%LK`C*YQ,RM&(73&,DQR)G$P?V^LN&L7`=,CM+C&M3L=3PL\8C +M]'<JOR8VX%,G1:R:=9TRW]<2%HF>%3Z'0GP<5&-<,ZVEV21F>UUAN=R]+I/] +M"5R01LJG(X*9^>D.*IG!IA5;Y%@`@<`39/,ARYYG=D_"[INE,>2W%XV!3:ZA +M%"YL2$;W2+^R;BNSC"M]O6&,8\E#P8]8*CMKG,:'FP_`@]:FR6B*:TAC$M)Z +MV<@P/K":0@R*[9M=?>R27V[,HG)RP22$;LY5FF@]S2W98DC$UM9Y>X*]FUQV +M\XAS.W\@(B>0B-"-E"^D)<&:TA#%K1NW4D'_10^"T`A_NP7>R8!'B/<8#@M4 +MDPWC248(B_KH40(609&SX.XXP!"9/4%!GPH]%]PJ6M4Y/@1\@<RA:KLW$(_Z +MNI**!M#O/.+2S)+,LE9TPUH[V4^<#H,Y(4>I;`WKBI/@%90/%!KLB"T4(_^< +M#L/=&8)"YEN?B:HQ/39!+S"GR1%7&-@B[#!P_&FM[:#WRH](^M;BG=%T":G1 +M$Y2[_Z]&!_!Q($>XXT%&5Y&ES-JBU=Y+8LRP#=;R<YD1PLJQ_%?B8JV:RECP +M>%<\7L/#8N:1U"CUXE/#$I;<`3*\XW:;Z(>!P/DN4(`MZANMQ<J'<%TKJ!&0 +M$BQL+AM58VO`WQU..(4P+6U&!Y?Y5]RXC*2R9I&O#S7C+L=($X=>1^RMQ#OA +MD_LXF`[_TJ;#<4JSH#]TN$N%"\B1ZR@)^>KL(59>6O%:3XUX$M!FD]SQ,>CI +MK1$.[I9D9!^=]0D-.2^6LE_QD@W7E;\T:=1DAS@/,.%Z!^H`M<:W[E`<=HP[ +M)TP)\9H*M<FJ+>OQ7;F^?CG5J5E;E>[>_8"BI&OBPL)924(DUA;VQM`#8%+R +M_D-6@&_Q*`8]T($'BLMZVG\G^>:,I*(DM!\&-$=N&?BP\A^$F"-W2'SDOY5\ +MKN]^S/:2?BFU\MQ^4B86T$_*HL::JJ2IS46N!2!LQP@T(W].I&XHMC-$H>,9 +MBHRY,2M/@%<33D%4G<X.%HP:_8[_PCXDPKQUFI*F)N,S:WD;E)H-E+V+G`L] +MVCR)LW8#A?0DJ'>+E[[?Z\&)U"@JXFVKY)\4%CF;%!J"!$CIT(+SYRS5M]6) +MKW@*=T;0TT3#Y0!<N;Z,1ZRO\("^&3!RC@7)'R<.3^&PQT%U>U4J<&,'T5K/ +M\O6\4Z>A#RU@W>CD/:Q?%G&O/\\O2GY>MNR4D.G;!D.>QE2%T\*GE8Q:<1VF +M=[&D3,'7!DZH9^ADFEN>6WWYM5E=,OUG'!(+5_BF,MU\;#:7%UY>GA\=IVCI +M>KP=L^4]._@!ES&I7@B_D)AS\;O5LD<$)6$+$<4?807OH\_<_?]V,P\6P$,6 +MNO'C%]!*AIY@DVKY"+A,6_2>(LJ,N'-`B]=@"28B$]>^+UY(BC11`#H9(*5I +M\_ZK=@"EB,6Z62)RSR&.!=K'.%N7(7Y))BIL>'0$<`@7XR&]=Y)5BX5KBAQI +MJ4HYI)B-6\Y6/VTYP[?)@;K1":6#37MOD,F7*"E3RUF[OS(I"3S]),9`=R>4 +MO<Y)<0GS^7UBA58Y</7_EBQ;3!C;FEM9M;>N/"#Q!IFPB>F%F-9'DEQA6HR= +M'CZ%!]$6U\=YSDX+HN/`C&K,J&-[Z7QM5/P-JDU8V-7K5AOW8#"6C27M0!*? +M%O09A`U6$>'<-BTSBO9Z,WPSC:-I)]!CY/C#!(2%WN07OK4]4@.56NNG,^$] +M7\HO*U>7WSC)DK.^QW%J$Y_(-0?ANJY.I^X1?A1B-7CWV-N51+?!U%\9MK)% +M?)F_@+7?(S(]:6^4R\HZ68[)A%_,\1/:FWO7?[,?:GDV5;A7+*9NM822SYZ5 +M2DR/HM.:/55Z.4CL-=^RI0S-&AR,L<IITHI>T44Y-%1,G3,]@,YLL3_[GD;P +MP<K\'2[X8:A_!WW$"C@"V`W\7SN%C=5N&E;R<A866J[YY)9K!8>I+<ES!!=[ +M3O,@U&HO@K/=!O@G^8W56EQ6['60"!B+Q]8G!19%[=#FK!2QKVN.QE6"NN<# +MJUVZVB"6=X4_R'#2%Z.(EK:NX>)U[7KK9E%KV7$6K@YZT0J2Y=-#"X;#[YSC +M<^"KQA439-EX8Y]:)5M9P`'?Q??WESZ73(C%<&+F,1+!XE6U;QN/H)R*["E* +M_P.<O`'@\'S![BAR8J9`"SV0A$J&_3R!S0/.ZA*7]$(=OF-W\]KN8,,PGI%& +M6$AA>,X&&;ZP>[,:'$F`4?9M>1E+X)W>QN?&N3CB@4)B1:"O)\QKC<X<*K<0 +M8/+P$),MWKP&36>:4CWZ1_*YZ>0!=^]Y#&+1*C*5LL?0HN)/*G!AR;,,K))? +MECT`5VX?Q6^<F!Y'LRHO5(R)30*.+`_+0)$AI`S!J-"J!;;Q79&8&&1X9M&S +M7;(X'=D>W%I:0OBP<LCO)Y'$8NR,AORZ_%]TF$`X-5I'06/P^Q)]\R+9[+`* +MM>34##ZNA+EXB?94!G7YC-7"EWUQL01]<A(9Z*]$KN-_J=Y`@^D8>XFM6P,Z +M<&U^\"=C>I$8JJ^_&C:QKT'0`)<YH*(XT@;#>9`4R^9DJ.)H$Y\KXA(0>OU& +MO3W4*`4%+;-VQFY#,U;0AEY=Y8H[)HE6;<E5!)Y!+4"3]$?WIP?TQD#,-+VA +M1*Y&-5<GA5H]9GXM&.\IP89S-2CH>B&B'<:S?(9>NJ_)A^)&K#H<YR(:'"NH +MX890O5$Y*6/<U%.#K!*L;_`?VY>^D"?#EW+Z[-17*E.M5L_<Y13'LO6V[AON +MB(.3';2M'R&3!DF"'%YTY-,T(CJAQ))JX^RH5N:;#V@]78]+E&^C;VB0Z@^` +M7)1.GWC42D,'@0WRJ?PT=NF1O[G(YUH2VII\BH29`YZ9X>L,@$.?2PZ*V+?[ +M*G%I[7">L09_HXH@$^J0==N8(_A<AC*CZ2VN4&5E\L%WZ[_[@J^V?D#:)EW> +M(`L;U@BJ5,&VCM]9"_Z`L8^:FSA*LG2YD:/D5ALX!Q];.KV'$DU/)8FMU85- +MLO`')N1GD9!`Q(`&_QI]3I,G=$-_-G8!Z1O#J?,5L:O9H.BY=CAL,8.CA28' +M%0.@8R>)D/SZB1<O>&41[8R]&8:28)"J9,BXXD1N7T=39G)QZ5Z]>>,!Z.=% +MX@]\2H;,"6U::Z$H1RYLK)@>:Y_8)Z0CD*0Q]FI=VF&;$7/'."UUG&AZP:J\ +M=*?[8>:J6+'?5/0IZ3MA7CQR`(>8LJT@UPYT2E[.0J;D4;^LN48?7J4FR6B, +M&DMCZO'0X/""CSQY5$7"@E=\KXJ*6'XI^=T^FZMXZO_+O"3$F\"=!VI%"5M\ +MZ\L'8KL96B].-9%C8MY^\$DXCH(FB*22M2[7PD7CL%<;S`<]K32CX0T.B'6W +MT>'!%V"P2-HW*S?Z-)>0X7NC-@$?=TT'$4$#&M]T_P?J"8[D=L6XYY1S:@,U +M+ZAWCP^T!@^,8(AN,T)UOKK+:<_'36ZMVM`*WH`BP,DGY"\5.^^YA6XH$2JR +M0[/4N)RH"]Z5U.5L9E0=/J[S;XK4GGSZ8$5`5=,15D.",#V/DLJG9.`-(JNI +M0#VUXN$?N-F4S$7!M!K@>03!\`*01?G&O/+:8=GK,JLTK5].`#,`-AP].9\2 +MJ#'JJ`W##I0(ZG83;8Y+,RU+-4NK=-9B#G:*3OS,B14Q[7&0.&;'"1B?6?ZY +M%"/]NSB^$:0#/D=0=QU"?"Y%G<9>N&BR,[N3?P>*\G!6C'8V+H5H4Y8$F)(2 +M[Y?+)JDC2#R>R5D'E`9K>=E(4IEA"=OR8R(-5B\1'S^L@6??F2LD8D,EC2)R +MY+[`73IW1$32Y0:DN;3R\+34&6':BT;;X2F0,RJ':>ET%/U^&Z?US:EDI-=V +MT4-(SX".)&7I,^F")X@<*.B(;[M\*30B4OE%F6-7>I&!1BUJ^=MO^26DP@CF +MC,LF-Q##66]F-BU[HYTQ8IJG`I6BQ!F07U#G%UK$(H)G\)]L#IZMLK&IJ$S0 +MS&IX0[FT&'ZVV7.ZQR%[_;,GG/"@_E@9TU>GCJ(&ZS01LU_R8+<(.FB^4C%J +M\7=[L>=UA+B7QW%_0:17,KBI\&)1&=A"W<S\2^_;LO\C07>=H<O)?!/0Y2JU +M\H%WR(/',XR#.;+A1@"_30C,P6VV,N.P!0&'+PMUFI_E^__%5`=PHH4$^-EE +MJ%I,IVXI8*D;K%Q.L-9%#]UY&X_P?L_]LU!KNU*XFI=6,4>FDD^IO!"*C;U@ +MC9"6'I64O*^I#XMLK*<()CA#.<Y7G],NB#L)BB59#.PNJYVT=>]IE@%!%)4L +M*P2;C?-AS1J4=.HAF@4*:F>?$8)O:>X#B`'9F1?6R+"J7U8[T`<!"AM>=<H! +MY90T45OO)^[`-0I?Q",<V#M%3$0RVELWKP''WJ]D4307&&*>7D8"YA?[33)Q +MSZ;^(#0HK1*$U\HWH7NHOA='>MYIEYA"+($#?A3EI,D6B@>^0UC5Y16"R,R0 +M[%XG10Y#B"3BW&N:))'WG21D)B>;EF'>E'=,5'$9$(IMYK6,PW1;7='AO<78 +MQ^E73$8#8MK$OU=EL3"[^MZIK-5'OOO.;6/5U[]/@T?#7>&*+CH02OJHKVE> +MTW?\$W`=&W!>:#P@#+=YICOY<@?)/YY14S:\/)'MXRV(F$?.2O>U!NT2&7BU +MBY)&1ERA+G#HJ]05[=S+/;Q@)1B-U@M*DS`MTM-P0C;.CN,EL0,A8QX]I=2$ +MS^J[[E5&\<&$8KY"*'R>(%M!XO&D`,;U<2901(7+FU-TS@.>19;7U$*1XB^Y +M?BT>BT6X`84'^8"*P-UMW8OM.K`V>%81Y6[;U"2'5I&&=YUF60DOA2)Z+9OT +M0S6_!$>1QI1G1EYN/H_$I,AI1<IU3'B'_9BN_JG\/TZ,!*B3G6B#-<]LI1J1 +M1RS"R\A7=P7"_3X+6Q9KZOXO&#\@`:[8$>(!&J$9J9U:P'"?$YE_+`AO&U4F +M($0(X>IXF>E2\"TN)/;/L%>-Z2@#H7V02$_F!`T*I)H_=,B'J/77$R^HL\LQ +M_(\5C29W140W<1Y]UB8,L9R')8`<;^MZ:MBK0]JE$:UGIMOQW&!UE7XO`70M +M$956I&!3ZXWJ+X$JST@^ZZEP9HH#_&;C2!M)C@YVV9<L,_!4KGC33XP+$%?) +MOY,Z.[AQQ591)S`:LHIZ@T8<@V6L*#VW7[\?L#'MB8EO:K=\SBG&9%:]AB9X +MYQ9A='"#,2]"HVZ?49;&,R(L[SQS>TP&>S,S5<N7F-@8X>;J?F_"G,"8W,#0 +M@C)?TR'+(I1%)RYY;VKV>GU3I^J82)H(85GU&GOV^L5`)QY=HZ>U65+D[EJG +M&U#@9%6EPNX'AW\L!..DZ_(!`Q0!O-B,DP*7B$_:<\?&E*\YL)VS<6DX_8L$ +M2O%JUD8:^ET_8%GBS;^+^2X?#I.[_9.8QP0P-FRG%(*5?CKN;H%F_!P%6AL; +M3+%1%)R=]-^!#YL80]FBSZ-$'D/.1/EH'ZVI^S\W<7HH->$`2G^/,;TB-2M/ +M]3.(J8I6=[!JZ+I5`8SKMS3_.^',P'Q(0M#647A]L8R9Y(L0O7=N"JW[0AYJ +M,&0,FDFM;:91[%Z7$!+)!6<"!T'QE81-_-"GD4[+L8ZWKI59;^TS:"SBN&^) +M;&0M'[^Y&)E]7;SH'&+"\\L/L8QS+7(E/`>CEML#:/%K%Q0,,(_#EC;*-5*O +MZA>)W2^G<Y'.MC?!=Y$53/'@'F%F*B-YAK(9Z"@N`T&#JZ8QVOE3]9[FP:G2 +MW;Z&+[(_5<Q\V8C="/51VTP*.],C#+P&3X+5SOR1ZOI8,1+(=[_>?-D#]6#> +MOL:!U>UR=/LZ/'S^-A$9"]C--FA_G@(?\F$FI,&SO<^LI;'>5(,'$C=_:X6@ +MF6\P-D:1`;6H(CX6XB*"HEQDUC[[>$I!5_"_1&Z"/JZU]8%"O(1]R%8C=CT$ +M-.2&0K?3V)9C<C>)\^\O9@'5&'KA+"H2@TJK-%"+)4S2IGM$H__<D%$XQV?\ +M@N>LW9.&EAH3-KZ84U:<OTP+]?TQV3Z`T,9K?^U8V=6T8.O&JB@Q7!<9D,DR +MI6V&^[\*RG-^$.GMB]8S,(C7CW9">6?B9KJ^U8R'FYYGZ7LS/$&CH>,!*T:$ +M6J](@.XJ.4',RJFCA@3:IH]T`#[/L_SI20X$W16VPP=7RV;-V[\K>D%IUH4, +M*R"(LM74AT0V883M=Y4R5G5<>?/!@,9N+\JM[9+SW_ZG^!IOD&+V0=I<IK+B +M6.NVAV-28.S%^;;U$&[^/8LTJ*8?N(B`6"H_>I:.NK;5Z5-UF`43)UG2K.?! +M,=5O<NM>'W]7^Z-)AI1@*PD75FC*03Z4%KB<8A+G)@R1\G@07W-(Z*&/AN6. +MM<"6F5@93`K(U_=B[9],/XL-MGS^W.8(4M]7$A$X":$I-S,W"*]M;CDH<K$` +M9('[W>:2BK@<8OE:0ZEX\^$8],@,$GWGQBW)#%GR*7,)OAW_MT0L,$!>$@+2 +M2OM^H^(NO89:+];N^[>Q!L3I*[?YU=+9)!C"@9*D$1'=115-KFMU$-;!DSVU +MOQ#].K<L[^$[E$7.=Q4B5WO\1]RO$F^?+_^_B(G*"6]!KCC\R>?38\Y"EN51 +M_1=4PE1L,FCP`M>VHS"VM2N^WBR+A;%70O107*N$1C&3=G.3"-[*P37:IRG& +M'B[,#@)0C;"CI:>*C`47-<$18OLVEQP\3NOX0Z3W$\$J6?#Z$+$!:@VMAB_U +MD<Y]H_"QMF&%)@M=L&5"?=%^OI]\">W.2T7AR^O;K.3_A=;A1;N`,G_$Y#1D +MD(&VO8W0+DC_+CY0"1,]A-ZG8)<LVM>&]NE]^[>D5*BV6=<S[<YAD2".U%O( +MA0(,SQVTG.E.([@$Q"&E&2%#+E+S[8=O#,`^SZG)+XO^S@R8?@P]_B3+,#]] +MB;9AG[-I4\".\)3\+U8<8ER!4K%V\4]Y#/M`Y2CRPFM(BL<_>]_CS-B8DBGL +MMW$ER$E"MQ[UK*23IQZ=>&V6*9^*WL+'PC.Q0.L&['(4XUA&<XG2VP`>JNN@ +M._\J>2YLD<]E(5>AT^'##NFM%W3+:Z4&N?4P$(]`F`&$!4?/2@I]8OG(Q5?- +MY:NPZKE!//"\E2[E%3N/X%SSGZ0-OJ6OQ-O;E,9H6#`9C^V58)!L\P9_<OE@ +M8N4&:K&<5"G,":/O2WMA-9%\5?CT5.G>A;'&-V0JVK2[%HW]<A2SYM3#<%?, +MHQT]L853DBBN,UR2!A=,_IXJHO$*2!Z.I[\J+SL<K4X-7&,UC01AS+5#?1WC +M_7]"2TPV]A4$8%5XBD^DCQX_^J!_)J8K_`QX39&<,H55MN\;L>@N/;:)91HU +M$`[O+UMP$S<AFB!CS#I*'IHK4V<%6`",M#`=A-9'IG^Z80YU[,H9A?KT"!B* +M>M`PQ;=(T'[3<D@J,\/QZ.=X".#LX'-]H^BTRH,_H<P?-YFC[:@+]83':!"O +MN]HR5?:O(%85(`1Z"1$:G\MV:S]H("$;-0V^&2A[>J-V\82TQZ".73'AK&<N +MDN\F.(%?*+4#Q%)UQDW&X0P'7T:4O<DQTA/M0MF\[CP;FFG?@<`MYD$!93I. +MWX%F<`0$_PD?%GBRQ,QT@J>C@2M6PC$Z2:-7\7/(_(&]&]4TCC#4CF,"T@XE +MUZ.#IS/=<[$^!ACJ'2Q<ZUE(J",BV#;D'<F.$X#.BZ]+(IBQT;AU\7'.R.7. +M6O<MYP[NYJ'^B3LZ&Y2-WZ8]'Y:2(29KPTB>4Y/"03'L$?V76\5(8*(TD+UZ +M8??NR*$O<5[N)CSH#Q.O-YAC]2,33+\Y*UD>?'67!Y`'_ZG#?X2=TBLY@I== +M6!A&]3GR:$:3_E2&#[2\H\-Z\+5IEWPT@HHW>7&F=XELYQ6Y)H526_@U=,"T +M""A3MZOW;(Q11T^^@RD;M1*$V,\D!_\*]`S$^@6W#?>&O$9P+<*?$T"JLZYL +M7M?Y-J/[A$F,\8`%O:#VK@?TU@2?VZEYVD5HWPYQZ$EN?WD([Z.4LM!\#F22 +M\HW*D]RAH[L!#:LI+@PG:D)W/HI&@A$C3:$B%*#>(L<'_H*'4MQN\TQ@VP;\ +MR?=HLFKU:@+^MA>*)$6V)CCUV9`;*?*?JOHG]ZX0=5U0*ZX]5!$XMSD(]_/? +M:8Q*$3DHP5]76WLC,V7N*Y5H;N$:@LBQJ$H5'8LH#JN,CUT%*=1.&KCVAT,T +M`?=J=B()V`5-F<Z+1Q9/'!4F,-E404NPI=UESD4,;(_VDKO:1)/[B^;Z>_K( +M!O&6NZ.)F;=71TWBPT`B3SWOR->="_7%1R>T+J(;$ME@[`FB^]!%!#"LCK+$ +MJ+!40]B->Q"SO@JQRD$:S9/EBNUF6>+TFP/&%N5XQ2"*M9"?R?'+\,G4N83B +MQHK]?B5?F'@.&\,$@\57V;<8#KND]1_L8KYS@Q<O)K+^CF!,LU-_ASEU:M&/ +M0.)LFQ!:=&O(>ZQMXF5#D-@'ITR2V%RU<,6B@`&2S0HP1Q[QBP6IR6]%4>3$ +M?3(/@"H=K17H5XGD]ZG$`NE-H,CJ>&,*'<G(VE!9[R3.Z&5(#UIZ01<IV8)Y +M=Q7%Y+N_)#E_F.>/:;5V,K#AHM%9I<`)G?U9[_]+KH.Y7]MUR/)MS=,3@JKT +M71'QI:;&:BQB5LE.;C9-N9Y5Y4Y./K6'Z/'7!'Y,^WN*X`)]]%\<JAET.$7, +MWXD#2CPC98]?3<%/=&_X3@'U,:+\W"%3NE-WC$Y[M!#F)SA/=P`TLE"G7Q!R +M"!,\VNFQ/]WTD*GE^W=.5\2N_SIXV@:`15(AW"G^60[5N0:K8,21>_<$T"AQ +MK%(O$=6SAFY;A,WV3U;CFN/_=(=UBVL@RR\5R3C-A.^OIO4"1JGB-D"7>;$E +M'4E6I!2@\$",OKR=O=V603,5,BRTJ'UJ9%:4[>XW&I_-%?JN+(KF`,WZ]&L` +MGORBG(K07WYM,MI`LK[P!:AA0)!H^]XUU6^`X#>]8)659BZ]H:1_B4C*-WM5 +MH%$:%&0YG>J_L:M_0A0CLC[S5DS!'%(\,6V'<9I#5-`Y"XTB<V);QSJM9@G! +M&`2@D8O*>L]`1F2[1ZLX3FQ7Q3^A@XAD*G5;B.NE1C7DPL+G\OF,G,\P8NC0 +M4:ITMSZ5:J?*088_.=RO9I@=[506C;KH7\;66P1&Q8$V`G1QIL!S&G/4V+U( +M^38S^UUK1\%L+510B/I0Z"F`-Y?A3%$^_V/H+Y-"CN#6_AQYS/4)B2PON+N( +M_"PT9J>V1^/9)Y&_X:V^CRCL9KURUB"+99'+82,EL67E&4SQ0YW)CT+%F#BI +MF=FJDD)Y`B\01,S=#@1Z",`-3Z5,LOFNMT':6U%'*D4TBO^GNQZ%L@/MC>?L +M(+B2!O1Z#RUG>^OK0?KL\\]=/G\%IB>VPFJGMS3#K>583`>%*]E&>WR(XPXR +MM'R63F5KYW?B7!HA:OX59O-H#2CW4\,V&:H0\%NVU:&#>A](T0WB!N^;:2;N +M'@,9M'5?/\>@BF,TTN8NJQ][X<UIIKK;%@(=LO4WFZO_Q"O2O]PV+:OMN3V_ +M]H)23."M/*G?^B0O<3N=-TAQHU-)1,4Q#E(9,JR;0(GJ]?"BQV$^G\T'BU:R +MKNDWCQI`;W,*.%I!SUAWVA1MHQRH70]HK\HL@5;TDVI#TRFC8+CBS_[S]_=W +M@2:0S@7WNCLGX<G!YW>E@73EL\=,*9#>ES>22#H?7#W"=\BG4:=J99P/$@"% +M;8Q<[6<5A_U^3A@!@B3VN8Y0('C=V<2W8V[MBF]+Z%)$,7/H89*31)O7P]3N +M#DI\`2=?;FM7VVN,WDGAH6'$24N+C!A;'9_O?OW'UK_]W6ZS(<)3$\O,&:8N +M.82NYMK!8(&8Q'6$;,ZPF+Z0*VOQ\C3JZOFWSY?@0&0)3*9@[_S4$^,R6&;G +M*3>T&YVH@+!&67?&;R![+?>K1],8US0@I"W=Y&I?O?_AR:5;M>VI)P+;<RE& +MK"ILJ.;8FE->MN2B5)XGSYX_7@-A;0>!XP.ID#3`DU!<]/#.-\(^?JS"4LB! +MOO>"-<L!-5F>4S75H<H#H;=G(OIMC4$[IVY>SIK'^.'KLWD<^!JO<")=16A$ +MN5VI#`K+C<(<BB"??P[\#H!KW0;3J_P42"423:(-M925O+\KX=KHG4UH*G9E +M3-_[4"5*F(@0UJ`I$T`X`_`U&NU6U.XC,7B"2QEF>VZULV%3"AHE.J.':,-I +M7F?&%&FX&\6;HPY&)/#!FA?CL1(Z(XQNJ8DNI3UC5!B?1+Y+5P$9]G>4SUB1 +MC-Z09":%6,^:=EY$J]N*';Y:G3D+CM#BV@FDLM`<2""Z+EAGX&Z^P;[%^^7H +M_G:J8;Y>Z/GT<J<L;IL.N^=3V2#HN9\>UG\I'!Z!V*.G]^U?*.KIG]I^(1AC +M8%LP`2T&^PY*,.>2R,>)8T+_^Y/@4J=R$>P9M:#/JGIGVJ=WF8SW@35;(E#9 +M]QPO'2P2(YH.TJ$'6ZL6NPU59GW"A-.Z(,;P?(J/.AMK*"I7<(O?;@ZR<JMU +MD:-AL1=)^#"V2?=^!"_>Z0]:DXXNS_MJ*<[/T[_'RM7^0!K.6_T=C@:).M=N +M0[_11Q\?AJX06UMUG9G1R]7B$/$5[W-R3L/.L9;L<&F2I,E\H6]@?II^+TUZ +M*N>/W4`1S40.Q\$3WZU5S-E]H-*\B2][F41Z2^R:F40TCU!C!\S142%C-JR7 +MXRXQO^GQ!XI"O1#A:Y@_)Z5I<7U74S@VOQT^PC^:V\X0V^)+_[*9-%87.4V* +M;`.&%G&F?!0"!LS=M^@F.6X$>"^K:'I<$>A('0="$JN3&>`$T);#M.]IZ>NZ +M2()T;75(0H2>H//MUT/YP=0JE%$8?_U4NC`0#G#(-.'=P/T)YWDC%*KWQKO/ +MX]%]:Z!'NIHA6R4#;RA'H@0?I=N#NS#H2\F*U:(+T"*/9BKUQ^J$:2TF>YMY +MK23[1KQBGGC735E7W4D^/R*.P2AL(-6'[%'U.7:ZP^)[Z;,;'7YW&8ZQI +M>&P%*H0NR3YT.(:9?%<IN%)"A!T&;E/31I"+G.4T]_5E7]O%$J!..1N,7JOF +M(KG\/90)O??SK<D9F;--YFG<$6Q1P=@8MM!,_AT;S4`Q<PHU'9./*F?Q^:?H +MJEQWU=&($J+E-1ECN_/.;1$7K6U6_+6]P#;[B/5"56ZOK:S4U\.CMU!A;ED@ +M[HOIN9I@CNS*^M9^7D6XF[+V0IYI).W]F2B?G[2/C5'`#392][6CZ%2$&)"J +MC],:^KV<-8\JHHPGV:8*T+_6@9\)"(C;:GS'`CQ(NBOT7)9B;%Y;NV.GLRT_ +M\RXEF[S$#$$AD,QZ"*>=C&]6I]B+.-<:%;53TVJ@30X73!<_XP91?RLX'@[[ +M*X(7(4"@O5.>Z2[:CTU%^ER.7$#M?TF@G;\D@`"]D`@M(O@A&H,`SDCJ+;LC +M?OA"F=(#E=>`9SFFQF]`B1TW7>.D7H3`5=CWVY8MY%W!*TG!8@HK5'Q],M*T +M2+%.Q3^!Z,7CU--Q]=9"#W"]I)G,$<N"4H*SXE&:L5XLGZV(T8;PQ<WD$SNN +M)>\L1`F,COK!!$U(7-YH9&![(+Q02P,$/P`#`&,`C+`.10````#1*```K7(` +M``0`"P!.15=3`9D'``(`044##@#_I<24>1-K#Y/0:@3A^65G:C)AX+TN0J(6 +M4KNXC%N^/JYY+"KM7"#QGBIT3V[S*PGS`4=BVS_EYW^BNM8]GYU.+?N4`W/Q +M%:YJ/[QW9(^B5AF!SV^AUH)E&!E'G>'1,`2J\*Y_4K9#2BQ`MPR,LRY:<%VC +M7C&]R0U@C)CZ[[V<\^ODK`_`D=I@.3+F(@=O?0JQ=RUCA,B$2``6FJ%BZK]F +MP/@NY*<MS8*N4EA7Y`*[*OR-ZV"NBW1<+P[1I7DJ&&@'Y(+9<:15"=_<=N"Y +M;`J%?T;LBA,GU<(L6DR:?D[_B=WLK,?(+EOL0:`4=-A4^U`S23%HF$)X2<)C +M=.1;].Q4"T<9GO/5"JQY,JQ57YQ\H&_F)]J_II0HU9$$/^1_.4V--[<3B5F$ +MF,3R#+.EV>S(84\RQ3_'+;`GO"`\GI99>D=;,1O!U!<-'[,==4)HT!(M\D8J +MEMO/69F>3O%WIZ.*\:[;31J5"?II?,1@%SC>F(:IU3I`@0V($\NC60@C&)3L +M`7S!T(%I1/_&9UURP_E05=:+&+4I(H7[&N)-PG0J^:.-^]6'<3(?-[I\<@SY +M64<B&.?3`+301V;SV@3M$_N$2-@L\`@9N(']NWV31P-)PV1\=L)T;@I4-\K^ +M>,:.S:N.O.2,0\JZ=A9U)'@4UUQCF?`*)*'[.!R9(O+A<*>T'#4,RHO"G*E! +MJ1%?`P7CZV>2PG[6M%)FI7'5<%693VLQ`4[XW4?9S_X(G9#^_?*K"%(+PD1W +MK13O<XO,TG0M!HU[O7MHM)(+[E',RW,VDF.,*N`!G%&ZLX/NQPS@V)QN5E"^ +M7`EFT/B)P`"3^K=V*)@=.Z03:0T7=8;7O'XPUZ^\%Z8\\C3`^J(G!98@,)1$ +M%I3-,<7+&=BE+.@G$F01?P2<';GQXU3Q-1?3\*OLDK8A<'B2!3?4MT[0Y7Q! +MBGWF]0H^9H3.2$*>V0\NG4VX!0RRK.\*,N_%T7C,L8(X+-O_X54,IY/?(/-8 +MA%4G!#$/TD;H1NK47$QB"?#P0#C)/&Z8$(D?5I_6N%4#I$.2;9,JZQ*>Z.G$ +M[62W9J<:[NXZKYV=RH_6(7:]S)UCM#M5&$R@(?=+V7U'>EF56'7I34GO;@]C +MT)Y]8QP+8$&M.\(P-\>#`=PQ.%_*;IP*@]2?&,I'O4P9/H[26@-L-[^-T'#R +M"='4DTM0\/&\S+,L%+M"B@94N47^$YGX','JC?Y08[]>X^4WGCI7-]E9_7?J +MW)V"DIXYCAQ]Y-;6??RL$7V^A9.#_C%I:CXJLHCZ8#-N^W3%$\^X[KR/<,DT +M=M(,:')U;77R7J3_>=\^"F=FC;%&"`9!16==W']/FO6^1*?40F4O`KE<:0!Y +M5^F5<BUUQ!&\RJKG4TJDS>#HX%339[]6N2.5-([#L06!L9ZV#DB"/G1[4,K- +MM+7&.H$S!(^OB;\"M-B:7R6S.GJCZ+V16]'%RFU[=.7%:DWA#DID"/09<.)V +M##S&SO*)I?@JI+*=-[#`XCL(&7EOD#!`2L/E18V>4T`^MZ$%XC.U\.(4_4M6 +M)S_(O9;JJF0(N]UN'OT9S<-VO,G@(YG3D,(5S(V78J]&B"?_>!40M-QM[5E0 +M]1%8>?JY.9SC"*]DK7K0ST?O0$11F'<_[HRU'/A,%[D_+@O=-$27./:H_]"K +MRH&TWW.5L<5R'J5]^6G;K'P\9V'6AL5)#*-KIJ=_AC_T\NT09;73O7@(P07^ +M#&@L'(E-,1]F;5-\UA3-G\A;UW'E4\L3C.H?5)D@N/\/@:;[,C2Z/L+ML#E' +MZ"DNI.0X%V7"^/8%HLP#CYI.TUO9]*^29-"A40?3IR6X#6CD4B<<GJM1-@GQ +ME@3/35:Q$D*'"7DZ88KW!N1<LB94>V`/)'[Z\[W;%3MYKZ)S;SJXNMK:(YP. +MXHL$Z18DIAHL/$R_;6$0`[O,J&<R;LS6H/.#.Y;NKDBEC8C!%@ZNTT"H]--Y +MQ6NV&G"DKLD#_I^Q6_Z;SHAD/%3TZ)$%Z#/!'OM#`K7*^SW,RH0@H&G<B)O3 +M,&?9R[G'RY2HN`6%8M6<_4X9R>,M3Y_%XVJN2Q/CTZ[:^02)81K!8&>Z*W4= +M8W;&CPM8Y"C-OVB>E3.+AZV3Q?@42WBWGS]"VT&/Q$^69203K?>MQ4#(M+3# +M"_#_2H`XZ]&:EA@-9A(ZR*\\&$SU!)7^R1@+@!"2>^Y00T+@3CD]:3YA;,5" +M=Q8KA4(R<-^4'C'A0*\L!N%BR[VXV*:"/'7P]B%RP8K"E`"!<CS[=HX*U8': +MF2AEW%)R&1M183TL="*UVVF8A-K"&8!VQ*[^U12SX9-'"X6-1^KG317RIP6, +MAKU4B^+VR!/90)#O>>9(<"V'XCJ*33WRK%LFT6P8$+M@A@4"_KT&!."/U,*2 +M^'W-P!E?LWL,JZ*S$;Z\D=L7,$8;406IU#DMX#RX^BFKS#NP0J)59>=IC2:+ +ME(8"(>%2$J,28;F]4G6;`;U(C37(Z&^]<C&3N@N9D-QF19H9U5:(`<V8Y@S\ +ME&U@^\:KLJ4MX*X`Q9,Q&(OW\$!PXMH=8WEWY/=O2@^N#]A`6,RD_%)?G.J# +MR;N>R&=MZ/DDW/R`J>.>_F3UE?+GS%&9FIV`WN((IS>R3*CYXD2)VX3=X"OQ +MEF.WD:RK<12<&4&922Z.1UHBC](W#^O0[MJ8"($]^*&5$9,Q#=Z*3L7J@O=` +M#%&VE?\\)@#'4[Z`%([Y7,.&(K%LC"B"'C%GFR/H)8%/R^_7`>E\*&1PN8D5 +MO-OH]1IF)7VA+U:HYO&Y\87_GW7TT^/(T@]0B_\5<9CA=6V[H05=5Q0FC%([ +MY(/;?SVU1N1$Y[[7`VYI_F2!P9WM+=N74;RF4FP'H&R^_44R//BY?22.\N9; +M;Y\,DC&;KHO54,/1GL/O4Z=S10AD0B*$\?D:4/.N=GFI=;11HC,R!3![-!3V +MK\4/\3G59ZOXR?`W.<D!%_]?V*^5!J>[;)66$E>'.WY48BHU<X!7[2G;*A,\ +M#49P<`+-3N(FF>T[L+>U#F]@\YA<AUI@CT^(YY_Y%(%,[;-QZ>T5LGM<(/.D +M)0E=%"[%]DJ$/LN_36KG/_V%@P4]^7GDL5$_KOF5^,-=YEB/[@MB%S-&,Y%/ +MGI)"8ZMXIFBE2+R?SV"906OH7HSJ/"P#KH5@DSF@[MH3B*0C_N<'J'^.<5V" +MNIW"D)F2ROI(+A>\.2??G0=9]^AMP@?\O;;<D](VN[\Y<&?;_R`_KAIU<4MN +M^H<3?]'D.2P$MV8*[_LZ8GT3*@"G"NF(O(C;;:PEM"-"2/;<L-O'!:X`4(D7 +MW.H#0.&;5H&7N+8M:<"N3?HI)G>.7/R>"EMWY/WX-DL+FQ^U+E%L('K`H,I[ +M%O7HJ@O*%\JS&O\'AO+_S_$V/U#;?+80`<O=X:/&V[F](+*#'@4H3@1.'L`^ +M$OSK$?@$HC1R+RFWI[NR#O&Y.]WG(23I(JGAXK8&]UQ/W`/!=X`*709J*=<< +M$@T=H>HII>IC'S+%KH<55<E.CM5G]Y&H0>CRO_,@$_<I-C,,I;[?3Q@VFKM- +M@!EB)H[^^#+)HWVG$G%<9MYB?+,JF8M-'(&Y]>+1'>[BF%UDEJ+A5SSSO8!K +M9C%-S@"MC->+RV7=G^&W<:%TG'`RO5>=)'1YX",U[P,C@MD&55?*PH:>D>NU +MNVC*52\9LW^3'FYN+"/_$C[RO'#'0C`T@S<U2Z8B[M*,@`>]U?_FQ#,R=PN3 +M--*Y,[!_5I8=MW>PG/7BN'&SDM(J^8))X`Z:[,B.J$&O`\B_!Z@;Q4IG%AG. +M<^^G[6O?U512?SZ_O?[!Z*W`_>A8*@Q@P+U<<V]($>V[R7,6:/QL)0LP8'6S +M8R/M_`*WZTI<RC,^2C'3\@I.G46G&&,'^4&G!L)4R3ZKOE=A):/GW&`*JX^\ +MA,NK<([>$807D'[[+4DQ__Y'(`GT0&LAH+%NA5BXV!M@;U'P&PL?7DN5,/M/ +M67BR`6_'%DQK\/C"F,/BL\^#,EKVW#%D`"%L'.IB1Q2H.Q?H=?._+IWH;3;U +M@ZI:PT+$SY:UJT^^TZM0C!JEI`]>20XEC3*67%&^(,B>JJ7>CMM$LZ/I;YR4 +M:@YY>7-D523J)<&4,;1_5S]MKF<.`5)/(0-.$&;)[1*X\[RNW6`&.1V,>29$ +M#0[0J_:7=BZ_[,)HD6[<YZK"XEVT3M!XE`ET>H**<1=_<[-8*OMP6-7E2-:O +M#N6.`LRPO,U;$H;YUGDRAPER<)Q/O%L1PZQC.>&EXCGA&'TWZ#\9(-<@"Y+S +M<?E!FD\C,Q^JM<T]:F\73+&H(+%*&6>?F1TKI!`YX?(8G&AAS3&I_39OI3I* +M<Z6,/,_)8%&"4T2O[I?[H1&1M#1P+A9!62RY(F'U.<U(MEPV:SG!0ZP3H'N/ +M39^]T4H=_W&OZTN'MK=4H!(-4O,!D^&4OV1B>13_6=QS(:73MK,!-E?K)-9F +MOUJRQ]T+:`TVA2%!"Z-N<MK!E8KS8T;R,,FJAQ"[@M05Y`JYE*)#FYF+\7'Q +M?9<[*^*:=3)GX9E;[`C+L.>.R8][3QTEWG-(1&8E'W:^<ZSFC\+2A=9NM_8> +MDE);*HB)K8G/'.[4Q;C^@+H<C^GUPV,;SU9H+4+M(YGDDC%2D'3^Y@PX%8(M +M]7?H3H@81QAK6D.?6>]HY$K5^7#V[5PUL*">4W_Q`2,1Y_%#<(Z#VO]G#A]H +M]WP?%%".B''.(EC]*@)2C9L5&T6F%L\US8'6W_]+I"-F>P_-YR'3]LJLC(D^ +MI9FM4X51Y#*4W1SZYS4B*T@JW1,5^0@![L=`DT3N2>NA=1B$Q[QI3>>E&+4M +M@;AV]X6I&P*4JX:\28T0`<N`^J<^02)06\UJ9^K8.I33Q%S\I[K(P<-*1,3R +MMO3W=W7DB_C.\LGZ[#P>Z6PZ$:$^&$P>V'`8DICJO'\*=94XB>/$MO56CT8' +M*%X.F")6DKOM6AVF%LYH[>%-H5EM\>P,9)&=.AV*ZDEJ95(2KR'BF<1.C7`_ +M>X90MZ*&U>Y:GR(;-`2)CAP^),649?[R6\V4Q&E^^*9@HM-H'Q(&A2L'N2\2 +M_)Z],LCXU<@M%P[>/[#_9<.,P4,_6-91F\%[@ZW(\!,/2@_SXB"NJ,5*3/E- +M0+]Z4::2%#("/B")<Y]*&N3-9K=U;-'2%N-^`]X02.4H7^R>,T-1OD_NNN.> +M0`YA[]Z+`7-"GU.H*7C$5SNM]R3ZH,4(BI%Q%'3)_D+>0(75\D5PH&&'"I:4 +MU56WGG`=)6$_5*,_@3*F-K>PCY0UA1JPI>.L["M@]Y"HVFK3?>:NA**2KY-, +M27U+[>>$6?TN^:&TX5\CR#N&)RD*;X8?_*H^5+(Q'FZ<#5FBF5T@)54JO-CB +M0<&S-_%?N>V\;/[9#_7I6UHY?5[=,[M!%W'M9H,F-WCQ,F?180+$IL02=61] +MRD+ALD^CW?VX4B($P1!7.289&B:80X`7KDO:)L1==Q[G!?I*ZR<\1+,%(2TN +MSP[S4<I#,4V5KM/_PD"<2.&G.JA9NN8NK,O9JPY!`*THR&,X0##A]]T5[S30 +M6-%YK?GNB/%@=J:"@2MSPG%EB*>L5S+/)B>'\182G>6/7U99^1;+EG"6`\\7 +M@3:?O.BZ#-,6$:.N66Y^QK+C6@$;[7V=T!@C9YLP(V4U:`CO=C*R>$VR[0Q7 +MHGWWV]0>T=")M0EEB;Z!JY$AY?I=*G3R'4<O]QUE/@`>7)`&$L%E`Q2CDU() +MV:(K+TF[WT=5V<ED4SR'ZWLHD=X@"GX*`B$F2SA*V/`L<\H0;URM`@N*`G<^ +M;GOI&!_X51=];MT2-H?-C))/K`60/193UA14N]A+]91F!ZE@H/?1L[($)KTG +M7M.L&PF4-UT08?VU%E<?/G0,/JZ8=C0<I>\K+,$_>!U'4@)(=&X&;'X\8ZHM +MEIIOM^BK`(G-H)[0D'^*%K**=8*[Y@DLZ=GHK@BVD=FOUH?N)!BD+>?^TVR# +MH#Y)_@'S>N(D&/P)*1&VDV*!.1(F/:=?MEEU>FA]Z&N']]ZM/V_.P^'K^=(U +MU'MC(/RQ=]-A]V"%&S+]$.(2_];]RX36`H>?VHW]D:ECS:,$/K%]?L$*KH)N +M\Q-Z2S;FZD#_GK+.FZW-Z*J-$?>>;.Q=JTWB+#T1TF/P,;X,$G)2"A!24QI& +MVS[]F*\=F4@B)UUZJ>!G85IB'3MZ6T7'GFG*IW(!^I=FY;C,_#'TQP,+J;;U +MS=Z-+\)#=1(_O(CG9M6W)$Z&GYC=.)V#M;=$G@IS)FKH=M*K0E99H/ZY@=A. +MTW5G:$!T/H@KVT^H[F`I,B0YA4WXFG>H<5?V%(`2?[6$7_!P%?WM_6<J.Z,? +M]Z?[ZH;F+H8OW"N9B1]?:OMN&\M]_W[\H]ID,TW3;8,C6-B",+#`[YLFT`^S +M#'8WKJ1ID15ZGJQ:M7:)&GOU92RMJ_<0.FLLGCB^=$E4SOIW2!0F/TI$:%MO +M1*TO`EG#[=,5.DIESU7)NN'*!OZ1>FU87RL&4HA#I^O.K'19]HZV@Y+`T<]) +M9@N#I5?J,90Z57MTS`D^")E.'Z6K;?9N50$RHE7\D!&Y<`]%N*+>VD5?=Y6" +M.%JCN')\DO9.:TB#0_2+HU3Y)XE&0"WD<&?=S=7C2$F,,M(?/Y!3PDC.EL'L +M'L*^KZ<C<<BW8'56LZ_AL%5>/!'-SN@`?;@HP#E@L"\%WV^7*TG[1"=A)7D/ +MFZW/$"5;Z+$B#B$!_\]_!8?$_<#628X9*:_/6J>/M#CK>=1\EL-&G?A2H)>G +M@<$5NUWZ4J*"D@HB>%;,N*=6`=ABGV%:<1G4)T?!X6D,5U2">MK3BIE<D$UR +MGI(U>L7C\"IMIK8$-?%HM`A5+=ZDXAWHGU#\_U1C^;32=&2Q?S/V6>:+DJC\ +MT@0[I%#\)\4]@`[R7I5?,:W/!H;3`6,^M3[XBZSW^>Z2TF>5HX+^<7OLS<;( +M;@5NKN=([VH>L>?=PU//(F?L><AWTZ+[1CAM$JS8KLH8R>:38"#Y87=`?L.[ +M(P6M\I"LFBK%]T(+0LIS2K!F19RP@F1RE7J:ZZ31S7_N6PO!?'1:E<3.KW;B +MX,-))HRVH^7&/]/Q;)`0QY.^W.6REY0JH6[_?!6T:9UGLNR6TD$M!<9HF]FH +MC<`T]'^T^HIDDQ3,M!63N(C%_P2[`)97&^6:7A>:&=LJX2@;$HS&<$O:4T"7 +M&E-!$&^'*]'V^!S!0]UTEM89+%^RP_\FE,P_DHP10X])G#-0]Z$/WPXHK!LN +MKGA3%Y!\6'X";RW2N9R$F6)KDNG)\L_)^Y^&C(@F7I<NT$ZI)3/+2SN?,@5! +MS(Q7S:IEP3MKOK(=DI$3!$#=-D1@`>'8SYD+%SP6B%*NYS(6?;V!&TXZOZ4^ +M6>)`@P#?[,I#UUZTC`L7!Z8HR`3B&1G;LZO98GI=+_HYTG'=)`9_N0(66G&8 +MP&9Y"^XE)N(,Q&.XB>6CZQ%845XPA_ZYT4B%OWB/0)HT.\[G3?Y(1(PFEPGC +M<^#M]@OC`AYK]RO7"ZC/[*_;1CWU'00:>Y@;5ALY[O%.]CWNE_9.,AHF2WJ, +MQO?R5?_?=\^]/7K&D?REU.+EW.VHFDHW.H&E_,DVX2834$2M,Z8@BC]N_(=, +M*T9`/F12E[88&*][W=MMTCZ62`"C+U1H<D#@H^8CHK>MZK9"N'!3M&Q*HIZ? +MOJYHW3VYH)(3,Y!]]0F`*UC;+TOX^T-"MHC?N;.@%DOW!>NS@N32DTK*=N5N +M(!!\)W(DB-IR@R!LY$,KKW49R@)EX/T$72AJ(S,]N?^&H_=J>FAU.W9QYAG\ +M,A80!=."+M>]1C@@O"!RU1?7K@B\6`3:RL$`E56'CVH+LNN\@`9RLH0YV$/I +M3,Y9F!YE?CWERS]6G=CZPWPT3P]D82U#/S)7*UF[K%D"B6JB7/B.,B/Q9<&Q +M36&DS@8@2PG.?[%N4!'$#IOP##`B0#<88$D>NS@/Q)1`-R/`RI):?$%#B)ZL +M@_W,+>^,P\X3XLA3*O-8,I_4B[VL,Y8QGR&2YB+G]AOI3/2K^0!$@3!W%A8' +M9#@-0L@NJI^231RTR!H\JKH_P-Z!Z!,Q3T=2.;;O@+%3S7HRK*%[MY>?0P`) +M9"5_+"5$/<)#X5`M4<KDRARWY*3*CKD%M,BJ&R^'KJ)4QQML#NQ+/]MV$\_D +MB!W.&()9*H022C$"/^C[KF%OQA")CDCAK$)6&_-85\[5;SIDUC20L[I%`AS, +MQ,_IUSO3=$52D(*5[JSH3H_Y*7QB>2`I`SGT\>R"&,1UI#L?(OJ8C<S,FT6D +MD:`UKK]TYP=5)D:W:;_T;(IG9_1D;X#Z"GHGHF\=GTLB<<D56G=)7V"PNF4/ +M`ZBD[@V(5Y4VU45QBCL?=<UAMR!D9(W-<^OBX,8(H[N.PR0>GD=<5SH827S` +M(SRO!PQ3_V$DS]AU*UP7$8<_F.WV,:;0@1(/K9?.`&S+(T+=NAGJKDY*;=W! +M-(SIY^AM=#M;%`K?*)E>2]@\C00HZ'#&`5"7+\Q-&E-Y5QILN$:4]8HL0-2N +ME/<%VI@61.5["?"4`-HAQPA&/2>!0_FX0CZ/&'7+\(;C4^#Q$X.%"]_4""W& +M9(N2ECFM^FQA:OA(2GS6<R$E[:?^_SCH^0TYJ:G'+R)_H"&(TN;J8CFZ\I[F +M@N$[FM*U9@WJX9E12*7HQ%#O,5OUE^'JO<2Z7U'^SN;G.B.6T"EU*8G!26?_ +MNUX[6OT@2-\E:'OQFM4#`70\)_,8ZQ)B!ZTXG2%(#V#N6@8$B;;+J&M?$O^. +M-Y$<B%11;))K[WE2DU=%,*TU+W*)OJJ!>-SU=AVQB2RD+4RE[%&,T@9\S_G; +M>^&>B7LP<DT%06Z3)4OW5$4-3;V;<7)QS0P3$OL=:7.@9?5MJ8EQQ<QA1;/X +M(UUXLH$:?<D1Y#A_2WY1Y#-2W>2L)?YA:'W&VW?G<%A-JFZX1.O28!!#E='^ +M]"D9QKP1:7H)HTG[TU.%S8!S->'TP^3Y7Z]+NV2\2^!E6A]:JZP;8"]_F$B8 +M^:+Z($$/N!60]EUWP4?XNVHTIWX2<+6+`UVNNH95>3:W]V?X^[HB"=T^&N]+ +M^4;E(>Y0!CU9B(AVB8BVWEXF"++/R<SO1*\W3[LAE4$.(NA#SX.:1R&%/W0Z +M&7.=32P01F#\D;19O[JRA%\G6[;T%B2$M^KXJ9+SOEOR"YX&\/^8;OB"H25, +MJ?6L(N24!*=,%44C*L3.%2:ZA61"*3MJB<:A%L4?NA$-FPDWG9Q'7+*R<.)D +M[<$9RQ+[J54CI_N4P^R9JB)'<FN%AE_\_XNW3:S7ZB)6)S7:#@9VB.+H?=JO +ML/:D"[P*;+RMKC'Z6]S@OG[2&QT`#ENR3$2XMN"/5[HQE%_@07&F=#3MS63W +M,]ILHU+0D@;0[<U?V'RV*YQH[:FI0-1AJ>W00F^<YP1HFD_WVR+D1CNG78#Y +M40L_U59_0&J`^2D?&8),E:K^9J"DX*ZSB*5@4[RE7CK#W']UJE.,AF.!"KF" +M^YM?#D883:P71?O4GI-]CEI>3E6H:%GB4')5IO22*W0^,'ZF/=Y_HYO@E'`_ +MP;ZW+/ZPT/2-8)V17`S)_BS%4MT3L$%(4#GGK[O2,T^S@5S(Q+!TW4'!IXB4 +MCJP&9=!X$E80/L$!ES:^<`GN\8X$61V,X.]4M@EG\%G7K8_R"UJFQ'(%YM1) +M"I6O1OT:=90^!\UG2C@_%%?8_>7)V>]S/0:ZZ0&JC],MK,$-CP6]`1<5VNW1 +MBRRAQ#G0]4.4#/=??VEX)*BM'D#R.),[NH:6KE\J15+W99F&$%VWSAE^(P,' +M0BEN8AR156LHS%1IF`_'91H!,"$F-C9$JCH;H)VC@3-ICAI%.LR&%:E^QGS3 +M6-:&$V15/:IGHAV/*X(2,$L(GP!9"JH60S7:RM;*I=U@6%U.LQ?I:'^CMB>% +MDE7%[_[_>`UM:-2.QW@.7:05;,P0*<ZC>B,R2V<^TW2T62MH[6T1)?Z!JBH9 +MWU6EIS5]/'Z[`3XK+/*BKBG,"5(RH4V@&H93.CMQ)+V7'T)"HE?<28M[P@U/ +MP?NN/6S;P-R\DB%/9B63;*S`H"T=2)&=-R/W:>%E^[8VX+4XM^D^A%MY"1JK +M3Y-^.:L>:1^`Y4M^W9(G[P01!4(K9GD]!<@<MFSZ%JO7>2N4!1J7<J<=S1H# +M9Y_9=Q3:U:9NPWO)XHXI7+I1U1#<C&IR$6Y`'\H%L87B$*B2$^E?>-G&]QZ] +MM[WXT<Y!IGF!,(2O&07I^VCW[L"4=/%*/C'/@7)^_+>Z1_.4<_+6X(RY'Z4Q +MOT-;[@Q[IA=87=T+B1#YP<+Z2U(3TQY'8$]Y7HM2JC&[M2AVV7WZ)8'SD\51 +MU.3,4?E?9FBJ:^#CW\1Y8V$GQQN$$@&5,0]:3]OCPFQ(<0]@N[2>;A6U*Q[3 +M*057V"THU`"&"P2/O]RVM9^9H0C4:S..GJPC29CMQ/#(:[G#SV*2XC$Z:L^L +M%!3/UV;23BVA_Q/QS(]U-)MPHA,]N)YE"#E8%U/'P14_+(X`ERP.(#?'&1;: +MQ57-D\(,P;\C%],4G21V4D%,!H4W]M_96GVD=._6EZ<G,@7KPXN>"Z^#\Q4M +M"A)9880SM:-J?,O%;X;']M:8/JR+PBK9-B66I1U'AU*+G%G)M7]\FR$I_'S/ +M*BYZ3*I$S9W$/@R*H7@YA_$2V&1-J89JM(5+6]B3P,X,"/>HQ1?"`@T,0FH6 +MERRCKWV7@X8"A7_QM*:STU4!W;CT<55?EOJ3X3PI=NRD??4P9U`>FN?\:F8V +MI!@E93_#\D?C[U-#EA%O!>,6B"T<YXH'#?Q8NRHN9>C;6('Y=CK\H]5[TA<? +M,2B2T,70'HY^/P\C+8D7>JHYD&VY@Z[IZ)4[7&FALT+OA2C`)LE-Q?5^1>Y0 +MGE:6N?$Q)+'LG2*Q^52W/\/=-@86FM)Y)<XHB*E2B"&I>)I%G5:Q-/S?Z5)/ +MY/$&4K1,,>4!.A./R22ZW,G2"+[O[`;M$P6BW4#U=:/EXQV#XZQ("/MCW"KM +M%M5!<=?H_H?@>$K5O$(MT$-5*EMMG0*7Q9^(3HU:0__^A/9Q0WI+L`:*Q!:. +M%44Y^ZW/K7M,D@\`MIY4ZM,_9XOZUIBQI3:"C5$B!K'$#C/5<KJPI_U+7V-0 +M9'*8RS8GK'`$N&$+D?NLHVN+.Y$Y-BDW7I^Z"_F%M8N2S2M7JVE@`&F(13C4 +M5N"H^Z5/F)."#%9D*NV4E1XZ!X3EV!U#_NSZQ+GGO&C*R!-C0>7?>1+18(&T +MG+"KCD6!B&A-D]X\MG0`TP*L<+0A`X5G<[[NW!TG\*A'5,03MD'%H@#_%P40 +MV4C_4JPS9&F$DT!;H=6]S2B3BY`DCVK^9&3HXD#5X5T,C\$$C6/K*$,ZL-?Y +MU5/2Q\M1!>J,6T4H=:EM>ZX4[%AC1CHI2-M<V^-S4$#W7T$[8A%#Y]\QVZ-> +M?C]>@?"8$C@PC\0RW.II3PPJ4LN>B`(>(GS-J'BU<B93,>6#E,W:/:=@`T1Q +M!7/_I=8]9*A]TA#X\D80\5CG(5$<16(P(H'!/I+RS4`$H47D+=;@\8)^O*XM +M,817US"_CAZ-TJ[$:F.V=H/@PA6--7/3)*""M378<[A`^*L>`1N\GZF_HC(I +M$A'EV223:!5`UD`G\.8.[C!`4]-&CB2:^!WCLG7EPM%M$@KTV.1`<*`?=V\7 +M\+`ZRLOD](J3_<\2K.YQJTTB:7N"RR*(181DXG2\C4<+7F%Q_>Q1#F!@;S": +M(:T(.F77J]VPBR9_-+`S8)HF4,VD20%56I<\US0I=^/D;OWS,;`.IZT)EV<S +MP<AOD%3`+VJ`V#\5\+LXP*FK3SNEM2!&1-6%8@`;:<3(`0W$H*X5#QJ6WI'O +MKWA^R6-4"N!$MJEQF`'E2#9W!XN$:LW?$1=/$SR^J:AV+%45C2E^JZMO.-G+ +M7F8O5A9)(RCGK'7M=&&^4*80<Q/LI($T"X4@)E$^1*:ETZ="&HT!)#QH^7SQ +M"G6A4V,)N31\NB7J5UL:,E&3#&1YJZKB`J'!A/14GC88ZA*\!M(OZC$A;WG! +MQ-4>#@PP060:.9L^3L3+XFHHQXHH2]?]XZW=G]X.7&&,8VJ8%[+I:L)6Z&@I +MUS$AQ;N()P>Q_\JA?=^CY)4/0F=3FI6Z@.1<(8&IO$6+@_C+[K>>1>QE(=V7 +M'#QK'3D%X#KA%R#"M9#_D'!']0AD49VL;=4\H][KXY(F258;&L%5O#WIZS;4 +M#S,V!\8@LAV?Y-YQ+.2TJ9`<UP;?>)PS]5K#G]KD2`W(+Z-9B'=J>ZQ&>BN1 +M@#`8.IN3$V9>,TA-(_9`(%0M!)(*<7A6N!9$F*TI+QX\?(4^O=O;CIK%XG+W +M\A$>32AR[_C#*A_X=L)F=295HG=">=)VW9Y3?92@2858]SM'?PRN/M?V$N$7 +MXGVS4U+AW>W#T!!Y,/.86:"+*9%;J?"EH;?`YD6A=1RPZ-L-B$1:5&/N4IRU +M[,4G8LNDU:!Q7J'6$OLM&6`H41C86:!-U&T>>F4SNG8!@R&##>O^E/CD1[4A +M;7H@<IQV]0)&%$>J[$4T#8R?X+*'+1OBJCTR39XP/(H[QW1.B.8>/!WPUL8Z +M2.U$,7L#W`I_"+UQ/QR),*)*:\HJZP\JF=ZNW3\3,5H/S[8#"'>KHX(=[^2K +MI:`)O(;E9<7VB&8#IE@_>IJ#34X),;62I01/A&V\G!5L,NB[\BM(JC*16U=A +M3]$$<R>3=RG/O&FXRB#O>?@`M.62OKXSH_"7`>W72R=4047UTYO<>3T+*>RV +MODSZN,ZY(3"ISN!L+@+91GL(!=X!_%;P)B4B*CS\)4SXVN,.M]/F83#\*E"D +M)/;8K3B#E!#:H,MN$_L_B1+_=L1)W6:,T;K5Q9QHCY+9LHH9#:I!FV98A>EN +ME34#<@Y8QP=?K3_/#E*!.7,5H@MGE7_WM6CY%HN]LBD0L2,8>*FQ7W;,F.U3 +MWMZ+FN!*!OD+9_&=G3W^_A&(E^SBZJR-KCV7V2PWQ-^]<CTDI?2[7*EVP`@] +MASZZ4/")T:X`*]?J)7K7Y?/W.7!2NJ-24(/6`(DB:0>('-^X>P4RDM?V\)`L +M$NR41"!%T(+JEX?D7]B/92,Z>^S/G`ISQ31!W9MFGT-9`V>9@79B:=J\&7BX +M[V:&V&"^VX7)%5;F;.>62*B\$*'U"L`+80*%U'#@+FC]6;6YV@/WDC6Q:IT= +M\+L\M^&QB2ZMBQ[+VP*Y4-14BP,MWSC[@HTI<JY\M#VR5.W"J"?[B*-^KV;9 +M>0F\I'!=T@-M)T`!:9DK".N[H+>8$V6.CL8V$@OG4/)U/KCH1HL_R6:0WC.Y +MG^$8LO9$SZ?`V<AP-A)!\AH*L@ZFHF'W<<KQ8+,A/2$NVW*@EX<O2?PA;N:) +M(W)[5L>VSM3R/:=R5#@"V@PO,.Z],6RKX9F!)`$ET6AQ+3+-\YV5+7LAFX$> +MA$9/:Y@6D:;@;G7>GD!F[.?$R#QMJ<N*\&XCO_,[\R2WK>F7P6(,=8M+_+W8 +MN1`46/R!C%H05>_T#3C+0N;X66?VP_[8H?P0W\2Q0:X8@CFP@BGS)M57SG(( +M_E7<]&R7$E9ZD`GL-L;B:#-T[E(Q=>@8NL<Q_0>37`X!M[5ZU.NB=DY/732K +M+>'V\NM%Y;9,/95*_LU8@KXSN74T+9@!=M-!/:P/'/&(;OT;Y[VA'5EOT*C5 +M;2B6TMZ2LAWU^Y3\E!/W\OG%L(=+PZHN%N372=ZCY`N:7]NY6=@*G(_]*0_` +M,'$;I)X60*DO:081Q[3;_SA#%K5S!.':?(<GXQ+S+Q:G'6X'2UCGR#%[1FU` +MRUJ?WV<TL'_1+/-YJ$NP$B!L3L+D46EC_'?$J"D\U_P[,D?".4@CFGNI/E9J +M@,3V+VS/=DH1/FTM#91M@_VFF]5WZ^%N*=G3I5^"+SK^NP]A`EH99<<[7W79 +M\0RJ_4_"(P1,@?C`B1A^F1OP.H-AL-7M)9+#@R4_P$$=Y#VP^F&H/\Z!*WZV +M::\_9*"UH`8+^Q\C,OQ4NN#D\':YCA6^#BR>U^D/"PHA,C^FONOL>I9!![W7 +MQ3]?^G06F%8V&Q2[C?I.A&1ZP-G68<Z!$L&)Y<Q02P,$/P`#`&,`C+`.10`` +M``##"@``HAH```8`"P!214%$344!F0<``@!!10,.`)W""T8?%U_8)41I.*%E +MI`WF/9P[QLGH2%G1G^(;JG@#1C@<>2I\)5P\88QP+"$L0/*GLJ(:"&D2$/80 +M,>5F%$<\PFVX*;6>(UAJ?:N?=1=A%7_<>48(U:5;3WLA0]VAZ\^8P>9%X*YK +M=!7C$I1",.!.]OO])XD&6L)I4:&B"@36\[,)>N9V$1!N'<7^S!5Y:]D*E(T) +MJK1OT<V$-QSMP56VP@T_CUIHH%L\O%1SE<;!E+^V^]#38@D&V:)B45#OZ8RF +M^SJ4^'Q0"8N_\P9A(Y[V(48M.8C-&9PD\1;BJ,94H$C\W:%_GHVM`N4`<^0> +M[J)?F,#\T\L*8:1A;$/,:7J&@!W4`R='MYNX8>/DP#FPL:JUA4+-8L+143\T +M%;8R4!G73]Y#T,XI/$%X6C6E[@F1".XJ2R5IA,Q<\6/]8E?2A1)2'&'[CA=( +M6GJ\E3RY4K6*%XOAT3);/\YB5(3A3YK6O";%U5KORIAQ$G^UY&>Q#1=-KC/S +M)R/@&N1^]0A\:8Y(X-POY&ND:2A4)2C&4GC9?)Y)?NB0W9<!*)"Z_=/Z>.2M +M^AG]<5NK49QK6_K'X5RJ\DWZ63]Q<&!=/WD]=M844K]T2ED1JP"^#C0,#9?> +MME76`A$,;"5PQ>DDDOWEP.C$+<0#5^"<>EF2`E1KLZIC3D277F2XVTIDX`RC +M:$:D%[LB;7KK-L!C_=`LDO93G?9!PH&@]TI(J$YYK3MFKLANE+([A#^IU3;Q +MI>R1;\@*]S>0$C45KOPU3R_:5G%V*^[8%R7YLTP9W3YF:4FH6Z19,>=Q31`_ +M!X&/^=;1@TAZX7X_$G/VN#V&59AOL<?*]&!=2O%P!,VC]K[Q%+E2<0/>OO:2 +M_WOT\JW'KR3<1Z?#@+Z'=Z^C?RZ--:[MW']0Q!KU]@]8[OSHRQ7YSAOA];`@ +M&W"`:AB$+<-I:69O.3$^]9VP0S<5;XK3EH)X.-GY<X?(5H_62A+B'2)15,9Y +M):P=45MTI76)*!CD?&F#\UX/G9(0*W6F5ZOT.+]$J^TP!@0/:#6+[689VYG3 +M1>VE&2"KF[ZH)`"8+H#Z.-4[)V)BX&A+]*)E%G$@0=^EG9$9!B)89;GF)^=Y +MK8L"A=3IA8Q"E=?N)U+*]?K^^O*?O(C#W[`:HN/[9N;W:KN$TIMI/+F,.>:= +M4K^\J`S%X+O`:]YBA/;8I%4R41[LZ5;Z.\Y3]9@?.///9+I:<+6=/K3;R9L, +MU'=K:+)91CB!G)WC:NA-B_:CX34!KQOD/V;ZH?K%`:>/5(^B)6*F\KS%OK?R +M-([*>=?PRJB"T-K157#3\>P$3VOH`VNEJ$O_O$:+V?`L%P7G_@*5Y/#"4379 +M8A4BTY`^Q:U7"6)C]AA2##ZH_42$TBG<%VV9JD/RGQVOX2-I`)-\MU];":^[ +M4TYKRDET!NMF+H/L)=<(PHWLAN#PP:$R[-'P=(V:VW0XJ24+R[3GOC@M*',[ +M`?$\<DPVV3AEX.E=A&/GO%0UF_-/P[WZO0ZR`=)K_'39'2`//3#WNHOH$UZ, +MOA]UHXL$(N[>7:1_%(-994SXOQDN1<9I39,;#D#J*[M9?A=K%##QO[.@!+1_ +M!L3:MBDM#&-0;.>KJ_>@S*#^6;#6CM)?;K'+O45?6QP*YLU"8TI:@5C)FS^6 +M+@'3E9@/H%@SXZG%MY<*#CL?SA=P3R?R`1+@25-O,MZ-76VZ9FQ'+5VCN*[. +M[AQ-J;]&)QZJ0BE>9>$-O(K%S^O7#3W):'W_,DG*`U!1FIYTGX^'7I270EKL +M/-@-E60H*T`G3Q&Q$8HQ4H.@_#"X>7`+]Q8C._"]&\!,32MXNC48AGG6J@#H +M%<;&H`4MSX>)F`:QG"WLR8X6T=P_[NJ;%R?8SH$".Q-E:OK$_ZRRO;S9,!2\ +M'^ZWV47J/OC.?">_,7&B"W`VW23^B*L'#L4Y2X)[`P>S4!&P%FT%@2KN3VJO +MLHS`:-)AGU.Q7QVLPX"!ZUZP\5.R5QOA0BBM_H0"2W\^SYF.3@))T>!IDSZ? +M!E.A_UV#>KW.5XEBVV?"!)/LI\;2C'[@L20P9KCU]`J4/9R6_)6`K_H"4G^D +M?SVU]<'\S?_Y&XCOB(^8?=D4@%OU4[.6(-AAT8'A@\Y1H1=;(E;HD'I\<3GD +MS5W%$%G1>T6Y&J4[I?VUH+]LIHS0*L#^BL8]S+UR1X.GQX!&TJ"7@S)O2=W# +MM,'7"'O>=3&!`]_MOUB$F/4QK"I>%$)/9AWJQRM:KYKU+)B[.]'=]8XD/.D$ +MJ&(C_%W]4,K26CV+A0$71)RF4-3EC"D:B!T?A,98MIREF.8MY((*:2Z/=,(] +M,$,)L)K?H,CJG=^_;1)$N1BB#R>`0H10<O?'RFS-I"K@#/MTDRXWJL#PKDJG +MTPD<7A9T0L=>Z?G,;;9'D,(3(_&F0DNPX`?#\-@+4_8XU_H>&#C\O.K1+!(P +MB3_8W,L^1MK_Y\FP1JG4)I])32U=;J!'\92&%B;8"]C<][+0E;LGJ_!]VQSU +M!>DFT:-TGH>$YO>RLQ<'Z(4F,8!,R",#+M*H]92>4H@]A$^'[XJV=V9H.N?+ +MS>`$N'7.?2N>VFMR!:GTE+/$1\>86V=7%W*U0-U<*O-NZ+[,>7LFL9RW0436 +MWAK\LR?)FJ%:F,MM1@V.G+89@U[?%6@V(77P!"7A896(^YO'.$_),E63:.%[ +M]-J8S/U"?F+B+34WX,2HCA07^=2>LU>1`N$[ZLQI$_LU5L2+G7F@4@7P<?\: +M5X=W>KE*O<2.W.A3XNJ3M$>'M(Q&B;%O@?>+4>VS3T?8)9[$$8?T^4.'`E3S +MCA-3Y:,:%.AZH-;@T,&O)LF%S]ZDK<RR]K8K&SAP>T8I#<U:3J4`X<@EV#[" +M,%T/:,.)TE3S,T`[C<[$3@(<RX;F8HLR5D'W^6DI2S!>=)&*_T,-P$?M;F4% +MD;G/W758K21K"3N-UHLO&2]W$"VQ'/4)I!/12W6S<+BH%0POKMEMX>H:1M(3 +M@.I,I!DT]EAA;UCNKF&$:6%Y[Z6S?:AFM*1.8E6S6=T%_Z1C>O+V@``)`LK= +M&2N"HLPQ>S<5Y@K*!N&HG[[9QJ$)K7;ZX#C%#'C6^2*0$@R,M*8KJ.?&50G, +MA]#X7W4EV4$>'$\QN,KV8$N>3>[0T-!34,/L:'+H*X+M>Q3[`(328G+O")"Y +MU76Q0JJ!]DCS\$'LBF'!T)7I<3;PR514*[U?#IN.(__Z5Q@L,>>N>L!H.E"> +MQ:+1.@5A5,H'`S,=^K^<**3>+BAZ3&T[:Q/^3)$39Y=1Y)('2M>>5,SIR2U: +MZ2E5,(K`4^$)=U#7WJ*%?6;^@652.+SPFTY7)`.9I%KW7CAQ=$"S+)24<&F< +M@R`UNHLD86BSGM0G_D-P.D]>9$\0;<>^H$F4H7..39JXWRSTH=`N261[RL<W +M,%BG,G-[=/N*^928Q-R(2_.<4\$K.M.6@J4K/#N4LC/MM(/E-41NM1H&?\`O +MRQ*R,.V[7L<(&D/&[.FH?0$@6OEI0RYLZN16[M`NO*LSD,Q>8RPJV2(>;I_G +M43N__-"SX'00Z]-\#=17&"[A99\AS14;?T>28D`6LU<#<;HQP&?H<\O_'Q%- +M,U@B.*LZZ<1T+&BN4KH<&@2<T[O*H64TZ]"Y8RTR*::'4>8SVFZAE&A]N*TC +MO'7>Q=(@S[5<BX$^BJ"/%N/1(,H5D-5X]HS8I_(;.:.CAF:!`)6%T@)02P,$ +M/P`#`&,`IXL.10````"9$P``FW\```@`"P!C;VYF:6<N:`&9!P`"`$%%`PX` +MYWPFX+\32PLMUY]=L=/QHGGX##-4O>W%+VI^+B@P:.DQ:X6O@_8*$)(PK^3G +M)`;R)?_IV1/%TY=Z:;XB>\QGGLZ;4YV;$<.\D0,=[8D^`S+IA@5P_VHMJE0R +MX-5KI6_`%8*;B(<JJ+]K#8,<[AP@N'1A!L15-9GY)B5-Q+.20'SA0)..3<"X +MHR_JLK4*&$>F88\M]PWK5:L7?_H2C-`X7YBGMWW\GP$AUL9`B$8_(X$F>:0' +MT-C#J#5N+>9X"NO5+KVPX>XJ<9PJ<#DQ]]EKK/W$]O;A.$Q3))=!E;[2G+RT +M,'D#U1GA>DSY2$Y!CLFW==^ZF&S'&HP#H(>/[OH[!9<@^86_/MQV.!F%*$[B +M0-4-/L%]NJ:(WIH/RIYTD5SQWY`)?7`8MK=^#701>1_);C=FH+_7:+K;8OGL +M@#%]`'N53B?<A26FI.B5NKP_X?B<-P@4+68_\UK=HU>>M?C,T)UB%M?GIQCV +M2UC3?<'RL$`2LQ*X\#='00?GO;Y.#R8^3Y?V3@QT(36S0&'4YE5_PR*X?X42 +MF/HCO0#?_/TG`4'H3GD!H"$B]:PPJMGM3Y58K7J?60Y-N^&Y]7H5M?1VP^'_ +MK4OEJV':KE`8.BLN&=/K2BZ!M27122`_XVT"\,H$@,_=RRP]GJY9PU+E>:E1 +MWHO/P.;?4MAF/31)+KS\:`NAFRD]APW+>SHPX0\+3^#7YLI'D:=/!K$A0U:" +MD5:F73/)@EF$@LV<T]9ND_"W#"D=_$,348TB^+E_SJI,0LSQ^T,T_^":J]U\ +MYO69`/K<JVKYFD'RA.OF&5WJ'9FUCV%C(W$_TP[CI1B8["8F#IZ@JC(D%[<D +M2O$U&J';Q]`W5^0K.]>C"S-,9=2Q1H<X8D%%PZ`4`]917:$'HL;.D$A,!A0Q +MM$@0=:SR1:#()2`)G8&:$._N_,GL:2G?]]U''&U;-=TU_$0'U65AR.<H`ZW< +MNZ8HC"E1>"H@BEFQ9>?SYJ7,]S/CU!.G]LYA4UQ\W4SO4JB?![XU,7_/=!C5 +M+`-"QY-X4U;::^UKE]Y^[DZMO(Y/6F7]OO^BW'%VV?(V9*W[4I8(UN*IS%F( +MHJC0GPA#&0F+5V)$RK?8CZ0%<4,9F"D1L!==A'Q+@$XQ?T@,>O%[`DU[UCH; +M,=>5`#"U73$TCV(8%H=VR[[*O^(,P)/U[S\PY+<-S=$,`L9Q7OMCF-+&#MQS +M=Y#JR-=92:8%_O]G86G^,^@&&L*K_):QPV\4@996YR\EIL`$]<RC`(EUOYZU +MTL(=98)-`?3K,S0@WKH4X534G=%N"[J"*:=V,.0"E\?TFQ4C.SF"Q#<.&F/# +MV;%&EIO;:"Y\U;B8[U3IM$ICG4;='2K&S2R6:HW@$^JPM:L!I;=@]%Z3HM8K +M5=CW648_EPNV?D/[G;`?&QZ727D,V;C.#[K,$3J-SD_OU78ZJ60->!<S>;8V +MY9$D)Y-^20REH-C$A2'$NZ@!$MZI=J3[^@4[;A"'[DLN9\F)R7V_!WZ&:3`# +M6P5*U4<7GLU+`/,R1VX7CZX4EJ;9<Q$K2?IJF>^V4_D=GUQP6/H\?6!LHXT` +M(O(K,+`G9;2V_A=6'RS(P`T!P9U=B3P3/=QM._O8O!\F8#B_BQW%16H2<SQC +M<4X\;5GT2/.Q^G:'86U&V1A,0HZUC(/)'?WG**\.6[$V;<5[]JEDU9T?N6M, +M:[07$]`(7@<\RY2ZL31)DCEY(W.(S/7)*@Q)>\_82`\H9@GAZR\`HL,P$:DQ +M;=*J2JS.AP2/YA&I&?[B%-_ZQFN(]Y%ZJ?$0E]6=`)*H9Y>[,;C]=5"^O>2# +MR^LXH=46!VLP%X:NLTG=C^L'L;'WY8,]DR2$$33KBGHN+IT4QAW-H7,\#OMN +M`,K,I-7E+EZ0)EV%M(;7F0F*2JOXH68E^T1^L'-R^0"&@UWY#?JF56D4F.OV +MF.)OP%TJONJJM:!(2YASPQ`T-(CA81>FY9S.>VI](!IC#-ROZ4YFBI5MA(7T +M]756[<P;E*Q/&U`"[TT=P[AEH90CK^2Q6U$K2"#LX:52E:4\Z0D81W-WC+&D +MAVR_FG9ALF4T&RH(N"_O"X7'13^?$RE0WJRWB$G#5(%/%8LQ+4CA4R7RB`1Q +MLK+XYM1@26:[!NO5OD/&2K&W=_UN2!23&-&WS/V*U8-V9=J%2U"TT;X9,^;? +M2,U^D1^4LDK*9@B%',4`7%';KR;GU8<GU+_A)M./1*;(<;P!Y<,3";@L1Q4Q +MH6HZF+.3O6Q=X+;LIQ'@VU$`C9$D*=-N+2+U+N#(:J53*&",+JCST2FT+S62 +M\4)14;ASRR2<L)Y;[A$*I?(9E%`771RN)PMB[]6,YD,F>;N";;Q^P"DGKM+V +M5-2C@70OM"N8]!E`J?,_0-GGOI1/8ELC$K2-[3[=M5W&34UHL$LE)9Z$DOS. +M=;$4QX^QGO@2:4@$S@_$['&&N/3\K"L(*-S"#U[0H,9+(R4W0Y?#,/(KO#H@ +M,Q("_GQ0]W?YAZ?U6[#X(G9ZN=:1X4*$(9T0$MN&GJ-)I5*(T"+J_I']-JL0 +M[C+7S]B54MJ;YF'#FI*IV&U8[E67DGK?%93`&3G)"MCQ<+Z$A^&18NKRH963 +MK=<V9U:GIG&:K)3H5Y'!R1WU83Y.X-5TUP2=^)#]4)V<"$UJX35Z<_94??7> +M]ZN!3LU\TK`#6&+SY+5_-;L]F'I5'L:9*M19]#<F[!C01=,.8$;VL6%[4%,C +MJ$(F3X[-?S*I7+0;Y`4-L?EVOF"J]/G9L9YIQ=8M@G,M8H^(;S$`!WTZE*_P +MS<8W:@`Y?M!^7TS\`LZANYOBRM[CC0/L<DD3MOC[S?7`R8/M90CV`SN&\_MQ +MUWP#0=,<O[$F_DE%-TFBZN.H;)MR7^(N3\-'2RCDWZ@<C`[09Y#FX4]V.&;( +M)H$,:66`PYRC%&P4'*+S.HN3\#5/C@TT,"6Z;C<6Q!&@KO1K"WQ\2;RE'8;( +M0THH02::EM0%XGEO&Y**-P-J/DA\1.._0]$.42TL0[5L%Y4J?63@9(`'LS36 +M"%6J^3)L8F)O+-/*4]:YA`%YATY&#OPD06XO9R`I[V=:Z9VH&8&-_^R/_BT& +MSS"A7$.*C2F*',*9)B>K:5O1<B,UKD1DW/#.RZK]^6PCE^PYU#W\]@O/H79! +MD<LA[@RUMQU"-Z#E4UB$JTH+I4;JYK)^03Y=L5V=\>U'.%O_%``"#RAH%%!S +M0<0:>>#=ZV"OLY_*?X@&Q)O0;F!_*+7.T]49^..PHIF`+%?/50QD3OVQVJ!9 +MQC5DTH5VCJX652R9+]>>QY!9U&0B>H;<F&/#[/`%-FM.F4V*,$G@N_[E5IUV +M>]43F4A7:]]&9Y3$K?L\T$HYS;[YLO7\UA[>C'[4,4P.3#!("<_9^57O@NRG +M:2DK[2YFK`EB<*YRZWT\5/T19T^R*BSHEEGF5YD(`;*@.?N/%`^[G#JG17&J +M^A%?$M,R3;?0[_+B(HRJVM0TIL)X>P,POSOBUK)%@P$.@D-'VFB:*1O*F?@< +MRT$ZM!W7RL+7*;/&Q5!"L@=:QP4>-3W]@U^X`/.61GM*+=?X7JJ+L,\(:9'> +M:B!6HX1%8IXM2F-D.=&&)4A_B:%]#&6#"<U$=11;>E$7\-N@;0H'J>OM4/\B +M:3SRSM?<5:Q#?#)+:462HV.!K4QZZ9#*L0RBZ,[7+!:V=OS^A#IT1)"RZ?K0 +M[IUL0/S.Q[TB@[)XG*6,^Z,`IF^LMQBDL%OI)3$HF$,/A>@W%(F##X4P20@M +M;QF0EMK%%SNQ2[1"<*6/)]RM/<V$E1ZX(S+S<!XB55W_J68[L[;UTP_8$6EI +M,T4I:5?@8$1#O^W3L0X=,-Q@]PED_UZ\)KWQ,CI6C8PC=`_ZI0Q=YHI0G(W% +MA8PKMZ0'CB4^KG_5J"2)\1'[WD2L$G\=DC&3I/-Z:%[3.9[2`((T@-_5)@Y` +MK#Y%/-BZKN^D#,'1$,WJ>]'F()P0,XRC2<TYY>.MMQ^.'_D`LBV]7N'M4V0$ +MN)``$M+4#92JN(U1_W3\`X5]_[&(I[02R4!%TYA_]:KQ/1I$`@?8)61)<=+' +MEF_!P2FKLIC06E;7J8H(E8'U=91Q^:Z+)7CW1UZ?8V1$;SC$H*<,RM=P/[*1 +M.^XES_-#$V`9R@OZ1W'/TO7\(R4-']6<.9*EJ,6&SO]WNT2\.`QV1L1L&.EV +MSEI=GXFJ%]BN3VOG4QU8N%V!2#%%CT5"J:Z#8D09]]0R=_Y*ACA&2/-H\^>Q +MX@D@(:&"^;ALS#X!M-^6,+L2?_OFS7TC>9"7&(I(!\0L'@E"?!&O5F0/CF6* +MJX:G[W12A^O4"G/JP"S3V<$]-?\6^>M63B>_@FW%-0..>SDCD"8XE7$_PQ)B +M^C"R_?HGI),A?IP`FSCA]V8N;7#%TLX/`ZG7#SSWF?K7V](9ZIP0%9RA4=#M +M\#7$V(B]=J'GF(D]9BQ)2-B2$HL`\,S-F>:6#HR<ZC:3058:%**UK!)8F$$C +M#I'PBK-UE+(3,;GBFUF&WB417JH?;!\$DS/Y;_7*@YX([^;US@_T):_>^`X; +MB$.G'.T2S,2`)FM].0*18HPFN.DTH>2;`190%C#,:PQ#VW2&;=^2_$M9X;Y= +MQ*7PI9;),H&`I9!-4)VONZM![V,LJP7ZK`6MNI*\:BR<"`J!7ONF]\2.AGT# +MBA.S!0I5%J-0*F".?U__JTMR]*Q^XH`_@G;`"$4O=:4DG\0QR'02,_:CR_J7 +MJ61E,?KPX9->^V41DHA:@M.?FBPZ\C]'?XR.O?0/(*3[+^.G*$Z3SY#9>I/X +M/X>]8\@B![Q$FK!2;8:7]Z0*29!?=,WY4NB_%N5IU]0X*R/UMW?-)`1A+E00 +M>Y78I[P%,;I%>4H[WG7N6MO2JY9@<!1[1L%$++";@B\-Y:-H[UL$S$6MN4,- +M@I<BY>):80-&Y$4:`Z27,?.")U4SXTZ%O;:E$T,75"1E]*'9S#`I=5LY)%`6 +MFHAUVE^O$+4EV*7"R.\,8-RR@!8,_%(P;G-#`8*77RC<VZ2.DLP<[+JO-?I^ +M@!W0L+6&$?+G^?=>EQ<?`+%,FIV[,M1_+,M#;7`GW:1`.BFAGRUN:X[5+/.? +MRE[T17(B(A.8]1V7P$BFS7J>`_F@-`1];H3RE_H27Z!I5MC0HSR:^@,B[YH8 +M@-&("PUO!PG@2RMX5:.VU6%S`3=I^U;5C/.<6?E.-'$$#Y<VBKN2"CYYRZK% +MO<D"JT@%,6ERN?#A$=__4@]T1M$V_)8\\0'DUS<G&,UL!NK+*,.7FT\AO='G +M)*=JM8(+EG_A:!]>N\%!A-*XY$]AT/<!1N+SH4^&REM(]'T'1*+32.N@J>QL +M=[0[X'\N?7S=.LK^$J)7!1XR`2D!R4Q6V\!S!1`<D]C$7F1WX>L1,/9"&W0B +M.K9N.ZF@U&YEW;3F96%O'#9.^+BAN7Q\4L[QS-`-%)\C_V`*$"Z0?4NSFYYO +M\+B"A)\>S#S/$Z1)`P0)LPVP">!C!SX'XTGX4@/@!)R!&%`*T9V<Q50!<N'U +M3,SV8QY:ED,PJ/A/&6Q6$#LQB4RY]>?U^#<'AO.:.GPEGOWP-,[UX&\H5+<T +MG:+FR-923]-)IB678S6>.Z\025)B^-0--0!+A.U#4R#F6+'4DZO.TJ,[N;;+ +MY2J%['S\O_=6[_<`>NS@QG;^4]M*DS?FMK,[T%P36,#/[_UP[)]HHRD(6)5F +M^3H"$14PX>?LK.1*:=)KTLJ97S]6W=7H%Z@DUHD/1;[\$QV[1Y![?D*#KI@$ +MB[-A.[Z36F=P8C#)Q33'&E.#$[7,&@KFG^'E].;X`AN;V'@VV!*K93EHXUD= +M'>&?`R*9&AJTO1"NG=W]:4KULRPB+]6PS$"@$[M@1FG3'1EIW$/UI)$LQM]) +MV>@]5='D"H=2MWI/.<'?LV7\.0*>2;#%;.&L'A91;X+D/RJ`#Q;%:$WD"<-` +MV`JP+J=3^CD,(ZYKR0;1%);;"@`T(ZZ5/B@,#.GX[$WXR%5CHEBH^=GQ__81 +M>YHZYRJKM`)KS(QZ6.SEIGV8(^P%;!0@K73KN&A""NT1$K_J@`.TVU,M>3&( +M4B=4!FR?/#ZS,&"H4&M^2U_7XU'7PAL?2Z,<34E69DIC?;.JYI_6TK1K8!V0 +MP:]TG^W$EZJ1+I7;6N=[A:V`>*C>V056RA)Y6<+\#7##7IUH.V2(7=#E>LY^ +M.C]5>]]-$#Y4?HW(K.':D9HNTR?5#/01N(,H+$:M3'V8JE'<D/&O&)=PN\0K +M*T_?68![8I_;C\:_>HW+>.NMFD*;X]EBW`IRLX?`V1HX3-FBE%\Q@-;T9606 +MJK4*VR$X48[:9U'&6M+A7O3&\"1L780[:6KZB37=UL>M[X<95K3O=UDD^Y52 +MRE(6W:+@4_JJFHE='^I*?3QOZN<MX`DF#!97WF]<%)*.D&].47@TF$E4E[:2 +M=VT1C17X.!T)>(E5I!?P!P4ML(`#19='X&?V^8C;<U/+[GD^#^9GDJRMX`HQ +MIF5<&3O?GQHUBJ4E9U`T=!0P(<7W6\^?*JXL%?OQ)U:NPW=29W@DOT8@63"% +M;2161!D[^('B:$R'JZ.P"&DRLE^A4KU6=(L'69($0Y#03$?RSRJF9-I8!;\K +M4;!!C#OO3^\RQQ$Q59!5OX^M=S:BB!PKS`EAQC!-^7&P+H:]IU&?5**][7KC +M;FX)76OPA%`'K_!`;(F]="1MTA'RI>`!0QF4/]Q+NZ:H-\]9G?8EH[ZM48O2 +MUU'USB!RYSAN4K#KJ$]-^U9ZWMW?K%!+`0(_`S\``P!C`/BN(T4`````HP(! +M`&LZ%@`(`"\`````````(("D@0````!-86ME9FEL90H`(````````0`8``#B +M#W"YQ\\!$895YPJ>W`&)/%;G"I[<`0&9!P`"`$%%`PX`4$L!`C\#/P`#`&,` +MC+`.10````#1*```K7(```0`+P`````````@@*2!U`(!`$Y%5U,*`"`````` +M``$`&```/%Q3`[C/`8D\5N<*GMP!.E56YPJ>W`$!F0<``@!!10,.`%!+`0(_ +M`S\``P!C`(RP#D4`````PPH``*(:```&`"\`````````(("D@=(K`0!214%$ +M344*`"````````$`&```/%Q3`[C/`3I55N<*GMP!1FM6YPJ>W`$!F0<``@!! +M10,.`%!+`0(_`S\``P!C`*>+#D4`````F1,``)M_```(`"\`````````(("D +M@<0V`0!C;VYF:6<N:`H`(````````0`8```IHN+<M\\!1FM6YPJ>W`%R<%;G +E"I[<`0&9!P`"`$%%`PX`4$L%!@`````$``0`C@$``(Y*`0`````` +` +end diff --git a/libarchive/test/test_read_format_zip_winzip_aes256_large_ppmd.zip.uu b/libarchive/test/test_read_format_zip_winzip_aes256_large_ppmd.zip.uu new file mode 100644 index 000000000000..b501b07da2f6 --- /dev/null +++ b/libarchive/test/test_read_format_zip_winzip_aes256_large_ppmd.zip.uu @@ -0,0 +1,1399 @@ +begin 644 test_read_format_zip_winzip_aes256_large_ppmd.zip +M4$L#!#\``0!C`/BN(T4`````E;8``&LZ%@`(``L`36%K969I;&4!F0<``@!! +M10-B`$FW(O*7F%7MT6RY^$=5W"*P&R95;B4@\::&_PWT(LWIO=BQ,R5>J8YG +MC:$_?G''Q[3]QHL`D9#QZB'4Y^#B=QN13.8-,ESJ)-)2I^.+&GA//+8U/'UR +M3-NH(&@$&`9!U/0%2\`]$X?AWE3KU^E8J=2^3LMQ@XX#R.WO0YO%?V.!L79J +M_S4&]C]:^+KB^/:E1OEE('?CM#XOQ*(5']NO%+XA>95ZN`D'<0F5B*G!#3@N +M8;F@I3,:^PH;`^F6,`9T=SE#)P7?>Z_)@TNT-%?;BD@]&I7H\3EXK+V\DV9, +M24RK4(ZY'U6,(.R1)<3JL16];\,5F1Y8/'?DVEQ<+)[`JG6S/9S-67ESV74S +M<ENKJHA'WLM;ST#0,I/Y#7HKL*I==[]-1WO=>I$$B9;*55!6`&Z`WU4I"*<S +M#O(.XLQ,^PM0*#K0[_T(#[O6O=$5*^G@-,>KJ'^B3B!YB<YALEEJ_A3[U_I& +MW3$-2F2HH\"R,(1,4Z\`H*OQ0%&4K\7$^T34HN,/IUWQ\P;ALTVN1D)N)?/P +ML-7ZH03Y`&ROV.2/VK@ISKJFJR9S$\H"[?]JBG*&\;*K--B7=$/J`].H.O69 +M/A13GTR310<7]17)=(A^X"H(P<$AK+\6.N[&(\?NV/F]HG8T=EJV1Y-AQFB' +MEXU3!H;-#9WS"MWN63ZF_2-O+OQ[MKEQ\J,#-Q.[7`QV&NF.R1PJ-UE'[%;% +M88:=*84`-Q7^>]O@':=(UFH(Y#_JFA)4"NT67'DED^!P<,^OL]OP_G=KP@&W +M8_`-$*62<?+1X0;*+L_URR#\1REOMO99.9^HZ^7\_:[?T#Y/H@L-F1R8#0+1 +M>`ASQAQQ#RQ9PP#A<G):LZ4%3<2*-ZO3*17.PUM4Q8G/"F#/ZO#HG@`H+I,A +M(SB$)>[3QUA<E5FPK`9D3?_>='\;8JV%>&A3R05L40=^QG#<F([MK[:&!@R. +MEEJ/>M>^I4ATG3]8#O978)?(_&Z1(.SY0:#0DL^SFP'@\X:-JPT#&BO"S%U9 +M!HJ"9LK'D8E64FT"#-%G_LSHFNDC5P7$7O-38XANT7SJ?N9D',O2?/W4/MUW +MRVAQG#IGP+#%[V@!`#KQ.D#.WQ1!'];_KOUV$(9-?R)</CYFYX.Z_/%)&27% +M-UE>`]I\C@01.^@3;-Q-VI/;/G+*M:J4>7MEM4]FNL[E@W$:NT@Z]H)"DH[O +MTW5?NHO72A6R#+T4?^`"MRKYZT#.*\_L:SOF?0F8(Y[*HKT+6R?>8($:/MI. +MF6%78G[16$`2847B02_YQ/[<R*DK-%L!Y@E6YE@;L^-E)9[[._ODR>]^A`QM +M;MH*_5D#KHA"XQ7C?PD0#=?SNO%AI>HWP+VV(ME4%0-QJY:*IMY6,/J:)TR' +MNL0W1SXK9\T\*NA^=I7V@-$R94G1@.0=Y&/W@EF;@Q]\!8F^MQYWNT>;0D5< +M"OK?S4QQDD#DYQQ&!+[O.9C2J"/?1=+]DJP9`&"C(-M8ZLT)-<%0S70O"4=P +MEAV3ZF";Z?QH,,I*^1263X6%BTA%60O)#T#Y(91I5<M)4;T>4G5PD,96/&ND +MS"6L$&M*J=]F,;T4\0#M?/;=\?/V*2,TZ@Z#<#">1%FL86\+2$`IIJRL%INL +MY<6()-O9?)SOD/H1U*N592JAT[]/2TN4Y&C-&%%%UKO%G=E#,H=R9B[5["(- +M@7J.GIV:4KG2#1S[&V7/MKX?@,$3X4+"XACZ+W3"H7W3G:K?MT@]RN5](K$) +M5KO`J0,UGZV@+@&"^GPR:@8QG*Y6J."1WK(!]=J4D:D7RYOW/J>?#Y8$SD*$ +M(('/#XUP]V5QZ\WAO+(^_A!AS>M.$08<;,_!M@^C71]?=<[3IW6%JXX!;<&O +MI''$H[4NY"NY6CL2&FICXGEC7?+-%U'MY(WB@=9@T>A'^AB4K^N8$Q'EBFB6 +M-0^P]P*SRQM1HX/B(IHYYUQ#4_[M-D1P"ISU2+[1+#U%I+N.=E2$HK')2V\_ +M+T.&*\>$Y\AV`=ZK8QE*1,K#,D%.+_E;US5"E8^:%JWR##'&OG_-=\J'>U<+ +M@PC^RM'JQ5+P]18993]8/YT+.L%&N"E62?GW_/?CCX0)/-G5LKPP^9.F0M"D +M_O)R3]!&+TX9J'%B-P^53Q(OO)%QS:KHK2CSI_.7ABKNZ`B9*?OZ0@$CQ[G$ +MO6[`I';TR07">W>!=K"X`R6/F<W2C1D60W7&TKK<DZ4]A8_HH80G'(>)]"EX +MI5*$N\"P>BNG/M+QPH-P')6Y3\::I"UKM2H>8;\XO,W'_)=)4J\F_TI`!(*8 +MA_]$=UQM?\#F\UOKR"N2`^@Y0)+=`.%[CL`2Y(8!%#G%$YE![6*:6)DRJV=O +M*;,[[>0R4OSE*BN"IYQQ9Q-@UZ\AD<FE)]3#ZV<FM@SDSJ.-%G!2\>_(+`A] +MVX1$IKH6H:\NPK)&G=T&HQ1VD:@W6'":"'.?-`BK=F8=MTR4)4D#0,/*RUWW +M%:="<G63,%W>W*BIL059%.D:PULH2@,BL.\G80G:<(T'6_TO'XE]5;Y-Q3(W +MB<`R_`@6@Q@WG)6)<8SZ9MQM:=XJZ;!O3X:806$T'#14S9RP61$$N8L\8;2G +MATJGIH39^ECKE1D;I\/.DQGB,?-2E>/'[IZ\2R_GM^"Z8%#EG\5-B?($/T"= +M/Z?GB><?P%R*F1(:#:-/DJ6PYGN@N/PVB`HSGA.RJ'8CKM*4JBQ#8VP%VV56 +MA,+BD/[R-/U?KL1V;@%3%ZRK5J@!,JZ5WQK/]T;^]*8<0,/E0I5[-F5P&48L +M)-"@FWHZ+IX6*$"%4M8<])^Y:X>G("NQU%K`K)M&%>.1!,%_\Z3E%(+1B;$: +M1%%Z/^Q$8_<XZ@#$*DI:]4]6^J<-S1U+@/V`K9OH$D;/VJ]8QT<XA259"?6G +MF>*<06)$1+O(B_Z@;47OT$!=XD>!9@2#M.J>'I2GAS5O7B1A5.HN-=QI6C6= +M0*/K;N;B@!2U_O'LC`7+@WAD?W(Z@U<WW"+>4;W_4/#GMOC8P^@=#0WXFW4[ +M]E#R!/D(K9X=!M/XM06P7=`71=EB8[DA&S*QS4)\P22PX$D/8VW)G-JJ1D^0 +MWK",HO96'M+9W<+#ZVZ-GM);A>XZ=7W*9X43C[G@J:D#/2)7+\+!,8(\<NF7 +MX559&BK7?I#Z>[9:Z>_A-%M#MNBEQ9;%8!('VZLZ8WYN/5]Z*]Y;>V&EN-"7 +M8:#>\PF-[49;(GM9`GIVPO/_7O,TY^0K3A0NMW>$GP(I%4WSB.W],K*6W=MV +MQPEYM`$7,;GX:PI>&;#+A$>8,B/7:`P21G856ZOQ=/&\(T;LN69P5?/,;Q&Y +MPA8[)BICX/8+&XV1L\RA,NS'6HI0O`4YJ%K%*WD>44?MQ])%V,K^)BA55CX3 +MSZN]M;1B/'M+YUL"U&UAO\MJ_+%0./XAM'MS$4&0Y!HZK(J?&X=>O`=WG(BB +M4KDT>*#H,187A'EU?(%,O1"!+W!J^6#XM^`H]<8WS,:_0QH]W0?-NJ$:J_BF +M?`:M6*L<.%%ZZ4ES',K_9B860JMJ2WG2<!PB#Y[9QNK4NIY]M@K#V[6HD4#E +MO&;K,1ULP$I]N:MA9[Q&=7X(B70\2"3Z'OQ@M[MP-.B+Z]NB7T;V?2^L6XX& +MQ>21Q7=KR\(NPRPAAQ4?+)>7"72YK5QTGP<(Q1UH_+8:T5$CN]Y7-4PS<%U( +MZ!X3ZO?FTF6HB`PJNCA,QS[N!8A"$:)SG'N2T/`L3#X9(K=LK`7/K\OZ4GL& +M6G<[AL_*0J,\=Z9"1SCE#DLHSK!=%F#=$6FHJAB<_^H&L#R[J`:$(7]/&E7N +M$=K;P(A&OC=MG<-8L'S"T*+R4Q\0U>I"7\/^I*X_7.YY8GK_WIJBJ$:$#Y97 +MSEEV6E`+,Y-37[L<Z\XBI7%)1E''X+4LP.@;Z)EO!:PB?`5AVK/(`ETV4T[& +MQ(B;K#7?USW\&&!=:YF.9JXN[Y(@S=/>M3MD9S\SJ@OLP(KDUJ06?^Z](&N? +MS9Y$41)(V3C?GG"-GYDOH\^D#M"W7-\V359BZC\O)9.TQU&E\J\6\ND,8^TS +MRSI1E;)T0)LF8:'G)MXT!&],2UCEFLO;1Z('OLV[EX:;8+FD][(-6/CKTK!I +M[4Y,XMHZ]\\LPGN8H^D>20S3UX&JDJ:/+QF%95]@=7,UP`W@=;3\P]TC9D09 +M&C_!(2KDXV(F`=[G,*,%MJ_H>0$$/"@EG;?#^`Y`'KOF&V/,^$R2I9$K9LVI +M-D>6M1E_:@4PL$V*?73<TI\A7[_FNGNI=C/_L91;%G-?+\?6LG#N6&4ZB"K. +MB?6*:<X1:R)3S#OZKO;IIC,;T;%W.Z?]/<!2,?EW_9IV#_-(SOE28DV,;K]V +M7%#]0\.%[!EM08?`DT%&\TR._I#01+XTV%]I,*)#!MY,(\*]-,8K?O^6[>X$ +M1MG04A0=!84XEXJ][].R@7(F:T4_2Z'-.5%EB,M@`)"\_4#FMGA+5["$#&1> +MJ#QL[]E2Y"M[Z&[@S(S+%H!8AJ3X2>$2$^?ON:Q&3XX<=V&38KPJ5W!#WFCB +M@=&[B,3H#X47>%<8;,5IC1N.FNGFX;)"GB.'']:)VFD;"+&-(!#5T'U<)(+O +M&J(5QBUZGK/*IW/\@7G)`2=(BH1='+GGB9"84HZOY?UOP^$Q;/\"^G'J.`NF +MDWWF2ZZJ<VY@$<Z49'[0SJ0]K`?;T<1P3B\+,8J"K\\X)13'"8XT#E36.=A` +MQN][5!"T1-Q%27M&0#F!/8E*OBK=*FT0!S`^-]Q(%"C9:ES;<SL8[YJ+_7@" +M7DH_15=HS=`ZH.A58E`;Z1[-8Z"/!-^^RIA:.@(JHKN!'D"[(B7K*O]8[SAY +MM[ABBLOHMRF991'6U`$N^*%A/L"/!N;9=^.P8VJX:Q=..=DZK^LW4"`[I=)T +M?S(C[O-D,D]<<`[H(1BPWB3&Q$B]V^Z\Z?4%51S)39Z5%<+BJ1K++Z!#*8/W +M3+!L?J`E?#`4#_0WL#:&V-PE@X%+&87,1UE3R[NU-H9]6]7`3,YCK3@^`5O8 +M\47:<==E56[EQ^-L22,08OBVFP@A9O?NE\H4/=9)U;,@>[2`A^I4U+H2QJ.1 +MW]`]D\O@MRVP&3SY]W3]*0;O2``]['8>,K-=.\.IEN>A2@0F4U[/VG^?X<?[ +MP7SR/H1!J&%?U94ED!J'B&<:5`9`KSPCUH-G"T5HF7L&%/V<\G%J7'[Q::FW +M,4E5B-%'`H%O%.1+["WJW75L+2\8KBY^3%B-A_DH*>;M0:PAH/%\P66Y\[\? +M61`G?2*TI:\FK38]3"X>H6F@;2=#>X@3C46__"J-YL68<US'7?'\XPP-I-6E +MYEH%.S1E>\^C`)[=,;\<XI0,5A4F6,41/W7FW2X,ZFD7@0%;V]H##3;T^3'3 +MD%D\<5)KRJXOCQKN7C=?A-WQB+P4CG.XJ-32\XZ.N&?]0YXD$8_NMZZ/%`KY +M*P?PO#J!O->`KLX,5!]#A^:["D2]062\R[%3V)_3]4A`H@P;J.A68):J).`1 +MAS-)W08[8[LE>0:F]P;?74PZ`%/1`VD#1$6TX#$J@]0K^$P8VE..7R=P-B<1 +M;*\BF"U:D86.7D4-HG"DI3C#^=4@5U0FGOU82'W7T:/K\E/NFHG>J]9TL9>& +MY53O?PLL).<$'*'U3+3^TO2T&+BP<ET[F6*(%]H/I9`E7'Y,Q!`G%#JSW/IC +M9X=L@J3#'DNDT-/A,2=7=I5EV1+2_M[_O7\->@D2MZ0255J)KX7SXC9?>JK_ +M:.U[VWR=OM5+&>_I,RU1T?369X\BIG25ER0NX\K2T?3\)5Z@-)K`$+8SY5YP +M[PD\<114UNJ<,NQ9=2J]?9^+]YN@H3-C(G#<K=G^N:J6[1LW"Y-3&I6U>G'! +MA)$.:)!1)9U)G(@:L-64CYII",^Z$DSWQHIELP-PY*+J+4WM*'*;.;:%@^>0 +M^2"-1^7BU9^*(;XH!#+IR3K@X8OZSG?T>QOQ^WXEFDXIF3]#I[`*G^:/"T_\ +M6PZ(NK,^/3LM4O`.&:)DGM$I'9/Z9#AR`SKQIO.<":2P>^<YUW3A0(Z>(4># +M4RM[<R']<]'9UH/64,H=C2`"6-V*:5?A/.QE=<BOQ$7E%O7;[E'73&)'NS91 +M0KGY\4^!O5#3AO`,O]%>_OP;0=;G6[[NF>'375"HP<9*@C:3R+!UQEDEEWFF +M8'43S7_?8[-1U@_NPY,\WQUN]'LC1SF%*X))?+SGME`BHEFUC2ESL5`I_$V: +M%O2*PU[KR,*XQ>#N%;#*^9B,/(M$A5JUUDB:C:B'O&Y&P>5(N6[5DK>I+Q.U +M1">@S'+;[K\2!1JL[(!XK),S7_$OZM,87>%Z*BF1XCE_^:,8*:61;N^Z#L2H +MY^X#[O0Q.0?P,L_G.%CWQB>*WZ4$:P^H>8H-;N[$6DOC53LW;#"M1)%7-[EC +M6.`AP9:P\QZLPB#$`>QL%),MGXMF=;;H!;EZ/$+/J_4P#5_FZ#-RTW2&,>O! +MG'.'VTP_R:*?I6J.3EWJ!U_+/82#!`^6=L&1'ZULT/3HLK(<.PQ1XIJ'2.C, +M=,!+'_^&FOOM3Z>,;$0Q#F!QF;IONHG]=[UA'E<;U/?"K"&O#HS_NV<[1+?N +M3Z%)/Q<4B_015+BYFI@$$;MW\GY#5J""8L^*>IKC.N0<+/A)%O-7FBFJG>L' +M6?LH!O*BG11'T*V/O'>&9JP'I87^&-15<?\J44Y(R,$V,N;K<C1V<P85.B8! +M/2E=#S-M]Z@_>A5"`+O'&E0M0']-94CG.[.P8`53XOZ3*\_LYL(-&V+BI#K7 +M:O`-B6CF5R)CQSK0:=L[MTSK,0:#RY1(,,5VK"KC>%%3NH=9&`(2@W&USK>S +MN4.[B4:CY777`O:-XRV_EJA=>#$AV-5?#-4AZ(WRF@1QC>`PCMR"K^F%.EDX +M-L#4+/1*.1FK]YHT_/%)6GG=!V9I%"TC.;@R7[XD[R[)1)(C9OHC3(GBQ,== +MX_4H]YR.?/60EYKKA39M!QT?T%U%:SOSZ=/=PYNMGUJ#;!,S%`OHX"@RYZEZ +M_[^F1_G+@E1X6OJ=:B[0Y/*6A8%/#1>DV:*6K5OP`25'LM7XF&O/W3N$2[5T +M,S"C&6R<Y3BZ!RZPCNM-3/2]<HZT"OW:`2?J+0PR3;?+_7O=GLXFF#[7@\G/ +M9G=XYVC"#$^W^]@`F':P60]%V7*9"R/E%,:2!OV$0!]#'_#5UP\7\D^KY=;C +M&U-ZH--"'S;PU_LVKZ(`NQ!%T-E;JMPW"ET*'PZ'`QN>1-#*VH$-M!9-["[2 +M&K>)6`_M"&NX[*_?.3\;C29[M463I[(4V(6)<F)SQ<>.%I\??P>R4U2+^Z3% +M\0A>)_Z0NY=EU/N]^%7:WR;-LKUS7,8$P(WE;<\OT0=,PY@S>M[;UF.8=X/\ +MH!;\28=GE9R2UMP,"]Q_-3^FL-#]:Y`J7?BFNP[K'\'EF1@+GY;T!(,GJU/J +M,]*:-C'Y)H9UNQJ_DKW,OT=>4?C^G%#K^!49>,7BZE5H`->&6NN6RIOW/X52 +M[3]Z`B"ETS44/PR<;UXT%PF.YDDF_2*]T?2=S%NJCFQ?^27"70?_A6*M*\%M +MWK.!-7R7"AX_"HW>FEN+$SI?:ZB\),]EX].#Q:/>"MZ+S!"OM'^T!1HY`O+^ +M`J[K9"/W>3M<*@UUE<`NPZD_:*Q:!\KDD^-T&[</%_M0:XC)Y)MLQ,>8=-.0 +MU$5@!`[[)EU$-AI!;Z]8TP>9)_1SS>@MHRW?L(3D=]95:]M"562VXRZIT(B` +MRR8.J1L%-:%CD&:KC'R8FQ@L1_IHT3_J0T9.!$5-XJX6>1"G[8"SO`81STJJ +MT0%::GT2GA&P53.W3H*+;RUE=(&N>EIF%`/R1\0V;KJX`];HF/[0>=7RH=0= +M;0JC,AV2^<E][&^8=K:5B2GV%W2F$1*F[9EU>DY'-'85\1X37!ER=S,&RSRQ +M)NVC8%+LH)6Z3\+Y\\B-3-2&7E5R<^`I<_K1P"H_#)SNKG*$GG?T.+3.T)!/ +M40E^B)R,(.$D"X1ZS!+>5O@5$/@!_W(E0K"7R?=V:2>>NT3B.@O5G[B5W<%) +MCCS>!MGC4UW3J^E\[/M;/4CRNVGZ_@'[&<9-14.10"O9"NQV/MJ>#H,B4,)< +M]W1FV'[<F]HN^;R=G4ECPA\)7M-9"R!HA!,_#GDEP4#X(1S,3(OZ7]B"TL74 +M<#R$"?\5K)M@_6`\[HOY4L#9'D=E/O.$H4\$579CD+1ET,>E*I\J*)Q*"TSZ +M.=-PU\@I^/`9L*CB==D^#J,;#\A*U/5"8SI_H:SOF]7Z'FT;H[6?.DE,S`Y* +MN\F0>'J4I01"V9HU2`('I+=<MIJBP3>1W@0Z6;P-:B\X>YAUALA48'7=\,,Z +M&R/-O,'A`QQX)W\]M.5S4LGE=""6MO`V9@CY`6&-3($'!=O2_"W)\`2<D`!0 +MH-WH=/<22_!7MF"?3)`.VF#A2$T`UEV37EB><Q^<K^R1WK+P"<#JT[%]!5,! +M'_2>WPFAC"*01T6MG7=&`"XP_V?6W%X`8;!;$#2_'J(H(NQ^;,7>L\?/\B67 +M0,Q1>!TG\$@\161Q`973_,T6^[X_$E."H/JW4<6:]R-]XHY`,^!(<%W@_TQ) +MPG`GXP;8%S9HBS>%[1!?1+[VQ$`YNK0VE1!+70E27NR'#UA)Y)%M;)1)EGNW +MY;9HD'0G'P,??T-QJU@**]#<YW)&;H82CCB70HUKFJ?<)$`67ML:8!>/I`(6 +M+J7,L'+OR7P`/@FRA#`BPZ`1E]PO=59=VD8\_-X,*R17!JT")NIJC8.1$;C2 +MJ%[8SKH.7BXQ$R6K$*-P0QJW1V5XO=C]F@K@],U!64D$U80L+-M`K20RKM(H +M:S8WYTW'3)>Z`G5>?MK)W<R3LCKB6XG/5S-$U_EG=W3.\@#4NU"/6!>R"LB( +MP$EMHZ9`-*L(CAQ(3\UUL%/QD6GCKY\-S9A;UBL&K90H4<O"#RVGN`\\_^S; +M.?!+@WLUM.YH($)^W4T;'069V/MBKRP(R_3-NC*MNBQ<E'"?%VPC3BND6M"0 +M761+L*MQW-XN!A4O3`49YACND#L]:A[U#_$0DWE?GLPIFS&NOBPX!FQ+`HZR +M9W\I;6<'W83<-.5FO.1M!Q`3(<^Z2YB[!PO>>)+'-;A[W5VC:FZ/J=]>ES5- +MQJ)`^DG*!".9`Z3_[1&>>M"Z>AWC\=#,A/S]M$HDJ'GS9&UFOVWI<U0Q$/[E +M)=[`//S[^OZ:1BLO,"99Z?=^&/I668HCM1BJN%D*42Y`_)X5[3H1V3+%>3CW +M7=7X+M4]Y:W=*;3I6\:55A!M?7!&X[*S/&EB<!]OEC])B6GD`ZHPRP.-HA?! +MF1;(H1?9']N"SL?*PGUXLQL%6Q/':F<\]FT*@P$`7(+(48L31E>MD3%:ZMIT +M4EG\>GE,7WF8L=E,'$=DMS#[U='GV:P8W"-1.#3<^"7R-]H"V7]4>$3RJ;86 +M_U+1RA=I&!\^GHE#8,YSCR%(](\;:O^F-;)%T;W33\Q,*"6G\`>5;JX)RA&D +M?WYJ;)I+ZK`5HW`F89`R>XN3V($@?=$R3Z1.]3*82]'ZR[^<BQ!!M-2.8Y\; +MHH+)4,OB\I"BHJ4.Z:X6-4VK7>$9!:*Z_(`Q>M9[F"JJKH7$GDD6Y#ODH0&^ +MFSG2,V"'P^'8"TMOO;UG!/:6G?5-;N!V"ZERHUO]\U]VYXUJ.V3'!`?MM%5+ +M2II8>P3O(*BG6U\!;^VC$MDT5T,I:^:P/5(.=',BTE2S"^YZ2P?3Y0D7/9P9 +MXUJ<4+9'BXEJKX()%;52=&R4QEWIK;0\F`*?,02>7B'U;"GF`D-/.^\NEP!I +M=)*`!QR]?<?T;WLW$^S+:P(L-D%G!/05)2<'F'$DH(8RB`BQIJ#3":4\!F9W +MG,V(#,(1U4G-@1U,.TT+[=CT6@AGMFP?O3<3#L&="R0G^F$8QO`DGO6.EVKC +MFJ2&BX'YJH3KFM`2/UY5X&-RI#&YKT4+&U<-KEG59(?D'R6V-P>$4%"0?WK0 +MI!NNB^X)O'PBN0'Q?E:[6L.B/#EM^I[92G]67"+ABFR&C,WCY/WKR4AT*#;N +MEYL3I"^NLY*V4*94E3T[=XT\LVNX&%#@7'C\A24B!TMN1XW<^2OF\;@:=3RZ +M"*-AWSFAWIO)MK@Z'05[/R7YMN!'-.Z+WI/1.H@ANIHZP6\BY!C5Y()VO[>W +M[,-@7(LL\I7O(5C)D&DA#)-Q_#'\PG=5I(*?]4RUJ5\!!HS"UI7BYL7(8WUY +M'H723FW8[%M17>]^"#'H@6ZF;N`X,<O=RK1D)4/!.N.G_&E-L<7'_<&$BO96 +MP/+_&.HXY2-C6\,=.`/3O2*<$B)2TC,[N*J,+@N,FNJ9Y-A\^H2`OL&=0H`M +M7J];DH-7$^B5>):=@*Y@%HJW7YAV>01G+4KDDSRY:KYR]\O7\K1O\*;STB2S +M>I@MM8-3Z;R)O4T?.PLXZ/XB;KR(N%P\L--6M3BGRE>5B_+PE(-P%H$AJQOF +MWN*,X3(^`(ZK/RA+\C5`]N6"?<B5QRA^G+D9V0H[`%05E7O(/&=6OL62R-Y^ +M'+G!"I>[V!%G2<)$M.`\)$;X5EN8X3?87?K)L>09T\7\]:V:J^%AC#:B'W2T +MU.>-#LV(^^?3-X:(F7M9Q_]&B+YPJ5H%;IE(:RK]5<;DK/N#VIFE+M`A*06> +M-H4LMW1N?0O9]K)I"FD<@I?QFZ8J7'^(YFEYP.Z6U#^[[`\>P(J&,'R2%(5$ +M13)U*\YQ6%W%"Y=9=\]L<JZ_%UY\3?5.H%E*GZS/O@D!9W<Q@:E?@LK,`VO+ +M@K]`@7UUH\%U,<QW3T/L1,M^1CL^3V.]RW3!JR7'Q,?C(\X2`6V=<*%](Z6L +MAT<@SI-$&57+O1LZ%+N/0XU.EZGY&M,I*Y)]O;TNO!SZ1"6"M(D+*LG@5$<A +M@=/L86'0@$5[I.UHX2`/G$)0TH&-!EIX]K09$\P&PZ!SY]A41RWU'MF'GA-X +M>%%BH1O!$_,N/3P%42LC'1K^MH$6,#1#77SN;QXSL=MX=OHYT?EV@DB4X,?9 +M2!!AMU_E@OE)R\86SLK2\8W?-:ZY]Z6M32]%VM[J:E(,.XB;F.)W54/A\(I< +M1.")(+J3J+=!`JB&K3;%8=@LO'IC2>)!EVN3SSK>US<?76W:634#YOMTSX)Y +M+D+Y\1:ZTU`UD]O\"%*`Z;XB2X!^!"AF\WJTI;/O'$^_YAL<0'Q"6^**]['5 +MSJ?>U%[RHJ_"+,O,-K]B%^F(E10C3*O;1-#Y9=$-MXCU']"++WR7R-CIB$;O +MMBPP$(7*XI-19<*W`;.84E4V3^RAHQ*G@9[A)N%4%+H\"L9ONURW(P)6CI56 +MUPQ5H-L<,M;V2J3HV5$(F,;T!JG79JDQ$8RD48V(>&IPHDXP=`&KMEDR=9N% +M*-P1'343C[]';+""2=L==T#%?(]*O!7HA";_4H*\';,:S$I,_'',61P?07*= +MURS\X8T9Z>_/OF/_-OWY9G]0,P[0/^>H<^PN&*D/YVS-3SR20D>][AE`\HM3 +M,E(W)+1[2<HT5>SY@-WD>D$.]<LF7-\P:M7BI-+XN63>-%CSS$E>6<7>1ARR +MB4?Z0^VA0I%^O+2ICBI`L/Y,J\'^17(-+MH#I6&SI""Z+5+VZBY38A%<:T?B +MF2:@8%U=-3@94WJ<9EUF23.SE@%-E1BD8\+%W_EW>L[&4BN=$V>&=7LV\+U0 +M#>"#RBOQ>N$V1P_W9<Q(L+23,]?K'HD$O5_O:/E'/163P1W?ZPHUM50X7U=( +M3^HL6_M=\/C*4:1\T<@8DIAU[CY<8%2&XI^0-34$+SD4KVVJ4(DYP&!*+*-Y +M?0DIW>=V1JIYHDJ=3):N.L#UFUN4:2W<=+C]0&KT\TFVE\$'F`JD9O\#:(NW +M]6S^P!BI-[IN?&+.+4NY*18);F^38!=0XJ?$CG`(HPC'PI&:/#BH5';>?]2R +M&O*)MCK25D[0#HI^7A"3.B?S>'B#\["0Q_.9X/0OG"NDI*K)W_J4+6()@*7# +M%)[06D)S>[MXVH+$"+2^[Q3>]-4UQTR]U4ZY?4U'XBR/3-(BT/W&YG?C[=D" +M=O2.R#3_''@/SFS6(QJ7N`-#/5]T0THO0.#?T17`URNQ6WN\94Z_X+$ID`(F +MO:LJUY'8R+WT85B?.6C/AD0V$!1/R.IO!>&4I:).+8\<@TTVY^Y2>@*AG:K% +M\@MOHR](%=7O:@T(`)2_RDI!,@/G2C&$+W1Q3'"F;J:N+F'KHQ)=RN4^I#!> +MKKO+SW7X(G\J)9(X)U'[R]@$FE%_\2&KR-[3K_*7:!@1,7`E.-,EXC96?RPD +M'C_B,^E_]EV8?*)MX`^UA%<E<U9`9P]K7!HT(/%-PS@JDMZ_DRC.12Z[Z\-* +M'LU]>%=2V??K.\O`2^Z:AJM]?%-^;]=BR8O?I`DJIIU?PT:*>]URUG+/;86G +MR@6?9DK/YRK[('R;JVQ%G[O+""[$6]08H,*STF\5QR">356%/VV"4T_?=&FN +MSTOZ-(32T1P-UU.@VE=^FW)_7*ZE4,$KJG@HJS>S'Q+R(87BAR%YD_RN0'D$ +M>5UTK=CHD<M1<V!):Y==8;7'L[JEV@]\JZNL"L])-VK?TXHBEI(AFH0';5!^ +M2K+4N#$(JT#RC=KCJ5YG8.\MAW*7V*X.T7"XUZ46S?Y+#PK[FQV9]@'LN!`0 +MW>&>4-1"V1.X.<9UR09M6FRDUJA0!-YB:*NZ\-9)X6$'Y:"\BSBWK`5T2`;I +MQ7#G@\%&:D>5):&Z%PHSXWX,4GB&6EF@_XLLBBQ@F?AHOFV@U)EUTEG%0BM? +M2.F?O/-P'?SV.DJ4^X%$]->]=6Y*JC[&P'J]\3_1`24=+[[CBJU*X:E>S-F& +MOW0%6M9!!7KY?6#9$EV^JB-(T&FQ$_'VPQ;[4@UH6DD+R%PN1SZJ?$17VMA_ +MA\[D%#.U6:X?73YAN+=33=;IA)><J`K!>ZU?E.'5.C-<])'EU.".:U"3F1Z3 +MYL8HK^%:\V1HW%IGR;IT.N;AS_[C.!6OY>S=G.B4#B.3102O/4-6Y6-J`.(; +M(!1>.DR\&?*[S(AM>/71`G&W+^ZR3\ORRY=0<2*`3LT64=)+@LX#D4=/$?(I +M7A8?ICF*67<?C!O2;[$(NM(2\2&TBOOL3PPBJ3<FD>#/,APS4]_/\#!$#M>( +MUP4RY<072HA-84$WWEX9D?TAD2_U4]$:MEGA12+LE/.BW45[X6?2H\:D\F4L +M5$()%'S:&MO3#8Z<^Z-8[\'5L1#V9][!.3(O):Y!L#%<\:0R[.Z(/U@_04*T +M7"4/0JF&V+Y$Q7.#4HD(U$YI;IB0!?_T7PO``K(@[M0\:']W[0F4YB89;X=T +M?//R]0!RNQF?A$=+'S]2*R>\A1=X2Q>W_"@UVX7$_.P1*K,XZ>-N,ZI%=LK] +M.Q+:'!"57XN.Y74CZL08Z#7O!]:EJ<9\^!C_Y9E9B-L]&4E(]B;M$/B4[%^+ +M.8;;O-D;"T6AR5;)>6U<TX\;+S?XZ]?.W9S&7E$S,P-`Y8*</(0D9-/8W&&# +M<&!=M?//"._#U@@V9JPLN^;Z!3R/LM@K#B`LHYMQVRE@NWNV:S@`6!<5DI.` +M@]D]L'SJ<D%:F7.4`?2>+%(@C04S<1BV<1E9%C.PD<TA#Z.,[F_F5GR@_(%> +M]C9J$+.A(T;UHYSJGSVT9^9A(!5=QVPY.:_.B"H9ZT"&(.KW1_')PTC%RV.[ +M?PO_O1U@4B`XMA@0RC6\3S@L"AQU6[T]$8U7R;)Z)DTC<C8VE(,U=#2.967& +MN;[<O**C![DD/.MRET4Y:-,/T-9,6/$F5)X^VCD?+YCRE(&3(*D\?-N%JQK# +M^V8>K'&9#.+C+^&&&DYNP@(GK:3_N.90@%)9$HF7=637RZK0\9[BQ@M=ZWBQ +M+4MVW#7DW_\4O@C#H67A`$&F0@Y"`EB)[UE:`LG^SR`'`/,/G%[OC0?6PC;3 +M83LI`1%K!`3X$V$ZNN:T##NL&`"\%Y=6C.3-1D2V1VR79@E"203VQ"Z_@IOE +M!.`4^'6=W\WA/\>8"K1C4;@G%8G3H&_G\)XH=QNT76(ZC;NVXT>/\V8\P%2R +MO$"Z[>('EE/F0V+U#_2OI]?]&RRGS[!C*F_1EW^=@I%RQFK#F99,)Q!,:-:F +MP8\!J.:OS["F\OD_>G3^2!X6T*7E_1-Y1.JG>*&M=-_M=41HT->^V:U(*A$W +M1F<IDIY`>[_^,GT8WSVA3W8(YX/1,Z&,&(3)L+3DC3ELC78"(ACCGA6@5>SN +MB^F9BW\>)8-'\<9D%6(Y4Z=9!_-`DO-1@6_$<1O6;X[X8I@S0%953(_'V&=A +M,H-8O)(S@V\CNW<E1?.]#X-UJGWK+^,W?;%UJX?-[^A)A*>EFV>$CPT)F9FC +M)>P/A\=U-8Y9*^:9-#[,JFM]Q+MBXRO8'M).(!W<.+7*-6XK7DYWV1!F9XF= +M^:WH#9?D"1Y('34"J!V&J%Z-12W1#G^&1Q(^@;C+W"6TP.I(VDHDR.3JE9H[ +MR!N1W4W0H/7+A0^PD%\"#D.DP&ZQ?;X46]QSQ*X.3>\LNP=/F;KZI:;T;N`L +M;J^6D-1H17($I>]H%2SHW.F3)P!M.'L!S_$*!.XA_F/`+.R;VN6H>\$Z9",K +MYY9Q6B3YR2\]6MBIF+]/Z3WF,_L%#.M)NNI:&;^6A`V!=`R%0>Z2,MGB60.M +M^VWXB%J.$D]NW?%EAH*?:2`4*K+XGR`VQ:5L6%TCRJOUG?,JQBS?B!T">>"/ +MY%ZKY=8YCBZU\@OD%M/IC\R90*3EV!%;Y,T:-&@_":\`_I8S)UM)7L)S4^WV +M>#'Z*E_L!61$1'GX!TTI:U_++;[#NG`C'R<Z7OLS>E/ZX$\T"$&ZU@P#67=& +MPGN]&,@9A3@[9"R)PU>YY%H^'HSK'YZ<;.;W.]=_3<A.(VF4%.%PK6P8ZSE7 +M/G),A2GE#;Z7U09A+8GY<4L+@'_KPRPK)0XV(;@;=T'W3H:((.27"TMU?]+I +M?BWP:V_I'U0DN'"[3(1A;^2Q8B65I1/0!M8VPZ,,U:&&N4_I>S7,A3Q-26]V +M/D7$`-\OW1[?6!`;9SN5V$77WI?+8J2(FRY16F!8V9C*&5\B`$S2KS=2+3`_ +MT_=<1.K=#KIMQADA0J=ON52%BX3\MW<$-S0/.=++&4*DWY,?W3%VBOJOG:=N +M_J>_HJ/%C:6;@VKM@!I'>)4"I,MI8I4A);?HD7FCU#+**%.U-=&IHPWMVL/! +MFC_130$.[39AOC?`:QIVX-?\#VD#C>"((X^ND9&K_7&@//A=Q-XIR-'(>K.: +MTPH7TO5O]/+29;(A2%VQ.=75S!#P(]MVILHI8DGAH`(([63/[O->*?QHW%VH +M2JFTA6RS$P'KOVL2VPU@OJT[@6R#&0E/V;]4RJ<'"PW'HLMVGEU:X8FKDO:1 +MW!R)AWR6\';B!3&MC;[:PP&Q-G?:\?9558DYJI28PGUD:Z[JES%P4&]93(TL +M=,.P@RWH'7K]L6)RQ]HPLH`!JC0+]@@#=N<$].W`^.^"'3Q>D\:(#W+GN;T* +M$7LN*B38+CTYB0L[N)#[\6]*\"%'W.?<BZ&0HDU76AV&)%[1&R$K6Y93]]6[ +MJN8$-GZ$XTR?$`,Q<E+/X\96$PA1@W[CH'3-K28^;ZTEOOL-^QX=N^B,\B<W +MCGI]V6)\MQ#&OW#IV8J-IPT*X3@TN;&R>OIT!P@5AXVT4A#"V$6)$9\8GG#? +M+!O:I<A1R*K@;94Y&'1QNTI=`WILX#*9-$638')1('B3L8%.D>FH8&-_YKRL +MEW$$.A,]P9"]><_B1\U<?I'L`"?5THU;+&DABD/)+S]32%_$33"GKDO"*N_@ +M_,M2Y$?F1?(0=:/%UXJ@=-0L;LL;F_/D.9'`$00J?O2TU/+%D_^/;DBPS$^Q +M,\V^J)T<S8N]Z@'KG<>^YX<B`O'95P:QZWH8QHI:@WY*"=YJVU3S3I!&X7%= +M$VL/I]&)?*A'9'9=Q@BK4H*PVA0$"*-ABY-S?QY9NT](ZAKTOL@6)?$-TZ"] +M-`D;"'PQM$5"JSE%^BI#=)OVI^"=IR^7`,*VAC5-I?51#N4']@H>TI?.L1<L +M\G^VALB4FA=5O9`ES6TPDEKTS@7U*#"535<>^!$[&;,*L?93'^V_RP$?L9<N +MPQ996`1;T?9I$CMYWA]%Z@PX^09.$UT>_"O_O&ZS1L:&YNU_^!V)""@D0SHK +MG&FB<VQC:$!S706?XM*?AYDR&+@ZD&06A%W$</4?;UJ9BP4C\A)EVU[U@4T] +M$#/\L<F7LL:K*15'T0VE%D4JMR"(CA%ZY(K>0+F%,>.//SU4D!CA$S"S]"H[ +M&0/!AS_2MR9^=>VK\6'#Q;B6_]]A+4CNHV2%##+=?'&@/+5E?#AK,F1JY:I" +M,^2C3!D@$7>_^U%46/*(F79F=74B0R*2-&$EO)2K>4Q9*"`M\5[1YII3$'-M +M"2JJ)HX.^Q/7*W+=55U\2%]O<9*!>?H)U\P]0Z1&5E4I1V8B:?:!W8%;NW.D +M:TB$%!F:(SZ8%5HIT_?F,!;[A]5P=#4"0_`SKC'E"KR)"E-K)+'.D1@=4+K3 +MCQ1G8>L*3NBF;U5;!3#/:X<8;EM'B@>9%)_[*>@I1M]?(-RA$EQH"Y-4./4I +M0Y``,MS4SR,O!,X"<FG%=(C;5G_@TQ&`2D[EDQ-S@`ZE..?KH6S-)XL.;@49 +M"SXA12C\5[ESJ==7_+GX"GQ:B(F8/%58/^_*Y8,:H]H)];BZ)HJYZOFCK/*= +M@M>6H1/-;?]O"A*WK-,&24+<KFRW,%@0[):%%9#Q1/A4K6\R^Z]NE!$1!=6\ +MG=<E4:'HZ(R7NI1C0H6^4DQET^Z*O9"JI(+)1X5#?<28EN##@.?G';,^AM1O +M[$]@SC@G8Y5``"E?NWZQ:<HU6\K*O-B`[DS!81YF<D=I"`9_1>A$:&,$C$W8 +M;O/O?29Z4O'/D7RJ`^KMJ]="&-]=V@$PLC'3=+F^LTVF0W.9$90).33!1YH! +M?W!$[L2:CE"NOI8AD+UV$8@P\UUH344?!_]J!SZ(1;5`^::;8$YZKO?6[A($ +MS*I"!?.Q#4;EY%<R*II:W<A1AQ1JO8M!#J0"M*TG7=;;00@MD5?:3@VTV*UM +MK$L$=O[(A!'4AB(G-LH<;;,?F^LIYR@`\)MZ0U?F"\\G@A?4:)CTO`9:K',= +MH86\Q:ZS3^QHNR#ZH37=CE'S\%;P*5]/#/![@/H79)7*;91J?3R>%<-<Q<++ +M#S>VJX4V$1G4P42@ES]@,2#8M6L98!]O]`OR:C(O9WC]8TZ3NT2YFU`Q^M<2 +M.<KMV_OZ'JI9Z!\VO$3O9>\OOM\V*MY:F,%G1;"D[:=474-)O'+K6Z'5.^+Y +MMW3(0-9NWHA"PC`;FK`=T6KA2A;3'["L*DBL*RG!.2^/PU_#"52#ZXV0T8K' +MK8'_%^"=9?#BI'-FNM?6)^CGR.E`+'+%!#CO]`4HV-#./V5,P$^S;F(=?*(% +ME*@?9ATU`(0P!:.\1%1.]C2>$B3TMU#RB\P)V/O>L2>8WYT5I4E'4";`5[BA +M#AORUC'*7Z>B@]K;=;X1E3O!AI9,5<#ZY4\30)IFVZ[QX0V<#<="OT4>9KNQ +MI0=&]7:O&R=E\N'>2AFMG8D<D[C6/T5!O93-`)=UM[7L'C5K;EZ*A*@60=P\ +M,=_>*`==$NXG55K?%-&+*?0H.A].CNS2Y"7]8.P\7^,R820PHS`FV!@FU(6" +MO&2/8V0S>Q\!]K<+P?\TJ\&3G1'LKG$,F`#93KD#OGTU`]B3S^D.</NFO<V4 +M%)X'?I&7(.$BCV"6`"_<9-4;\%`V,D7QC/YK5LIQ7PU_9W]>T`I_8+K7["LI +M1*\ZB`!<EXUK`"[VROMU-VS-#+N3>FF$P>BBE1HSH?25;N>+,K4=!<VJW/(M +M:G?]G"&MYZEF^A0NTNE<*L(VO%Q^%?`I]36C?5-@:!(+'7'"!EQ%'3#%Q2E2 +M6AY*!9M4AE`=P1"9+[BI^1/-DLOAH7EE.<^+$(B>;TH98*F8='B+LVAS0ITZ +M%T*D0TV3E*+U.9=C'W[;$PTI7F65B@(]<1\#(^]LAMF-]G_W%H+,NFCTTB8K +MC\LT<(YN`J:-X_BI&)Q-?=[^Z-+0S$$*'^')B>WH,5-V0?N5.2B&+?&M%4]8 +M>FB_T556;M>RB")IL`^\\^*[T[5D`>[<DHG7S5<*PP2^X?&VV*L==\?!H3B< +MY\%6V#O?;&''FLO1G/&C(IED?[#+[.R(9EH_Q'-3<)-3OQ?\ZR/A"5I:M*ZZ +M9#_RF<_KY?=R:J80TS#UU8H;J3#?W`F)-D\,&@X9&0RAUF53I6>)3M?`@-5_ +M\&*-<=MMS:<NW-F.A*D8%SZ,_Q]G[ZKI/'/6I+)WIF:D_R=EYI#C`UZBY@MW +MK;(IY37#X\KB-YLU>0D\J%Q7B0/'$C4?`HC7(P*'Y7J#?=<E9\ZML'UAB_K: +M=X``VWRE8AB+Z?/G:A'@S)8-4P-KQZ!R[S4?CB)?G_=,8&^DXB.ON_3]G0+G +M&I3LC;%86=G_O#/;X+T^J>Z4&^HHYEJ7G,=@\>Q-@@?B9UUF>GHQCM*`LI7$ +M9HF'$I\B%WX)"$D=TZ_1HBB\265L9=-3+5HY0R?F-5G90=[QZ+^@YU?H#U0Y +MH\);TS]1O][F#4,Q@<04>8UA<.GYWMJ&#G_C%O,@D,YSA0K(S>:"VV4-!97] +M?6UK\0C7$\4/;)&0(^.0WV%F61HSI[/L_[?V1Y;P4;?"7'EE<I,<*[V?DSA? +M(N!&N#"ZYY,`:RF,B^7L=0UJ1C64O^IB^M_Z];ATG@#K=D<.O]C@M$UV-^Q# +MVA@.?NR^`GX":A6U[NZ`>9PD1(4N=?H@"D:>[-=$FX93R4M\'RAPAQ-<*N/" +MV3L4O0@H)NYW<*4Z^=W=T$]\MU2YD!ZC/F<@HA\I_E-QM4*4)4IC>_WW0V>M +MD3+S**B/65,RZ6WW(M(4*E4FNV)BNWH'@+/L\HO-X:@1[TB36GEJ;\E_PS2* +MQE<+7L?[BW6TV(F&&::9=UA>*MGR12_/I?5>0_$_T_M7^(":[8N84X)VJ2_` +M`O`563$&9BXIT>`)_'AZ!4X%<&1IX:9&(DJ6RSEY'_H&$>&:=H7\^MB^$\TV +M5^4-9XYD,(9GR]9L!T[*E$8EM*.#G71T^E&W&H!]K)D()%`:\J:Y]-J-E^"6 +M?;_E(&GZ*@GA%6^?`J_>+DG=!G#)3")K^I`E%<SHB,J/W4VE/E/*P(H]AM-- +MNT];8]WA2A>&AE+X(0BYXM`">WF=IV[)`$RABT!V/1?P'<M7]<-QE&]$X+`7 +M"S:ETM:4#.ST)4G\1"'MKLS:TMKG.]S0M4Q7YJZJ!I:+XX@MT;#3_QDX7+Q] +M/BPR=V$V(9OY!KT0G']F#7(;LVP<NC*K[M)96B")"O+95T4XH7>N?3_SI[;* +M(HT/3&8Z..T)Y9MU^)_QP%3ZPT=DE`)-=XZ*7\E_)R@]R#.?/%-T5D&E\(DR +MG"6SZ^Q*]*\T"]$3UF:?2DF,ER;+;+>';A1H1DAH:P7%7B%("766/J7[!H0B +MU9*)"EHL!;\L19P1_YPIA]+=,JGZ5:>78:(++59M[N"C4+H4(0,FNEN<\V21 +M(`A,8B^8(AJ(1.>%%9\@/A4QI-EBR]6KNR#=X?\1(5ER,[/9):J<>[8DR"8^ +MQ#@.J:E.X0@6/J67;Z\Q)W'<H]U)W]"NT`/H19E,`7PO/2[\D_R[Q#*+"28M +M?3A"'`.X$HJ0N-7GH-)VJNQ\U>2[FJ,\3<VC&^!1ND3@T(BG1K`@^W[DT>?$ +M@FP&\583^YH&F;3H:@FQF(MN0`_M(-<B0DA^GEKZ#`XH,#8S7(SB:X7CJCG1 +M/JAR8GUQ2+%56@ZCUP[#D\WRXP303,F/3KI391HHQ]Q7>UACLW)LN)4<-!') +MQ,LQ*P#^^5MT9SRJ""A](9Z92JGPQ(REECUVU#!WIAZ]M'\!N[8?/*WD,[<9 +ML_4LQBB3S<_/?JQHKA]+@+&>L"J11^P"@26\_M:B'`6D<\-%H"#ULLE>GO!T +M\L;1IC`!!&/9@UY!.W(8%'3#3;A*P9T^W"S,X8%'(U4+0CFYRK.&32`F)TQ1 +MJ+PG'S"C1!>->'^,Q/J;A&WDM?.B&(*YC0M6-L6[,C!.'611:C'4L,TF!+/K +M4>=);K2P=AP]0ITYP>:77WVCC_>RQ-?-NU0)4YKBHC'\M%V2J:U&Y/J)M6RE +M)1)X^^E0LTX>YQPV!2J`^L4:9G];K4[S&Q]%-`;[U54/#"/V4%6,"#MP6C14 +M=E$X1NSMLZLH8J9%\59<72%'JM,T`)R^U4R)WK2,'T+>@40S+K.7<?_[I/OT +M3"_R4>AW]I:G_'T(N^4*R\;1">O@K7*ABWFPD<\T@8/_I@V_D02\79%;ELZ6 +M+S9GW./[9`;)A@\KKLW%6^'R<?@UOK>$]VYI=I2X0=]K##$1;?Y.AJ6WXJQB +MOZ%*W$=-_^'0QHE$)0^=]JF]XYJ]:(9//-L`>GUQJ/(9V%^X^HCB(PT!A;E` +M$`&E@Z%D6ZZU-BAD<_*%KW,W,%K"-V"A+7V^@_O@+E>G\YT%>UD$]>T5<#.0 +M0/\(2)^;:S<Z,WI[%DWCIG)W;-]M1)N4E>TU!2S`"X:2=6&MDM`-.95]DG$* +MIO@89)&8+:.\M;TJ5GN-!/3`/V:V:N`L+[^$T7E3?5!W:R])6>)4-#.)49!< +M[ZDY8/J?KWCMM7N3P@ZI80;#0P3+B]'Z>(>R+85W?WI>*8E&S'6A690"K5&) +M8++Z+^&BK7I#-/88))IT(Y`A##BU>?_5@M$(="6*#TR&",H/IQ['.9A>D'E[ +MCWD9(<B1G]8-QC[_=NU3B'A-E[V&]N^58%KB1]WE_!?[H,+@CNI`M:454N04 +MEG(;3B&NM2L+%P4(*G+L?,MO4`\Z)R4SJH`^F11>RDX4L4A8L,9'X..L#1A1 +MSDXEP7R^L1BU=5G[%[DE9"JB!=-M,$0P<UP'*6I,:GC-,0^S9``3\>G)EI1+ +MTY0$^25.B016+,6X1P"_=\(/8^E`$1CY];9UO=@Q::/CF-[MX7&]@7]&:RU* +M@SD!2AP;I2QB4.KMY20"JS%$@UM"OGNS0%)5.RJT&9"=/$#RM61^^K<JS2&3 +M:$*DA;*"C,>M+X\?7PER%T!5!QKZW\X$>+2HD+/I8;CSQ.U&/>_XUQDG5Y.N +MAA:VB,MOQ^P8!SH\&A!M+`8]#?B<.(._%,Y;@DK7"\W2[*]4VI@)2F?Z^O01 +MB(S7%SV%ZUP/^--Q*!H`/>K3;NJ:%=8W3+_\#G,W*'Q#'.I2/A:]U5QB@.$4 +M-/"P,HL?9Q+DQ]F'H.H`EA%>NG$V%$$JXQ'3)WZ^6Q^/`)_RPD%U=&_0OU>B +MH2&$-7OT5$_>FF:N/X<-1X0+1RH-:4@S,EF`E"C.QWF6QZFT^EWT"<@YNPHZ +MQ'.X,.].$<;6KRL.]5=2*_*W>EFT:&P1'SKB'S)AE5?87'"D]_VR1^C@I>55 +M3P5FV581&!JSG.>@<NT>H-]J-@@&'/8I:_OQIMH!(\M1ABO_O%<YS1-\B@*- +M8:I=!\*\`].Q'U922K[Z./OIY.%BC*^@VVH1-<,2Y+)A4NML(C12`O##!%.P +M!S"R2]$ZN:T>!P&6/7OZ0[B'[+F165YYKKP.>OC_DT!"B_(4%&(PR)RX?E4\ +MAT>2,NN#MR9]]/MGHGM"'SR7$RFN-U%#Y(K]2<Y7'ZEL3X`R^T3'D\ZU#J\! +M:E*%(U!^*(#0K0]WN,"=%EBG(?7VEIX?TUE_4.?&<(LV*PZBS\QD.;F>`%Y5 +MQ_U=PD?=.N)YE:8L1.XMZS.G$`J$(6;#+OP<^.:QFN4;>R3,GFD`:U:J?_EO +MJ!<A,:I,)%'7O(O9MR$XWSMZR.&P4PV7>2YS4;IO_2`]UT)'Q&M+[U^_HJ]N +M_FUX5$1GA*SE:_8$RQX_-+ZY.[^G`T-D7_89L,H>FC=>WSW%F8@5![*RAB.K +M0AB.M,U2YI@@,PC-[%:J\C@@>W%I<Y>3%4=DR%&"<T$Y8SA.L:X@Q<ZE3@BV +M1M939R^9]%\`]TZT7.R6-\C_CXF?NE.4<BSU:,:^:!(CIA9O?*NN-W10J(>+ +MHGGF_(T3N&)X-T4B#8P!TJC[_<KO:-A12O_\)M@XU7LHCCS_.#OF-24\9.1: +M%/<0IV#MJK)_-<WJ"#&L#,>>J9+V2G,<3J0@\]DSD^3DT$]9T1\2OM$PBKZC +MIMK0$!JL:V!W%$->V>F*HI2ND7"-PQ,F5!-/@;R4<M/+AY+`+`9/9FS;'D:X +MEA+E0HR\%Z3!%B3><68[5!MLUI#_;\V,T#&D.$O2HB)-I*>F0"?M);9:^9!5 +MG6C'3JKX@'>F!Y[;L14LTC'Z[`#J"Q''T-L(EZ_Y(08]:B</]PT_*^!"%*0@ +M1T'ZZ#PNIKDWF;+E;K/%<OL\9;WH&%K?&K0.?,.V+=BY=%B`4;(?.B2DYC[M +M^.2K=S/1XUK@VHCE9!H*;*SPP/`?],L"*O_7F">/P=?RW&2S?2"1526V]J]> +M@]\9ZGMYPG)J>;\#_>-1/"H@6--EL,C=T&)O^0S#GV%RPOZ:&]\NT<"S]OZ# +M@AN%?N$5+?,T=:7RWV2^4?[J5Y?(@048BR=9IS#9/UU_.%)-5\\T<89_H?(1 +MIG]=R^7Q#F?-U0--OO))J*VTN1!49&]LVJ#U[&"`.ZHD<&'B#'\E;G(&EI`= +M'0+5D36<\+.4]!SG%'\8HB9=?6:X'WC39J=HU'AF6U_/"5&)P9`4W.\TT[V" +M,X)PFX7XHM"AN^H0E4I4Y"G.5"<%UK[QEO?#;%L6#!0KE\._)DS&00861K1X +M1LH6]`34.(SCIS&LJ%YZR&EL_=5[FQ"G:]XQC_('3MT%*$>U$I6A_<!/,MP+ +MG:\'_V5!QLJS9Z,'97.U&-0N2_G=!Y;(CIH5G^UZ<1EZ6<$5`H:T)&P;C6$6 +MR=^R@VAUCDEA]N/6JGG?7,3B:8((JO'K6+4\1"5$KR$$EPTQWAA=K(4DWJD% +M9XP_-D@@Z_A67D^W6>8>IV6#I-7J[N1-J/@/F-.PMG0*,!;N`-0[UNEQFD(I +MB&Q)^_NG^A8E+*0NG&?6&/($6HYPGH;R2LY?Y\,E1'8QF;*?SQC;M>I9S%). +MUR#%<)GKO?$[^ND-DI=+5N7`Z5$K)H<50.BSBNB[C:[3#1H4*VVCRPCG"FFX +M&"Q1,GC8ZUJ-K!?K23P.@J\'Q.J";G=XQWA;HI[KFW5=+SK97*RL-%72#L$7 +M^1"#K8F@'N,5E0V2!C&$<22D.Q-P,J.R7[FJ_6]^$<0PKC4&,BG(`[#=U%]8 +M%G"ZC*M$.+GF$M($L)$7,V]0U>JV:K>),/M[>P'R^L'9A_8#NCO\QAOFOY4^ +M8%:=>EKWE7+NTZ>W2"2--VZ.%+:5T2R0#,L[G;@K*7#VBP7Z'IZY9S1\.CBW +M#.3>X-N7K3Z7A,'N((4.0*Y&>T8Z4=A6A\!<E:RL-4]5%7D"<@N2J`G[8%<L +MHO>?U+NOWP,)#5$,P,?.JQ9GH=D$G_%190E,0D\'Q$"0$PC\E^J]*AI1S`!D +M<*?2S)`"_'K'5FY**?B6K#>MU)&&C!T<@^8?>J4O>H@IUQX?@$-$SM6'WDR+ +M@E4926.8XL#]%1(N6J5!B@E27,Y(YHJBDV<6NGO7:JW`(<PD$3("NQIY6>ED +MXV=QHSVV[/<">\\,(DS\$*<91GIYIE/CN:Q-XM/_73+6WQWD=@RC?LXFKC5) +M\+S+:2$<7Q'U<S+/'H(^L,_/X*Z#B&N55B`@9>`2A1,P&)P`7$V>IP*HGS4Y +M0^8,M2YI<^M93A97!N9$.7-TT*N2!=+-;=]*D-(2-2U>=[^K#ZW*C(KMI\ZC +M`:B-*=?)4$>LP4?VA&2,K%W%;5@_A)WN6K*CI,_37)IY4=I0.'Y;JZPJA%9] +M4D&H6_,7*BJBD7FUF_"1)WMTBF#?Y]$G#]!4MU"G=Z>8HX--5Z;WLSKJTWEM +MD4^Q6\X+EIU;<=XW&WS/)*7@PY'IJW\NO0`*Q3O-#7=_;*#M@RK#7EBER8II +M.XP>R@NCMRWBXNOK>G5)/[S"_N`BWI63.`NK%OYIS5+W/L<!DP%5`$K46:O> +M>T2'?*J.6I[-8Y0<"HM&'18TA!K$U4@4S(X1('NJ1CJQA#.-1/<PL6IWCL`: +M*FT>:/\@555?]/)G'@*@9:%OE.1@*)9:?:U).I?Y:)!A1_SCM,A!N2M70J4/ +MEJAH+(1A.1Z#`['_DABT'<^6`!2)E:!5VF]6%H.2R*[<^`Y>P5(RT)MUNL^# +MM[E!.JU_+1#CB6)K>H8!1-\:,A=P@MMIT8MRZJ\5TE1I5#G[.<J89$A.#.K) +M:ELGBD67DYF"-7,*)RYPA[SQ]K1/W9P&`.[I@C._0&5,N8)CHWAC)8XFX^>. +M9A;?L0F!["40X_K<,1ZSQ:8A3KPW8?86;+G%D('9INV$M1V]^?!W<T1;D('! +MR;B<=6O(HHNV6/+-7W'K:3S@EA%Q\@DYI<AG:FXS<I_GZ7FI74."^$.'8R4\ +M^#4#+U=:=X1PGO;)$P+%D+W">6&1PK;O:AG>75L_<GRHM;=C'&?<;>XDW[&J +MF_3>?GE<RLT]D(TO`3S\"GR0=LJ>+4G-;I&2<6FI5_=.&8\)T]U#U$,U:2)> +MDIPF7`"VD<Q_4HH=1*4(Z\?F%IQTP,"?K:50Z.!-H7R)P=VZ.F">\W'2=!S[ +MJDD<9$:'"+ZKU#KJSJA%75.HF4,U#HA8OBN9<6X>."0K/=^!H)E=+;<,:#PI +M[J0$MVS)2<\`-S-!6^0Z*&]`4T,"EG]R)AE7Z#14_,`Q!BU*DK/(O9`N8&F= +M,<;+/>MZ/JDY*,HV[;^FC_A!M)54Y/)L(_QH[K;O@!CX;TC>#Q3G6B)1MQ0O +M5*#RP/VZA=^;'[AO;$BY][V>JQ]).,)R)Y>.3HL-O05&<4,Z>RQU.*9,V"E` +MU#CYW-@,D00"D_X9E>#.!%[4`U.Q/YC@OUQY;+S+?R5::">L50SE<#`PK6KA +M&B[[/?*><;)-%]G?ZA_!YGO$=(>2LKZ&S[D,G+JX_Z<J#U$:P,)F51U7%[ZG +M4H7:S!2V2:4F+6\20*J=ERZTG:@#-.%^N20@%U=9VJ3E#A&7A9Z(,?,29$D7 +MKY<[/$1IHMW8.$CE*SC'QY"_SA<.D;9)V.%/[.E9297J1;(G,M2T#QM::)L2 +M2PG_L2`Z[B_#SY#4E1KMS'*LQTI\0'IK=DH+?I(+._[IDA^?KQD#@C=O#%$> +M&;OO4T7CBAL3US:^HC8W5]"GL2-]*]<![92#@A(I@IX!^OZ#7*?O?LI7:^XE +M97?$XW"7X0;#QZ#*25D=[>L$7KV`T#?7R.#NU:GF=1+GS2T#.GWL2F=1WVTC +M69,RH>T#V)*2=-,"'")C&S(8#Y8^:L#C!8&(.7R?(Q`2VP0X/=]NJ1,#/<N0 +M6K]'I79\6+G_+Z7?'A]SQ/X.G!+."*AIE!4(Q60H?\X<V6[2G85$EFT)"I%. +M%<`/,$(NYM_,X4G^8XKP:Z&C7WC_-4^[^&T3.G#@4ERYXZ@M$>,MU?6I(<:P +M/K7L,Z;GB*K&"$`JANYHZF8-/`!FU)`_]5:H$>U%IFLU$BDQC+MQFGJ&F)Q, +M:@6?L<A3XU!//P&]DD+:"`"-YD.B/#.)JW%0+Z<PJ7@H#T[P&.K]#?\VRR^" +M$K!4*$JBTZVJ\UR;UNC&`595L`?U\F_457140ELZT80**=GY"UA68H6V=QMG +M&HJB]Y40G6V37TGHPZKY+'\MD:&4IR*%,XWU#[`U4IKL*V3M;J*+2,._1*G6 +M$0^B7+#5@!JEI9ZZLTEERK&^&@@(E+!(V$.6&OH'#:EQKCUJ0`4.-OL-D<GE +M<EW%47.>Q&M28W-QZXG`J$M5G%7"T05.M4@Q'=OQTJOPR'1]KN45FB+@'",) +M5O?(K^Q8=H5M)WQND]Q\-X`-@-JTO%;$&:?S5Y00\9_Q(+.K![@QW&.BBBU! +M<JM$[I[KU&@)4T-%/,:#8W=@*C/ZEV?6!2D)VCH8NP+^P)1!R,HBX#J7.YE& +MN"_0#0-D[J36)IPW.>#?5H5_%(#JY#HYW]K&P]^@A<Y]_>3B':NL+CCDB5;E +MN)6%[L+?Q&?3MU"G/85&A+1W,PTRTP47N9EQ<!P_S--?]4I#SUCL)_%*P/8G +MM-7Y['IIT$J<AM\VK\..:]AFN%?/VJ`5*Y(BKW#;S&-7._!#\X0\H_:(OJ`H +M'0;?T9+A"&S([5*J'XJ9*G)`7=V=5A@S$Z7"*3]@U:?W[>S`@O*\M\?_?B?S +MO/M3K7=D:L,2G]GY8";S96+?)^QZ[[V9UXR<PC*!ME#>8'\?U<R@,'>'M(TV +M3D?7@@-.N32I+\L0.D3)C3<:/&X:7MJ;T_L<^,\V1M>3%-I!J\S#E'JWB89' +M:.R"Z_WN,1LNC=#*12REAA2E!7#O9BOQPJ69N,>"YY-8=H=C(QDG6\"F,Y=* +M#IH=NXPF-E8;=,W_H)'I/V[',J/";=F!Y_5!G'6+\G[/\:.!;D*USD9HE*.E +MSA@,,8A</IN%'><UQ+6X1H6MDO!I2Z&\*`:H/IO<;WO@,Y:D-\,-'C^`(<R' +M$GGLAIHA,<`$V:F1"I):AWAU=8+,T9Y-*;ZX+BS#J9H-&[U*_:`!3K[E3HYF +M;Q,DP.@2-/'^!#S&MK\`_<2I^"N^"6_\$%I%^<@\]XY8S?`J3._'KWLLWWQ$ +ME]73"R12$?,7!.`-6!VF^VVB?``?]*=`\R_]AHY\976&0#U:W+@44M8K;;E: +MHT2Q)L[RVCF%VJO;S/3*W'I9*C_D@K+I.OZ801M4E,2%PZ>4*%E(VPJ)AS>V +M%/@+*$]A^94RK7YM9@:Y*Y6F#F=LU-/U<5K6@BD^B'A);[O(X-(Y=55U*Q_@ +MBH1\(O"'<)<%`AZ_/1W!<Q<LSWY?$F5V\FR3H/G$MG89:A+&4]A%>52;"<JX +MO:!W&3U;TN;Y='L&T:G";[-^6DL1_60)$V406`=\ZGQF.?'L#D:62LFHC/Y_ +MUNZO,&V\=0'@,6OFN1J*4CV"0TY.^$'B\?5OL*+!^&V"F\NX5;I]4YF$1U.9 +M0#6&`+GW%[%)?BFN*#)OAF180/G0LX$LQ`KV+(-9IHZI32QD_].)1[1!_WVU +M]C3_+R<:FEVP)[_E-.:!BW6<P*@Z/,DI;A]N#Y=!CUPB&,+:[4YGZ3=08FBS +M5E$F?>3T'<8D"_H^,8-HNOM457D[T+D.B=%),)DLZ,P,($MN(GB'+2QF@@H= +MF^YQ@NZ=6\VSY>#B.F?0>%SK,'#3[*7&X"`M*38`K[\=P6+#75'@SQ`!S#'S +MF?8O/5/@+9N)?/57!A=T<$%]N<)(7!EXV'!5Q`2UY>IB!"(1&\2<8^GE^$^S +M2XZ--73P;L9IIMS,<)U^KQ:"Z9#`2[;_CP,^/X@+C`.Q2PQX*4>;*(/*$@,I +M*SV-0*S'ND/HNG>,42!@]89DN;2UW@E2-F10=#!OVTY5K\+_I,.L`,'PM3BQ +M]S$2AV5BO>-)5%BSG+E)0?WQZ+F22$,!_[$5[,K!J+Q-]354B^HD`NIG\$L! +M`R%OH=#LIOP]9#/,.U@>NT-^W70=XO+1\0"3K%`@?-_M?JPU[.I6X+=>4P(T +M:NIOF.XI+%]Z_-+'=0`:H1NHSN4*9NW"GQSGC,A9)M02Z8B4J8%-CM#ZUVP" +MZQT1.\^_TXR:"S#H#'#7)\R9AH`+-&B;"&IPMLTUI-?%U&N662="$9Q[$F9E +M3=O[2H3>DF9!'#!Y?3'B3P9QE'ZU3Y/EBZ>BAUIY_0*7#7T981+\QZD9YPM' +M9'),9H#;Q8M/>N>B'17_>QKG[Q0S";^E4A'<9Z%Y\G"^A*AN\ZY#L7HV.3+L +M7)#-N%D$&U.JCRG77X%,3AK2UL0IL3X[\H)\((ZXOWV%ST2=0G6Y<J@'P:AY +M*LK;)AW'W]#F.A#]J0(:PC&RC]ZOO`N9W%'0JORT]\[V/$WU3\L:XIQ;+NV5 +MMYA=DL]N28N]VR;";+0*H&V[<.?ZSOZ.J!NYI?*MCE']M$+Y;!KV\`9K8YC( +M077-SU8<#N"O35SN9N)L$T&2A@`&&F8`6U[O2ZJO$1*3]R&YW3$?X<T-35T6 +M[51B[7]?;BI7V!>PQAU3>ZTW"]YZXXJ.))5$Z&K6!3YXHH/&6XI`/!9^Q@KJ +M;^L/_G6!&><2H*J`CW>(-E%*GG(2;8_\S8PV6]4IC'<F_T;`*&_Z3HAN':9T +MB7D@GO0@*(C/V&*&*F)O6PT+T,,D5L\1Y2ED5Z2/#>OS>EEI9D@NW[_`KZL' +M72@5,SR2>VM9/$8C^[J9+)V//JGX#6\'0C2"PZO-I*DD[X<ZI8&6FY#YTZPZ +M%1)Q.T8Q$[,)AO9DW#5">4%#)D(6<H:O.A.+-XX;4`5W+3QW'ZU(XY&]6BAZ +MP\E-6RFVA=WY`.#Z4$8V#Y`L>.0U&N>BR&<\F%9UK:6"S7<LD,(N):\+JW+1 +M$Q#F4\I(O!=]S2?T#6.QL9BW+F_VMCV9Z3%%"(#4[EY.^(-:W+:*(N<(>_N+ +M:[UUJW"3J<U%VDW[5EK6J$5CUCE'5Q\HN](%9-R%!#!G-&P*YL^/<3\1Z/&1 +M\I'LP#[#Q*\WQ`GK.0,UC$B^8^E.MDQ7S1L/V'2\:8_N!EOK?M'U#6-D!SL< +M9O'%7/B+3U/-_X+3(9],JX\&T,3!>O&\FJ;1BL/7(1F<QR.$-MY%&E-<+SB# +MAAFL=5-A;R<=I?+5>9T1L$[+*,$EA1KJS^A$0`>YVSF*1952=$*6W0/*ES^K +M#,KX(9=A/)Q9G--*HHL(W03<[EU%<W)<._G:!19+DG1Y!JD!+.E87(=UN-,3 +MK/]FNSH2IN`HFPRO+\"^86DGCUQ_=B\GJQW-UG`^8_[%`?[XK]!X,,I*P"OC +M0BFMYHUMYFQ#2%:/M;VJH'_P)ESW0C;N*-6F\Y<42)%%WIF:[<@.E0F]!P;8 +M;OGONK5Q]=XXU>`<>U'O9^G[D9=H;LDR>O!?#;3AT1$1!Q\\N!OY?FW$,S43 +M@-B<:_^W%,7``APN+^0_];''NDJ>'*`J2S"(11P@YW^51]\M)H!G''7Y?],) +M>]@V%WD+3=\AT-&0(`C'J-%+<28[RNS=@AW18/4[`YX\U7^Q3WG+5HG2>TVO +M/I2_J(;0\+\'O8WRP\5[`<(WLS*;]RY7U^PS,KR@$*.L"E_&PK84W:#6%?)( +MV1L,0T_3MD%JO+>OIS@MXMT!SF!.3]X;!>5[8GEW6F*Z8-_E`0B277/EV,+; +M7.$M-_%:P4(UQ+:6DH9J?#UV.BI5&)I8[63J0FXD:\EX/`JP<TQ,0(@:M4** +M8>M0*S*GECU/YJX.))$=D>>U%FKUV5_^;!S,A[8L[Z!8]>[Y)ET6X2Z$-,4] +M=\C5/!\QO`+2I/!,HYH;-[]5&7E:?`UA"R97&68XT/^-P24HXK4DR<EONTZO +MX-RK=GA"]R_0Q3K^Z)-K5'-8<9Y1\'F<[SE=Q$T)M_H`U%5,@S.FBWAU<E:A +M/71#FH`U6Q6ELR]7K=FO^*_O/+)U:*4)&@X7%S:DQ/W.0:&RRO!$$P$<&=AK +M?:*O]M>23--$'*V.QZD0YP1C<$M>LQL`2&[TR$I65A070[V@!S[5.>`+DCLL +M_\1B?,)V/4,9+H,_S""[,;2YH%]FFL?DCLK,+S!Y%^^X`^(4K?QLT09MZZ`< +M*;_'`R@ZP[6P&1>>LW,\!!DB`;QW#$1[`;OEZ>/FG>/$V`QH5W9+68RSVR1, +M=<=1[K;[PO7@]SL@[FXE+4Q`L.:)=<4`GDY_H('S(HK]<$[$R0F!:Q4`H'YS +M8:L@*)W0_/+[303%C*Q'JE+BT7W+^^%3Q6KC*ABO\:1E;EZ'K6/9>F%WT-!( +MGH]D_!Y"25KZF8JV;O(Z#1C7]Q0`^$,]*((<ZC:V`71J7+T1_<+7A]-NDQ;^ +MD/>X?4B!3&QU/30QM\^+-8I=''>]5L)O`1*@V^WT9L<0)X4=;6_$%^1'#.>0 +MY?#?D56D)>)*C;F`$892!RDB<TW:3/OC7;$(@Z`E`/_N3K(/1T8+\*W02O62 +M[@*LZUVJ*W6")<7(OK7[HZTD$1+*EP-;.NN]31(VC$@EP^-E@NO)LZ*R2DF- +MS?@F)T5!+#8*M^B/M[6M(.)UL3:`6QVZ*H;8LE06;A!A]^2Q]2JT.4'G';/D +M5=VHG]WYW96"V,``/IO7$YG3Y-I"3*Y+H?$X?%\3W;G65&15'8<[/+I:[!$[ +M;,C*4>[2"J7A3%*>646<ZCMI1TEHC@E15&(;.6?!,/BC'%RP5]/CDWZ8GH)) +M#5MZ6'M<=HAE$^:>`[RM.D0=-_''9L-MN00Z>RK(S#E*7-8&!XYB->C4538V +M7L`O+'`+=0(UL:*21N3N5^`96J9KG-)R:"9Z)O=#\VQZDYB#2ZX0S/XD7MP" +M!Y-)\SXP5<5_4X43`AI$FV)KM>O-9Y8IGB'11@L&QT0QUC5ZNKP?$'IJ]5A/ +M5OHM>10;TI?.%K9J0$Y^9V3%HE^Z,QDP)TU!QCM!`2"'TC/#8G,`N`0FL!$9 +M<6Y2HW&VKN2._7W#B96:8^VL1]Y+"6._-S48+3-_2%>T(UOK-JZS6^&;)1;) +M<^V&+PP\,ACY0BHYG%G'+'+1<S=^#'*#ZJ;L7+U7Z%,HNLC#%*MLH-L_HLJC +MXG0"CW25L@B@FM!;R\8+H1@HM/BCBU>,/!3@O_8KE]9"NH@<SF\<G7@#R=?+ +M26T:,]E[KJ=[`*99K+KT,E]RP:6>'KVX'R/JHXM?1PP73N&J]^?X:V2`D#F/ +MX5D^W?@D1+=I/6VWBNIZ1`HL7-$F":#CA8V)Q<?IYE(^RSR4C:R-.-5F@)!: +MV%_^MF:P)PEQ+N74VPN7&1P7XD-_VWX%AGR!Y8_H:!)/>C<C$_#1]@F=_;:` +M0FEL;3EL[/P@ZMURP:9L2CG;TU9RHAU#;*LL\UL`"_54['A#31C)[G<7$!%@ +M4_*S:BYXCTQS<5@1('JCP7[>\EZ%%U4D=)J6IY*]SI2#4@0O=6(QNFD_<GPA +M]5F6X*J8QUZ=X@.Z(%?Q"9]MO07%':#`B:')VOQVE)[)YA/*%B`HP$Z6>#DD +M(ODT#^V_B&)3U[BZF+V/@"CF5.(L&M?V^^1-VL#2Q]%F:3?FBZ'8S`E_`S5W +MN@H98PJ!#&1N[>9MA=4%(6\3;3>%&*VCV")=+V^@4?O`J"13C\X37^*Q]_W/ +MVH%A?(0$Q_MRMO?OL?<)T61SQB8ANUCT1;**F"[K.$+`V,56`O."S3/Z/_5W +MW)[,89R7F6%#IGP.D8^BQ^203_YKU@4&`B2M,G>!<SL4NU1-3AW"HV[[5[<. +MBAQD[#<CG2`;NO$$)7)_GYST/3*!=38,LD0&Q/9SZ'&Y#\L'J)2HO:G1T*0Q +MKTK`,C'R;@,^(A^'>'`%5$RT>[(RI>TH;=LWFY6)`GX<"Y]@80BF.;A=1O-6 +M)X`3#$M+[U]B%BXE$+LW:+>:\5,&0;85?X>]YD%IP@STP98+K5P+'QQPA6@. +M26P_4_Y,1OTV'P8<)7>SE69QQ8V>_YRWG]<AG4G*:,]%KNZH3%1G"A;%WX;Q +M>A!X_#O:I\D[G.O@8(TT.477X&JF0Q-I*E:@A0<,G1X[D7#0']:4`A;>SN,G +MV.9;R$69ZH4Z##<)/9VB[L0O_;-5B0)'^+@OVM_0;^;W'^Y]3JQMC;R?+11W +M9`?-.3172.4V1^&)50<H8HS+QI90S7CG@^_^[H2U8(A*=#7UL)=,IV@U$!Q< +M..&TOJS^'&M&O?+Q:H/GN$L`(/RW%J]QLPQG+[,Q_FU@O.KO;P%:V/\2)/(7 +M(1LXW(V5=_ZTX\?<"D@.&%2QN\5)1"V,:-H0V`"WIB:.X8NVSQ@,W^KM&DO" +M@`,]HQ48D=6\7)`>-$XQH5>`;P=LO.8D@G:H`9P_AX\\"9IB`6</X8"<Q#8E +MIO\CTU_UWI!OE![5#Y+(.@!Q5=W+TP712Q5MA],,<V41%ZN?H10C6D&KOH&N +M+V$C\R6OUZ@!ZX2K(R3?`4'OZO4D+/[2=_>:BDW4:F?XW,F5KG$-8Q-ZI.42 +M\;I%&JD&+X8W=DT-@=\!^3)*J4%?'^URY@]#=1J2"@FOS($QP3#*!ZA5F-N^ +MUG+"9?S6&B4DT`9(KD-%UW%8D*GE!KC*5:1UXU29MA4%?P(W:,WK?S!K[@_W +M!&4C)N).M6YE"->J=D[M_+P)"S>;6+'`7(S)T4/SL/@!31'Y3OT3++$$",'F +M:6%9&7[K96QVGS3%TAA"QTR]H-!R3R<1<`R<RP)YAV@H-`[+'N<*`)H+#@7- +M%7D&,G%*-YX(PU>2P'HOJIJV6B.7Y;.2]0\2-\:0]K9Z[U@,\]%Z:&,GHKLD +ML\A7S.D.8+2A<X8\_I'J^42HB71S&7]`":86:5H_9_1G+,X)%_3.$>(^@Z0K +ML!^Z;KY$S40ZH&U:_)E!^$3/7;QMLK9.=JD'Z=@_KET&#`6L?2SO]!8V-#2D +M:?RDJ?Q1#Y*0[R&R3YO\4I_]B4ON>O1SWI2/Q`0=6?\KU)4)"7F"H#V1%T90 +MD^-.2):=4C7='[PKDV4P.>@^O+D.#`;>.-8NE>"$V4KZAR/!F3"W$1R-5?AI +MT!3KS'2U[9T'B]_VQGK8EO=2]X.!7/;FHEQ^69:::A'_\QCI3;"[A&VA7/K[ +M_J.I9J8_!TB]8#L",NQFAQ:$D<2U2BYV@$Y?KP\?A!A.WIF&VXHE"L1I(/$B +MU*0U-&L4)26=KJAVU>+``[V&=GK?[=7VE5.J&,_JZ6XJ:ZJ)9^4TND5`W)LF +M#?_NX"A-5"4CE3H_W+FJ_9\>8^BZ4!6R>,]O+:O_"?X'36(U1X*)RD2"R:Q( +M#EXZ5NI**"5*:](0=JY+B>"A%ON2H+*'O7%`28-5!,E*R'$<#C@LKG]FITK3 +MG'GQ)W*%#[HL"GULYS,YD_#CAP`>YLO>HPT>GB]&3.8$8+4/7#TCR$QX+E32 +M146E#4[OA;VIZK'J*&)53/6O.QQZL])P_XFL`3-:`\X@.8<A-,,+XE84Q_!% +MC*DF!T=M^P++U?F<W6]X7MUB^S6E8^QJ<!61RD63O[V0X]B*+3!WNE*76K0# +MT%JN/]6R+00..'<HX'^5/_ICO:QU'QK5OY9C%UTB!R1/[`N:6]`D<L\-&SH8 +M5``2"2.:]U<]8J"#P3$9U2_5T@W.&IY'LOMR+M5'9S4A@"-<TFCS&7%)OL\F +MS7(@M&9Q857N<(1&=-XCP2]V[`U(L/.<B61!'B8KB[NO2RY_AB?4'IET?P.J +M9SS_F6&^W*%K4R>!^"UF6QM.Q6-U!I]?*!AF])>J%/B@6$7"M^G_L,`%O&G< +M/TR&L:/PY$/G=BGY62T3$:T%JS@ZU^B#[]4&0&.E#FX<)N0W3BQ=5D!0`PXD +M6J"12`?,AF>0E(ZNXL-'B0FG_@-HO1K*$9&P#I\D@^!6=RHKK.)&G@17E$HL +M$^^CLK=/:2(,8;$"UL^+A7>O`>QQ7N"M,//D=5M<Q`BDH!3UA]"55W0!=I2, +M.5)P!TX?AYU0(*)C^`8@3B"GX)`Y_X/^FC83',8C]:$?HA+L.EF=P80'#H?J +MI?=4!4=UZR5CP4/!F0?&S1@VL-:50+I*ID'`+*52FJT<O)"[V-U4CP'!VP`_ +M/'?Y8P:W5P-(!H"C''992NLHV]&#^E7AS=SMK[G'>(FC71'"6Q,QVL0Q#+>D +M+W.U\QQ(ZBYXW$[T6QIE@!F&HY!+3[/K;U@@='+!=03,XJ79E%2@*45Y$D#8 +MV)H''%F<$1Y/)K9O>B@F"-?!T;TSMV1)%6=19H^-7'R%"$+MO=#]+L1$L)%C +M^[+.SJ^AG'=@D;RN:F1DHDZW7:)$<QHT6@!PJ)LSKK##$'AXM_VB<44.PF46 +MJ6)E8WQR0^05`J=VXEI!CI*3(\V;BG`"I:M("*[832K0=<J\JY^_=<C.2\AR +M,&*%G7\N+6[<%\$RKZA_["^MW-J1,&WI60K'7PW;[D.&<818Z!WHH&H<+FK. +M_[R"?;X:X#DL<#"J#5M>LR+P^O]\):B$I/N?3[AJD6-%SO_/9#M8@OER,L7K +M_PUAU0(F7I6*`?'^.C<GU*.*1?GHV3%/T0RF$XD/#@)$Y<)GP77+*@(<K5,_ +MSP,C10_"&7'WZ_;Q'5J.9'^%3N9=F@3@KJMP^C1BTO/DP'\8J]EK$@.!A0,X +M?'%\^#81,B<]!Q>3MROPJRXM0W\_X`<?3_OQ$C?.HU#2JJ,LI.N"72".ZR#4 +MDZ3:5DF+Z"[02/JG-+GX04)R\0-#U$Z%XO:+LQ%]<KR+U434?_F4?QFSCT!6 +M!J`E$;#7)/+A%/''+@GJP2T!_\E?:Z@7>+\@U-E>J$&X>F__/6%/`2%F1B5. +MNU-G$.CZ`7;&-:8I\E=FJ;(P%_S.\V(1&ZV%87PR7S[>PM2J6S2"R%ND][?& +MZPYA6?_/`S+&SE$7[_;\`P7<)`0KY.'\W%^;$+L_E8%F!.EI'PT(#7;0C@R0 +M%ZC;9\=#WS4Y"#ZL?'U1BB&W#4&S7+X@@08T:\H4_,)XJ5_4.E[ZM"-X;%QN +M7,><F=\\X5'G)DQ-4MDFQKK*/[06-*V,!Z.<O_-:Q/\R"O-%@K]"K#32Q+T4 +MFRK`'79?4.]D`:0^3;^$;OE(2J8F*]^\?=`RS$2KBT.D::K^`)E^<0?B*FN> +M6Y$38)2F4KC%LY,AR=>MD9FR1,15A#$@=F!0F'X/J-+Y;`9X_("`C])5/\*C +M@,TFW"@P56L)H3+D43-&)1N%VM?TQ0K;YA%$^1:&Y'/UV^7"*[&$WX9T"Z7& +MZA&G_#+V=R;3/1N4KA^,/YT2I+<CSUK<TI@R[K7^-7+\=+K!2I%E.NKF1H[9 +MGODR8L64^:]<K<!-Z#I;>W*'+K&Q0LU_[';S8YG2FB)*2ZO9<.$.'!FG`F)Z +M4EH21"=JO<Q4T73IBZ@.9WNCP4<U?K=R)V)4J$0S!FX^42J=A9N-2R5A\Q$S +M*CQ38L+O7&U_#;L20I.B`#74(HC*6I,-'+]00Q8/?X!]?$7N#X+CATT:R?^P +M4&_]9+E[BL%_8*+M7H\$5KS+2-.?K%,_J^,*8/%X7CDO=!"ZF-*MLTJUY-K& +M0]$JHQT2!V\J+LOLHQ]ZV<KE5J;_H+G:<MU)G+4X"8EYH)V?A,C<*W;>N2SS +M)S6!RXIC0I^]!A&J(MKN-UYL_M.\6LF%!^()XU]O',L4.QAMP@T5),?G=?+= +MPO$>J@SK6ST$`6LF:!D`<5BF.(U"`B,%]>:A%EN^'D[TT47D!/W:="="TCYA +MC_B$R"7LCW2$=URHP>F<A&KS$NJT_'VEEI=]NC!X\8E:1]3/L%`NLVB8^&'7 +MV@J!V)5R3*P/`<EBV=`R+[+]J7XBW;R*!8N)ES%[0J/?,/*[^/5_CT<U-(!D +ME6.4`-;P=UMMG;,WC:(CP<JQ"RI[4*:U/Y!DN_0A(AB[`'0#4AFHIQ1X4CY+ +MT"`:3K%28V!GKI8'SC3SY!`K2EMM.;Q^*]_R-U(2&D(/^L3&"[L![3OFVT_" +MT0'J9%-@"&!7;/`L,^)7A!D#UKM;O*JA*AZTSD2@BCBB:`5CG05FA0I`!.+0 +MQ;Y.@_H(#8\]@`(#SL4]EMZ_L]^FJL9L5^?;X\7</<WD?',LY"&N6H.XNBG; +M`E$)?R[58=4ZYUUV-3#<I2A9LZK@Z_))<MF(PP[$2@J9U!%BI?/3SIK:8&[1 +M-LM=^P?L`=B?B+F!_)PW3$16_F,-!ZC9G.R*-[*,NT3IT%=_X,^SWV[0RE&S +M>=E)N;X\G8!I*1RT'*:H:$M<".U&Z"/=VHY]B"3:^4F2E2\]"_,J[F2=I[3S +MRFFBU-+,U82ON`F9I:S)7[\?S7X3G%GJ"[D@4S-4;%ZM-Z7?6R74&C2=H/V9 +MUE_`D@<OYDHWA*UJVXKZ^A!]1U3(F,.#9/B'[D6$H7@U]*_5IA:&>P)GH_0U +M'=C*24-=N>^?'OVWN(E8,4DKXE^*W;'"-3=1!9"4CPD_M<VW&"IK$$9R$0&' +M?XTU>?FK4[;OU@*J):M6K63E4@U^7)L<CJY^W9Q&'^&]7WKC.I/*=)C03BAY +M)*+==:*C0XZ$7<4-T/O!B6!AG+N3L8=K8P3'?!%%2\BL<V9++-HT\/].%@34 +M-T3+H+IBF#V+JDI8BE^PRP9=R`Z6LT(B@_>_ED350ABT%I<'9HB\?U_S)IM) +MT1(^]@G69VY`AJ),6"8>8(?A;C/8O=.8BB2&6=U(($=UJHKXR"=DE^3=8Q-L +M\ZA*]C<_PB;R97,.M(3V;8:>@1YF'T4Y-D68@0SCI+N@[,A[>,MS<-<O!_@G +MK!3X]VI#]N<!U4-AZG(;+N0KH_464S@QNE*<<K5B'O5)[Q^?6MYX=,>M')KQ +M)UD_SNMJ%JI#GMW410'`9DK?JFXVK:W_P&0C0'_H-UA#&*-B]X5]5F"FBQ,; +MV(1]0<"(!!IV">RBS&>=;D?I*>HY1I[S.^Q'0A"QE3>P!4)J-Z#.[?77T-"K +MOGAZIR\Y=GU5HNQQ'&@2/8R%Y?X]=":79F"LD85R"EA=M[!/,D]4&YX;6S,5 +M(T1K@ODVTR?M@=POD%7ZA=D8,A(.2@9P/P=X3(WFZ<+[-=MY>8<OEQ:+B0%W +MP=,1Z@X]8<(]C)N(%8PL"*!15C>:&G&T><&IHL:D-$CW&I<$AHZOOE&4WQ04 +MS4;$8?M!GIS-!_&CC<NV0NTI^L:KGU/:(-TR0+QU^K&>0"*.2,X7E-"OPMH- +M4H^?]7C3(J7Y,OW1IJH#W"X+?6!)S%M;>W*6_`!,2T5%,P)U4F7C&I+2&VPZ +MVGY%9?A)"JA]K:W^7HE38`_1]..F4R_:Q';8QITD3?^1'0.5'B)BO<NQG$P4 +M!'=V5@\@TIU9N-0D<F(.!-8RXN!PMBG9TP1(3$\^W3?.^DW#9D469+6_%AZ, +MREHI+]0.&[QP9HF1YPQ2FK<K1+Z>MD6;67!-./Z`JU3>X3'&13J:8N,J\RT% +M.0R1OXTQ#.H*X=M'_6&!JRW+T&MG`H$KU0()&8'F!A0=:'JF_R4'5JXO.#ON +M?%1VXC)]A0;L&L6/7-[0H'&\)MO7YV/SY90G$1ZG4'WU=D$`Y@/GO1)99+N! +MAH92L/B6%SQ`4':94]C/!MXU9VP2MCXNF-<KW%1^G4@$I)_WL)Y76&Y*(AAF +MVPE#KS(Y&3B,VXAUK/G4[O4%8),4LF\H%R-TOPK/E[$WN)3ID=X4$,C%C=X_ +MD[..R5QK;W+5.A!^D^C",KHI6)S25^\UWZ^XN5(R%%.=OOTJ+[XC(Z6CQWS] +M0&,$B/KO%&*ZU\-(P:E<;+G66;BGR9Y[',N&8.]NY7_,%U5(!D10!]/ESPT> +M*D&Y.&)DAGVUA$PR*1>`OHY=P1$(6%_5%Q\!3KZ$>E2_X0Q.BW?=@9+#11H" +M%APS@UZ0.$[J>*:44>1,8Q.J(*``AFL'5YDEKGNTAK7%/)FV^Y:EV(!$R>"_ +MV^>]JC+,OG$M'?3Y<7=B$N_-?4!7M;<GD/?U6:$9Q*0OA^5.@YVP-'9B*'\= +M\$C$/0_541E]::B\+SJ'&5[`Y?$^Y3<E36Q)&=];;B)^B*R`8^^VYLS0B=PF +M#J2=3MC.[W,44A,:4J9UCTE#?#[]_MW'M'E4"C9"#/.-[G>^7N%2QK,(FJWS +MVB<$:I<3"<.&$NNX%7:BC;LH@4]@?[MC-"Y(/\&K>I@V@!C4:188KHUOPZ*# +MR96+=[$SD"*@8(JZ6K0W>H<=#@*@?$'=8.2HU3O`>R1]S`D<>!"I&%.!&G!N +M\Z##P/M+W9WDW.K=Q.<7M@"()2\W]1H6E3,J5V8^%OB4@;K[&Y)<QHNRSQOA +M%)_0T+)L%-!,OUI08W%5R^ICM.8+E=%)@.JF*H<P&$ZF[OT;"B/4[/G5V!ZJ +M+H6Y,=%#VTB)!-W2)'U6%V.-%/4V;(.^YV/AXB8*GURZ(3KAJ!PG/+?G:8O+ +M5S<L(O2<AK/]:QJ.[M(>LVRB3!O/6FRQ$OJ\DI+H=Q3M%L-RMP]9VAW(\H^S +M9I8ARZ.9:/QG;F:<-2%+4SZH9#7KOH&A]0$]F(-)1`F%;)L2*PO]Y3\8N%U> +MAWSBEF8>?9RW5=Q#K\9\BY+-_-DD[:^Y0J:RY)5B.'\^6(N4Y'U[RR6S-E,- +MQ)/"6;W8V^=XSTP6P]DTO*P'.:_K:#&H";Q(1G_5&CMKUD$!#6C"9=NSW^II +M4X@ANL3V;,_MT.0WG5B1A7*#`O'7>T"N"=*C[TE0M(`F+L9''0S9[1@DB>7V +MC'6W>5DIN^.EYUP!MJD<TGRB,;B2PK@"B+?8//EB@CYT&UGR<4%4Q5(K@J[: +MUXHU96S[T?H+7)Z[*W`;WS/B+?GNBLE56JS)A8B,ZM7Z*RSSHW+\P/4I+_:_ +MZ'N<V;N..K3*U\]'DS^-:0[UPV_T$VZ>DOB0\4`SFEAPQ)PEV-)+ZX*.QKZ] +MRXG[F6Z=>(H_0?GB'GJT-G^99O(PXD>MNABWI5?R`%2<Q&S]HQ-53D2S;?L> +M,E.QUSMSV;%LL80*2/1D^CYV-\:'^'5XR_HG>E961&40!L(HT`P1'Q7D*H?F +M_]2^YK),88)]:D=Z`+:*]6C.3J@F7<M97J?)#2,PZ_?Q!5)@E]E`PZS;$'B0 +MHC$=6<G?50.KDTZTN2.ZT)B0Z)&DJ&#_Z3#EL?G)@SVQ>=8P,7S9@_.-&O.O +MF'92=*T6ZC86`J>V%=>&;%I(9=E)QQC1QWP,\_M5Y.J:2"KMR:WM+#,5K/[@ +MFBC;@P_NQ6P2CB[?VF`FK[Y!Z6_0QQ=ZW?%F)%JK#QE5TVC];I@QDE-%4A+< +MY5<G#3#JOG)$MGWBL.3^BDQ^6I0!7HBWQ7:C[EG8&$;4E1GIMZ?%@D]AA@1V +M-BJ+6(#"`=V:4>PYR^-S6Y.&O=[O7N:D5>Z"/((M9;$;>6@^G]E63Z)DM?I7 +M_!P7<!PT5`/=TI60)B!SB6(<%*JWO7ZZ+&IZ+>]%HR<@`5P"$D<UW.&^@16A +MNW`(T3.5H$8,ZQ6YM2&M))8065;0D+%0$?=WX;YUT85-"%4+`-E@N2+1"/JA +ML:"%;5:K^T_2>.>',8>_5-^VJV">#!E,CK\M)[!T<WPH;,[Q/G^'9U(:V>\D +M^:TIK'K*4QRZX:R8Q/V@T'XN0,Y1$'Z0O&Q15Z53VLR#(KX^D50WX]A`TJ:> +MK1)F4"E)8S;X].`A<K_[=YY\-"A;+KP07(2L,5KH[_L`A2=J[Z]@NY(<=M3T +M6>*O#L/"=7D'4*,%BB29\VSA'`T$>:.]5:%I#0C^+IWAEXB#SQ4P4'DRQ)1. +MW!')UK:HW3!P-D$OTSR&C0NX[9`MP]O5WVZ;6ZC0*D((5HW'NZIO?&0_D608 +M?&U!+XV@,M3H'<I?.BNV?4T'+"/F;Y#<#D`$&&.BX0:D-)44)D\!9".S!Y3" +MZL8\#PJ+:G)/%`RSRGI3>!2,TG)ALS$O*04XSOH$=$H0]S9MN-9[M:="I%;H +MI]9<\B;,FZ9I'ZT3C1M*R:5@ZX/`]#W-7_S6B,ST%DL%_[O542<MV>/'MO0T +M(+I2AK%3<H=7@N[Z-!B=BT#H+I!/2'7UWK$L[0U3_RXTAN5<5WB7*`&V9-`W +MBA00;Y=Q'3=0:"B2I+;+4;`KQKT%#G5[SQF_6<;R]XMO;K-BB0_9H=JL(O]- +M[,,L,0D]51JL@ZDO3?F`FW=!S@#J)2[)Z(:]A4(>5/KFS1M;Q_96R""RY8#H +M>6X^K0RN8(,_F=@!UUSBJ*8\KFQV0_3IM6W"N)S5E1OHS[I"?*0(?\E!.(IR +M0U!NMJ4:G_*+'QDYJ24'^%B<H(HVI0":K]P,^TM\.=`0@HP&O]F4*!:]YX]- +M5,W0WF$5OH:%"9CJ6)YVI$.N(7_>9P*G!084(+(XSM_R3!?_N*::%RU5F21< +M<-,#^2O!LOF/0;*S\\.N:F8"Z3+]D22]=!DW^.4/HQ@+G.1/PF8;`\0,GW0V +MW@G<Y@](,((4E'*ZD:S]APN'[P1<`PL$F@2>\W;,YT>/,A2P</H.D"?Q6152 +M_U2Q<8[E8^TR5D_X+NGM9S@KK7;^36W\^_'54JS($B$&"Q#5Q');Y]QR:$MR +MB#:JE1.?^51$<"N78!!*.MWT1AO%&@@#OXGL=E!>7B:YDO_P(2:)!$-)H+`/ +MMO-KDOP>"8I63Y[E6EG"?09B-B?VJ?3LR'8,)EB^BZ)F]OVLODSV9TJW%-^Q +M1ND]U`VW5^A(7-3A!P&HFL(#+"I=OD)78!K5(#DE8E5.YAR-?VW3A;U-S"M, +M%0F@RT6J-!_MDZ??VN5<<EO1(`Z]6*,AAWG8>59'&TZ\Q2;Z+3@5F;J-DGL0 +M"J6,X!ZR*/.\]4*?\,D4?XQUDB>P*$XYG;)MP5Q/%FJ8AQKD)O*%,VDF:76Q +M9T&M@J\A6LRK-D7F&ND+)+V9[^RR#:G-U4;<UC6`K?7ZEZ\CKP_+>+AO%'0^ +M>!:?%4LXS\X,38)#CPU'L)`%C"$?,I95W/:-K$?+G[TU<'0_R1+'+U2\8/,_ +MBV3>_BABI@0O6X.5=;&5]I=`$`V9Q$NH90X7$'6'LMP&W+PNV2*1H(+<%]#M +M#=6O>`-#1J`Y#TG+OK^84Z3@UHCG+J-C3IOOL#$\..0HCE?R1'#!1PB(J-D/ +ML'@<ORBV_J?FKAI)*4ZD]((R)?>_Y.>/:?^@,8:V591QP+PB;<(C:\PYJFT# +M'9S;^):-%\<((DQA0-3%)_1D77L1DQ\$3E\9"8R*4\HFQ+>TX%#W<_*R62*/ +MH$C_)]K&I\Z_@^2KOB9CLM"F&(!]MO"FI^!;<:)N,*"HS_57^$AWT'R-#N0P +MI?"\K=O5D+7,DL"@Z^8Q^O:?O5.16'&K-+"$7(1G$DBZL6J+<"=LL\>A;'/[ +MHABHHL"F(FY=8Z6TVR5%8.Q242CI"R_"N3^N*$9"7XP71]:FC'Y7FS<Z6PC1 +M:&B(2[CF$GO":#GQY?G6Q/A]YYHIBMO?.HK)O72RF*A9PUST0YT1.+CHVO<L +M_TN%SK18L8*3AAB4(D!BU-3OWG^^Z/)XUUWB`)K!LA;T<K3ODK_J47CSB[24 +M#>?ZS>X<N3?D]I<P(RHP@HW6B!3>9HDL\./43^3IQ7Z-^W^A#K(,&+@S,P7N +M@(%5BB>B)?>/1`]5T_(H5AF6T%%//.Y"M>&@GM-]]0!A1G)7P@>L=.J;_WW" +M(-&FG%8H#98G]ISO>S64<.=P'G=?B/`7%.[22M\3,?^RBIKM_:<.S2#@=L3, +M4)X706S*G=;ICH:2D&QW:?T):?-AY41"X>5/Q.K,8G^Q8LRN&)S\(A78\6@- +MV.'0:-TD8"DRD*??]PWA+(MUQ<ZM7)7=6-/5307BW1JX.$)F;ORN/5&_'46D +MHXK,5=;@CQCX7)YL4@%<%`_,ZMH0C,OU\9R#YT\EO%<>!E(>3?B3_Q`%8ARB +M>SV[<R.!BU`W,%P&%\M!$T>Z-#K?'$MGX=Q%GXAI<%^[R'3*@\3O<K.%?SLI +M`M<3?T@ZL-ILS;@-DM2(JZ;I]CSM11QG4@WD@IAAV&"L[3JHT-OSW-%<2'`- +MS-9*7@I,A)Y4JRZF>\\IR[D01Q-7DA34AE$EZ.<`GW&O^[MV2U(1'\:8+G01 +M+_K5QE,G"5P)6<H<'"*IW&<V2#4A*'"(->.;.O@U6N[SM[A7=/CYJ2B-AM`L +M=JHZ[2*5\RK4R#6#JNPDQ^]0'N`LLTSP5BN-GN[`KFHA?4J-V&O&O3W">1:8 +M[RRU1KNVE3/(L+<VI>'5"#=@.J3,]U3#CMRR'*RKH!X#TQV[Z`%S'XIER`O( +M>(PV,.S]>2A$%^-PGHIY=C[N#IQ_DXA[@"UQ.NMX%C*<QQKQ4M'R(VP!8"%U +M6&C9*)FC(()>]NP?JR[0OZ"DS`.^T)06S-B!O).&.Z-BB,B_=XA?X<Z!;G$G +M3J.:*IKBN?2C^^X7ZBF3>EOQR+Y06\L0*-C`_*7BS^OL`9&FT,Z%14DXK='# +MZG[\=;VCJ?3WTIE*\!:TT4CAM1POR>2W#@:PT+O<$K#@]&T'8T5TO(6?NAEF +MY7MF+3+C[O%AA-6/+!N1Z<<<OA7[.AM&8];79J97:?]S%L*\'(P8GK`2>9## +M#H=,SRWP)\/1>Y+".T8N((>M`1E!M-U@F_BZ=M1`!^"51Y0-@#374?=5SB=, +MS'">9*GE@MEUD&`B+B=JL-W.J!ONUD/$PDK6*\,RJ$82M00+)M=R(+RY#(W8 +MA&;004A+[IKMC)@QZ-!::Q%N]0T?F3661.]Z1G&?%@&>0Z7`1.P?!JB>GTC2 +MFT%W@*8*'HO.ROR@'B=I*NQTF@2Q\_Z>@3^>6W_[`BP$HV5%L>+]`5S]5U-N +M*I1]^5=`V"5LY(+\)1(VD@>DCXPEEG=[UJ%XFZCB12Z-?^[XX"@O?S*%A='U +M@$VX$Z(F):?R4W>@&YG_)H&E$DI9[]-M1`@(T^N_4DS(FR:WQ*X3P^;&<%N3 +M:;CZ(,-3\H/H3Z;,.;',&+A,'ZE?K8+784'P.L/&'RG8&O2&->""M625K(3J +M"NS/';DS*JND,8,"41'OP:421S9!_-N>Z&]^RX]TVH,B[49.%/F<L8!"-64# +MD635H58I$Y0,]1%S!.T_+;MM\H3HMPG/14S5Z1UL\FG'*(3#44J%#5)&+\IY +M@K?*^RK*^'(][\DJ]9)VYH$$WR\6.#_!)=/[E<I1U6ZFRK[[LTB?B07UTQ@] +M]:%R-6!2J<T;KD+'7A=B[."*D.9?]4)CXX2*44OF&F=4Z/FMOR%JM=KJ7=LH +M.P)\2&ISS7GP>+H=(TT8.@WJ&.Z464;WA?;:)O]K'?EH.&4`"^P\,K"[AGH; +MR_(0OZM7DV'W130*YO;&Z[5E1@OKHC95D/)@655/[\G9X`:-MJLF$/("[_>6 +M*'QN_SP*1,U8<"`1WXG((>*\:YJ=C-/7B`7(ND7^4Z([1&M5+L?@LN<4501I +MG'-<2L_L+C@N\FY;<]P>#AHQ5"`*>ZW`7T?=O3PO0#/K/S11(?)?B+1X2^'! +METN]=[-P1@!V\,#4DG5JBL2LGU[4$;,HC2:>`BD>Y/YN>*+_JYR6$Q&Y2A>^ +M8\_\K:$>D1W<B"46NLP\COZ1SE=@L\LRH,9:CQ)A`_E]:RNE2W#[*I1_#CUF +M^K8G@.H"<T0QWT@#2")[H]L<3S0HJ(!F-,I.Z:^7&PDV'[=Z]_%M^@+O"2>G +M_\,EE*$(H%XI&9&Z3V'*4K+,FB"3;I5/];C$;P_!Q1&X-86Q50?E&H_Y62/? +MM"W7:?Y^J-6E)5@NV[VZ0;!YH:^H+MW7=E6O:I4Q]1L=M8Y9XK(-&HJ8IA/" +MHFWVGEJ8=8G/`ZTQU;M*)1O#2/(D*+=R`<CI_1?S((E63>MOU+P,@K6N%;V, +M:7_E)"`D6Z4,-M?;H;`LC=GD@F>648#:_57\C]6S,I23J2?,?3AQ:C*RNJ8C +MQG!Q$?ZH'W^^654;E)`53_/X0#PRU-*<D-FL>6-6YZ4E/2PHK,LLY&.-,1R[ +MFYEY_#H^FIGA^7:7\WH&PQ1>/BA[7_5]>6LJZP(J.DTA0Y\@?![&&E7[:=^. +M%#@N;7]35X0<Y6OE@3NV41>Q&K?[FS6.J=_N0H&"-W5*W0NY.NMV_Q>0S/2) +M7ED(L?1Q!09--DA"B-GZ<A27U-+.SP3L:ZA7OU;>75B#_\<A3G?PGYO<8!+B +MFXG'TJ"?T$5,'AQXTF,0?D&+!;90$CT*'KC5.^^,HY*/KU>Z1%Z<G/H?-^6/ +ME:Y:KJP=5'MI4@._BBR^NE6;ENS^H@>(NF8"74*7AM]BE=+WYC9SLB#;3Q=O +M62O7_T[[44[:RZB),ZYL&=E,OA2=N+:CXK8#7X1+XZI0$X8KRL$"_P6UACQ* +M9]HV\YIPZC:Z,';1(GB#U$XC,B%W=VSE1F_9%RZE!N1%!#&(%1`:AS?35'H0 +M$NA<Q@*H0T)NTI03."US'D'3E.J>K1SG-";/U$0W#OH5ZE;!##V`NTY@3A,& +M>=&U9L9XXUVPFZ1:QO%L`FK;RHS;[I&'[=AU$\U/-K8R/QF?*%2_-X2_$,HN +MD+K4_K]Z1:UJ$;\`HZWQL7_]GRP<L4@["EM<M/L<"T"8A.0_TI8T)>QDY>&S +MFL_['I2_N&DAW)35R'+?24`4\>K6J1TJKS`Y:,2K@==)XBW-F7>]CRWCTV)8 +M4'2;96(,8BF%HJL8[JHD9>%IT;(0HH%?`FD6X\4"IG!WAO`E++*2R`HC&(MC +MKFLRWU6'SL^N('%[R`0C,4FHIANP823$F;&O$V6^Q%4*O;I:,'<I$IS902K# +M6*_9J3-RO%)B=T5EAB?HR719"'PIWKH$9BO5NCWYY1=V9E.[P`\XOY9,![I6 +M6WKGL,U4C<DE1\#'=HC>$3==)F<M8\*DQMNX&]AEFH\9*%B!:N54EZ#;U%+, +M$Z(E5X]I(EQK_V-*%DENU(`T^-M7#+BTB)N+8E-D6[@2FW)OK3EXA!UY`GB* +M$DK/)E\UWRU<":BQ<ZY4WH+S\C("3-B@9A/3]CK#Z.(7<*/EZ=F9#\'>"9/( +MC-E09AGA=#U=&Y_%,'BA'69+]H%B4(MW-#QC:/:^'"&Q.1T/'/MMO&WMWQ<% +MW$'5GC:5T_VG"-HFQ?HYPSY@4'YS];)&W:!QDS`16J(&;5TLD5F__O#K_?4, +MD1=PV$1YNC`YYEVF"4NZ_22L#5[.<%R0.YRB5VJ>`K,$AW!NJ2]X_/*$DFBN +M::2J2,WME%];8GW=IB6?@31-^3(@:I4$%.HV2E,3O?TL9V,^Q@6C:8/GNC(* +M\P`MQWB2U:::N<%!W/NDBNK*MW+6P33A/WJ;'+7]!%FLB/%OKRHN$3IG7+0M +MT=,:+F\*J]J5)%\33<-S5@14-C*V*0CY@!I`)OZ$@&M%"?&<DNA25UCD!AV& +M*J%RJ7.WL-Q(J.-TFU&2Z0&CK6Q._.*$UFEAQ%-*I'Y:W_U!U$43<[D;#"-S +M$7JVO[2)*5$>ZTKO,R\]/N;MXE]X"[R'Q]9!ZFS-0GD5CN!L^-DCJ@"0<8%0 +M<-BV8GOP3#F,W&9B;F`%ER8@/CNM[&_^M320J<I.<XRE"6]"%JHTKA,M$KX: +MQ+MG#S[TC8&SZHA;P6CO;$A<YAHE@Z6H*&F7%9SJP^\;,DEPC;*=PAWZVKAK +M$SCI.W-^1L>DASYDEG"=_)<+$!ZC[\8"8\H8YMUE\[[D#,E8S<)?E!45/F\U +M#^E6\RAVG3KN.6/[&]I3M3/9K_79JE$]RR2NRAK+%D8ET0^(FKLX]?O$.S\K +M!2YZ32<5"U*VSWW[^^T[C28)2`+]9.Z63E2.Z15F7P:6$GUMHP"X9J`(0Z=; +M?!)IIH9`E)GIP'\P2N&L_VY*OXT2/RD!5B%FCNAU4F(?[4IG.JYC!'2@J;TI +M\D5.J]XD6QA<?">\HK4I^;:))8AGW]=@+>$UXGV*O#N?`JVW:>:CC:+EV\+> +M./U=%=.^H9?&CW-$!^1,.,"_:B62C6TR9L#F%L$T`U4VJ^Z&/RIS:M5^\7YU +M3C4J>0%#OWC?\VBH-%(>>?$H2NA#JL!0F29`+8&K:\F&#SFY,*KTZ*CWSTLP +M;DA:5J*].(OI5VN2B8G:DKSFXM<H1>D8\?S7V,.[]IXB]$=0D0[=;I5Y*&O7 +M+0SN*LXD&S79_AP$ED/X2L!UYTG2FSULH@E@&"6G3G'L])I7Y*.X&"6#XXUE +M-D\G`3<G"8BF0I"P&U86V#5?8*V7)29]?G,1R4A1RZU7N.["N5IF^Z[.D90< +M@`A_V")-OT#%"-*X@3]%)72%AQ[?W!71K=>DJL$W%=PRMD"$0+6$(CQ+%9I] +M-99.Y-D'%H;Z"-;#TM-BN#"9@*2_"OKC7&SO^/JD]>;!()@O!^FIA6LAT29I +MQ12^)L?L^=^M/=0<C"76K>W/%HPE?2M,R#%"0'QFB8Z4D%WU4-S(IL<^G2K/ +M-8OL*Y=6)VQ231]]>3OV4:%:YE/S+RPN-SMM9>,YC*Z!4ZAE#@0:09WY7FG\ +MIOK2H_YRP4`C>UPY&TD<)ZQ,L'7U)J)_R"7\$7`8;Z>\/W?;PO(U9M6;"3RC +M36_ON>95,DY0$;\Y><G05T<OG>@QTG%IX:3W,U>D$GC&QC^2MI*U4+&Q\PLJ +M"#:0H)`1CQ@TDH+6DB8*P_]N9X"<MCPV!_F'3@%1P)$'72HO/`/3RC*=ER"S +M.\;5A9K`'\$PZ6:FDP%3Q/Q6TZ4[@*]3#Q`1[_0;;1H,300=(*[3OHS)7F/2 +M6?'YNN:CKF'D9T]@4_\5^D<%P-;<`J&(=:'_=MM,34ML!>((AGMT>RGQ;<OP +M.^4`UY8_;I<@^M"9'7?Z3E'_D[[V`3/@&F&L2!ED]^S(16X=5"VM8V'?!-AQ +M):FDK0,S5V/$=OH@*Z[SL"8+.:/`(?M)/>-RG/-YQUDP,&$6G+`/ETA4[#C' +M_:C,,&G*D3]5D1:G-/K?K%'J.K)L)6)4KB,:/*@8K%4N+3`!]\&S:3B5B$#\ +M]<T,PQS)%1";)X+52DM2ST0SY]C,6ON5>-Z_AA%'E7R1X%CRYHR`^J*XTDK7 +M%)9!L\`TL;$>_F"MBD+-^PD:X"9JK=DL+]^QBBUX`8C6R_<W`0X?":*'=>]E +MM/\2*,!EKJ`E^1E,&)9\CT'5TY@(_1*]BKW`^+Z9+!++"XX;OTQ^5M57>"!6 +MU5"T:7J,T)<5]1A._9]R18`W1?"W<Y46=5LGDUU6)I:H3Z;;OR8)6"M%G?82 +MRV3[FPT!9ZFQ!>@1.(,`2R(<O=.<U4>11VW=3MEPMX^)&)S_`P-@IZ5V%P1F +ME)FR]T*M@%26Y/B;Y:@]N)S5'!/\Z^,GIW(B/(%0XP5"=86RK+'EG6B&_V[\ +M&FY8OZ;8HRJCQ4@93J$+'[-&0`I&?VG3M9&+9\P[>G&T*`(:)(M\/MUEQJ47 +M/SV4-[=ML7I#[0/1)_JT;B5'!I54E`UP8`E9+*HWEAE:W@E+LAE+-OV)8*+Q +MD->.MU:S2L!0*0D1#SZ>#@M3AF#+YQUWR4^3=MSA[HEP5X3KO.1&%&CO/^I@ +M9X0LRWJ;P]T34T,82&ICSN-"G?9$X27A89<PZ:PJ5"$=[K4J:LTT`^D"ND.) +ME:'U6G%[>/*-?F#J_OALYD.!NO55K<>GR\AQ"1_9A>-KFUT$$9/D.^V"/G_5 +M'WH/AIX-\Q9RKOU?@6Q*FS?//`KIXJG-]C6$7MDB`TE]4H9:4%[`.O6-)&RK +M97_+YUWRD90^#JL'J')4&5P"\1%0;S?`=X`)&O[W$,D#>9D.9SP&?-`C-:G8 +M[LG?P(;52);:3AA^]NIEW0E3<`\OBG,)E70A^H/R#K>PU%W(!CTSV4<&#=LO +M_(56E>0+QR=P,F4C'XU&SGV76PYBMV#W2S]A+O`%*M,17&91NX!Q+9:4O:3# +M]><MB`#MH8W4DF!Y$RVWUUXELQE"JRF"L,6Y,.,F5JO2<]_9FIM(^O3SOYCC +MX9W\O.?LXEV7K1O?]*2C+V&5N-S#:XL5]JQ!V03I8RFF&$N`\E;YX,OLO*^_ +MR'6UC/=L%@*2PN306<_V.?_E/XYKH9V!$D"[W=]VJ+FKI_7+B7+*4:WAG=RD +MKHLQZS@D4/3S6&2%I2G6K[+%;%BIJSGZ7JI%BW_]O?_W;'!H-2Z5`DN=K@]' +MV&UP&)/W5>^BI+X0&B#<OM"4,R\S)C^9*.AY7V)LY7HR(*&\J5^8V5L[VUE^ +M]//YE9AQQ2=-=7(3J!-&6.L(NY7-1QS(!Q2XF.\G(;-`B@6KV.K:J\Z^L?_` +MH8B\9(BKJRV)EL`=6N*)4/_%\"BB)P\+D'8N9GN(4=+CWW`LAY7P@_MV^*EJ +MOTK#&&=A!GIG_5'SI\-,,_^<,%>!E8(AZ%T6LW*/[>CB0W4C6T>ZL8=&82@; +M,8V#\))%0V5EE>_T>I`8O0->M25!H,K&M&)3C@T+>HMDKDS:U9[8QSHN_&!" +M/36(*RN@=MV]62=U5QHF+D`19..^Q<0$?B()CA2DWD>Y-D=$]NZTPA6Z%KMV +M*0TBSBI88;,EE9(G)9RT9S`\3,EZR,TB)K-Q3-@9GP*`>9\Q_@=?G,/F'I:( +MQP08]%^J]"X*B&LK"J%XO5:U#2;L6A5[QG'X[[H,_Y1]0U7DA$KR9+:)&`/! +M"@0B7*0`5YTZGP8J*?=370R3CE7-@&B3I78"H,E4$O['0B$S&'`7*2_-T[(L +MMEC5'+_:NNV(""=,@/LUQK+)[%0#&9<9+]=N@""W"5T1?7*=>'*-*FUSI*PU +M1P.IY1E"_5Q@V@/!`XS-4%)\0C#7PFN\7LF(D_1=F2,7:BW9`\7#,(NK(@D5 +MF#\?[3R&A:C]B_KL8KSM$P"F(@)^7"V2+%96QRB(UHD66C!LQ2"/EUR+2PY$ +MIZ8AX]A>:XN9/@CSJ^(3"L.Z)TG^K9R3W<U)+)%37"(\/:E^QX%#T5;1RMZH +M.Q:J$$2N9&AK*$();ES[AI/4MFOPY]RCQ2.D18J:TKD@;ZVRYI;J3,>,TW<@ +M>-%OM;`;;<")TL(LQ70>@"Q&8T%H$UXA;A.*V!G0(GE7!6M#^\6AJ+D++\%D +MPTM\<Y#B%G*,C9)>6H_FEJ?1'O�G1Y+BI68*,]$$*M#CF=E2+*,*'RY/>( +MHQ200^7J66"-;+C]23^WLG\ZD>B/X/9\;Q8YVWF+I-4.MAG;X,I0+8GLLJN4 +M(KF2WI[\K!$";JE&N\Y[LG^[^&U!:C<VB5Q`RF[53D0M8C#P^;CR%Y64M"=U +M;D"$KUP*GSFY1&&A(W@-O5#YX5HTQP!@'O]0.K"OT<LEO=)@!-F^JL3T5]\N +M3_M=_95$E+5MR8,A8I_GLL!H_GL<E7,?;"#\K79T,D4=#87-%W>AYX9#XWE[ +MB.R`N#YX,4_KA<?\4)5;C0.60Y$1V@%4)$<E0R>*-N/!I.5DC_\9&$BWOAY5 +MOQ'&Q1B^?C9WC_9:-^\G$I_H)'9)5RLYFB`<P#2&P:7F5XN-7,@T4D1.P4#M +M[2RDVS3>P_[Z0#Z(KB&<:72$8X8!6D6<_(([-"8Q]Y5E6?_U5$RJ"&X8&W_^ +MN8LQE*WVQ^*)AV%!"G0EJ*5_!^7,JG>'@F<&IG6,J$:O`<R&X(>'G27K3JU- +M4!*BU\#F1NCZ'A1$I*I)?X8)!?X&B\`M[`>G<U35N?3,>]8F@8%BN:"@&^FS +MG"V@]8+6I^RW<%Y9/,$RPMN8L[Y,[QS\[Z)'K1!Q,T,;[T#S\!$RFM"A#J7, +MZN4;X-#M`VI&D[B*G#1U^(?V[A/]P%(%A8@6?L;7,[LV<HB=M+>H)1[/+[FB +M8PRPH*E,,E;Z!G^)+G29WKC@Z&R/>IQ$!3=I=@<G5TU6:>.6_32>9^,61]&- +M:N*G4%%L=C(<3SZ+G_)UT1^<PB=K'L]+S:(-]7H7,ZF&D`K)L'"--`"8G3C( +MTV39(5+*T$-<_["FQ<HUV7V=#SN=\N]YIVRN@T8<4X"ZVDDD]9,)M6]FJC)< +M,`_3^=M2CI!A`'TFHB*_?X7>'M+M/1NJBM,%U-YGDF5H+6M+_,(]-!5T?K4+ +MO/(8!ZVV\/<+\)ZEDX@T[.L43C5^":7YQR;X8J9KT_`,:.@?Q=0D!E-N6Z`, +M,%@_K*F]Y#,>0[>-TG5`;MYP_6?8"P;*XPU-73ZD[_FCQ?.2<O+0`;I."7G< +MW[D)'][(6?,;,8W`(N>("LI:`9:EAF7O]`L$`>J_1A#!M/O.K\2MI"Q5"#4$ +MA7D+:3960A`P`0U17:4\U;<A86I8VOOK$^/+@!-YZA[[JHW#23`IRKHJP#V` +M>PF6-Q:J%]-`CI_:76CUPX^NN[+5$5$[W>RD060\$CY^WK^8,)'[Y2:.OMS' +M,4K]8[)Z;K8S\L+:JC#R9S.6%-DMAJR`'#(U)C[1H]?LAR!PZC1@$@,\7^ZS +M*P)[$O0>,'N=D[ML^/<H*.^I(D@YGT$Y`)G^%+\$2:E25QJK..5*N6]DUURJ +M2T`I-?:K;.4%N"T!5'A8^GL.+2*?4D)30%"`MJ#SIX:C&OS<;M4EM_"R?$@' +M]#$@^K4S[(-%D._;]^(H0!H*PU7S$2>GM4:QY\7U\\.1$.9<C+O01@*$F:I8 +M@*F)KW0?KR[LKS..-@YSEF\HP\@_I>W;M6V?MZF0FSSPG-)OKFVGL34)?U\: +M`$1<^'[$5U3M3ZAT2.\[D]B+3<I3"-XD^#6;,@7&=-(1N%OERH9F6O*"MV)! +M4G\N#X2:B1S#Y>(R;0Y??"(;WSH[?Y/Y`F-:ND!CGZ:GE!ZT@8!N+-PW&ZVM +M(#[=U1-&KQ@I([/]YMMO-O9!V>#70"%EA*E[QU@!T*"OC`W5?!\%VL&DH_AJ +M,@>*P7%@'Z6N0?COQ&?W0YPT0WL=%E(#'\"DA@M.DA@<=E^(:SK`.VJ'NNK1 +MC>(8R'?U^)[E]B4)D`%\6[:4^S:,(]PK8XFEQQ'@Q8G*56^/$4$:'L>[87I* +M`91M487404U&'`**FO((^ZR&G>Q,*QB9ZTF92<</X@`J7TDD.^I9SQ6SNP9. +M!"Z.1)/GGY\!)SD5J"ZT?1L:';8%BIN''DRE:PMVJ8)%Q!1=+?L-DO?7<*+G +M^!*74Q-M%[HC/G=TT7GYG'6<&&0['[C48TU;41PG]OIGKRMX&=&`TA:S/Z9$ +M/)SLW#K*S%0.C5&/834P@1WHEWU^([(;TE=*C\-*%2`U&VR<L<LC([6DH[KO +M4833I.DTP)\`T'+%M`>CK:`(3:YS[%PIW/O^Z,M/(N2F0P>U[DYL@2?<-- +M:]7_X>[<6NXMZ-VKI(06U&6FUPKU-3;70_(GS&.S^=V(VB712IO$DX25\B!; +M[?MIYG4;/`D@\1?"RAR<Y.#)I672V--2$(.PO%0#4MM`*E44-H@E4)[2L6=% +MH441QGBF<#<_/>W^?*#_^T%*%+DN:FA8C0M.#ZRF901(61EZ"2-W!QR#3\.W +ME!@`$X1A"@2E`\$'/?4.'[&[9=G6'K,9%T,R9BL%&D)(%*L23'JX0$E/TDWU +MW**\7%'JBFY/1,`GY)I1I$3@JZ]#"KGU^9I`\3Z0"@;L1MC!V.2R5R.DM8ND +M<>=J^R'V[=Q5/V>1$$`38(`N3O.77,XTS9EKLZJ:/3G*%QOUEPD&FH'H<2DI +M1.A*RQA'J&H[\:Z1.5N4I'P6$YE%N_MQ,>F2RL_XB;\L>X25ALW?"'J)US9N +MMX,<!1Z+O5ZARBOD?6,Z@,,3,9<O],D2%XW<_Q6>7K&,8PX),I@T[RDJ`D35 +M;4`D",=_Z<]7W$_CM1Y!XL%(<$0NY%<_H`>!7>M_0;AYCQ#=3O,'`(RI^(9& +MBT!\NR/`<;"C1[/ZJC,':%/&ETV(]C9B2/%_(Y$J/:%YSEY1U-SZ-^X8A_DM +M;WGNS78](Z3:C@R+WA@(4[HVU\XG9*,<T%XV'?<'Q#A[4R5<8TJ41`X;"?^6 +M,M\?XVA<'W]IB.9^5K]%.-+5VLV\^X.T%YGL-"FTA#F6MR%G"%CCML$KX8J4 +MD+92`4C.CLI6=@?D>XLM5-39(QO.OPJN"+_PXTTW/__:$#\CDV\NXLP`436H +M:'[ZI,CBKUHSRL]UH6A^`!AU#WOB"DY'V5K>6&%AHJ*3'XQ?FRA9-PM4:4K5 +MAPX;#'"Y>VE+1#O+6*"TFCO,J)\]G$1&42:!E*A4!8*%>GY>G]88[]ZY#2!X +MFL_]7G7C;,.UZ(6L)#B!\(B%?VE)NV;N=B-3WYR7UV*74<\NU[J>'Z#4-G"P +M:`-BANB@/69\0-3^F[OQ&=-IT_\0@&UUYB^@)-9V^L0"C0?/11M!G2_"X4Z8 +MHN8^(F^V+12;0MR_R#ONR/5+348TO)/?0:$X#;L+4&N-UC;+;E-8AO:'5ZO% +MP4,B*,'*DI&M>9ZR=?*RC[0JIN!#_9U$+:&8VN,?Q5"Z\>N8#^V%"`A*_U*S +M:W1SUBL\Y+W13YU;):+[D<)[30YMV+9#ZDAT9CZ$P`VV:IUN"5P)4[P_GS+E +M#'WG#RE_-G(FZFMIG&.B0HLE$NVT9HD4'-JFDH9AZ7T;!A]Z!EJJ2X$F[P*T +MQD/K1!A:!G`!2D$'+J!2K8&W"K\C^$S7Y,ID>Z;Q8HMEX;E50"IMJ=H89&.! +M-R/5O9R$.*YU)X)E7)^(Z(G9-+I#%P/$ZS)9\\EQ.O77)&C.1#:Q11+):HY[ +M:,LA5P'A\NJMVE6+X?.R\!Z>>-5E\]J\3+8]&EVQ?IR1H4>=CX$\C/1IN-`+ +M>SVQZ"ZL#)M_VPY4+D*QY\^\T_->S4LY<+U^R49)B?./%$N]V"GYJFD90#V% +MB05\<'AK0YE'`(M=W*8_=;B,N*KSTIV*%D'FQ7%0`AD1>U305+6?))C7"`2X +M</=0LP)<"$="MA4&'?)BON_WV"OK^*FN&:([AYCW(2J%3@NZ]/+Q2C:I8C?X +M<!4.V$LOPS/[ZL^_9;KT9*6"Y.<3AKVRK/T<]_Z';UG]23+^C(P86Y%C=#// +MEJ'=OH'2WI#*4H,T@I`CT)P^"`D.8^1?PU::92%NS#R*40"A+PORC(F-\/_5 +MJ"E>-QB$,"J6ZB=G[)&^V03BJ:0'N.ZGK:1@E3B)"V,,`(O85_4([J:E232M +M@J0N,U]S,\:7FF![T(!R5L^MA\APGMY?`3#UP$=HQ5J,XG,XV`<Q!36*7D +M9Y\<0H[50JS^M0Z_4=&WX^`F5P74J/\O-*HRKLMD9Z4^1BR(V.CV>U\M8]*9 +MDF!PS;[ZFKTT$5*!]7%/)3F9$6GR:%KX6LS[*7(;76TW3YY!33\DV!"47(AA +M@<YGG`V*$W[?L*DJ^9\@M&->[4$>+8YS36^.<=1(R:@,[!C)$]RJ(\*C+0%F +M"H.5UEX*PC:P<78-B`R.A]Y1;'45FZA+6W@Y'3]T=I>JAOZHPE\5>YE.8)A0 +M]TKH>_SJEM*%_QK*)72\D&AR'=KP+MQV?!M/>\%.WJ1#,\@.8./DR_()&/?! +M'S*ICH=!_M<$NB!\W4"1;1WW?7U:*BD+Y[><Q2[2\@R=DSLJ45?(,ZO;:YK/ +MG<7\D*)J+%J*1@WM@G^^%$$+$?NS]16N%8Y&-P]"!_M5%<];IJB-$S?4'M(I +M\6#+0#J""3)M#<L+3&(HT>6_L2FH_>+ST1MCZ=;6<+A>R*G)*FA^9+IRF:XW +M+2=W7)2T>P$;H:.8:^[G<FP.)J5=G.*=EMJZURD/$'[6?=.]7UBX^V50W+`I +M?#]JY\XC;"5(;H$Y-+5A+^#)<_-SBUZD,%HX?;\TX'1.NH]RE+M*T_[AY=VZ +M/"8^UG>ZG<1\K$IM*M`)7A`JY,2WT<A4HW9^N$'[`&E2JU0U"UU>+*+]$X_= +MHG&=QN5GE9"V%DEY4=3LTT^HL;OW%Q73.Z.:-`=ZH&J?+LJJ="V)IP3!Q*!R +M0A],O@NJ719F5#/7+`S9WK;>E=)P]9?$Y!W7I^-MO*@\C5]#DG-<$33.1\M& +M)4M4]P'BIH;:[3%71LU!.5`8JCK5'":$V#HW5JG9KTB^?.=5"@AC!'DS+2_& +M`9,Y2?V2)59M)M=A`S)47S,)#9]>3'&KE,^D2^H0Z4@>)]_Y6\6-E\2R!,$Q +M4WM"RRP*&0X!@JC-@,(7\IT2/Z=FUGQG@2ENLMBNPK/P<PY7W7Z9!(-9*-=N +MM^'DM5YP0@IDTX')+J-RX9SZ"O%;1/6#*$K20,>CXR[S\'*0=7E$81N^!5KS +MW`_6:]FK17V(8<=@.[YJF?U6JV<5F^A4@+L$`&O:M`"&+LF>-BQ(3L8;A8#I +M]4N.Q.8V0:J[>;]).`N?)F"6'S_4&:9\'[;:SB7,E;-'3=<Y,L,*O4(25U$? +M3:-N9`:04*1X=7PY.NF]U`MES16N%D]83`@$984A927A9->C`Q/D<@YJ&MEV +M,GK1^H:][XE*K.;!U0=.#OFX\F.)W/8-2_Y<OW]+PWZ%)`ZX?-N,HM0(I^7P +MB*C+V4BQ,HH/#S9W$>,3Q%K@(\U<VD'[LS!3'&N1KQ&WGR:A#RI$3`J-7$M; +M:1>8/>PKI#?4L7*5M,TF;T[*R;Y,R"4,G(I\I!_RY$H?N6K`Y3FFN,G!>T%H +MS-:T*^8ZH"!_J"Q&XG%1._9G?C%!R2R"?^.&U[SCC5W;!_E=92)ISED4X2C` +M,,_H`I^2[WU#?M:%I1*JB:P$U`+$`),:2-G%1JWNT.P[]#0S<@N=CK#[=(F^ +MH,-['!U]'&,MFRMZPJ*<?QS0"/>-E[1^4<:+EA&'EU-`071LX@[2B<0V[$]/ +M"@T*'+Q>%5E(:V50CGF]=4272<)%W]T![#=1@G>=Z5CD-7E1&>:%_-+6G6O= +M@$D'H#?\8,5'#Y+%)B@4-V9.V/P<JL"D=O$&)SR/>?9.%+F!C;*.R[6J)-%A +M);V7:9+0"6^4O[CHGUR:.R:4IG#6"Z[]IO6P/]H"B"\IIJH?,9;NSO!_OBE- +MYT^U@F'Q!*ZZ,':L$V\"]CIQ%N`R!QW[X*'!&O'<U(UFG"(.EJ'(KCI'X+V, +M6NKO`1^E^/VU09H:S\E=%E"&]@X&&60VX@.GP:W0VF;-QCX9-;U;LT`P<"<N +MED4D$88UQP[.6*X\]#9;VPBI#[*,*T`]#HY(L+C/\P1NV78*(\%'@#U.[&I' +M+_AQ82<[<QJ.AFD:-D!^^><SFNDUU$;*1C'@[SO(HQS4TKK`-ABJ,5"S!OC: +MV[D-!^'LKM:R%<W65<?(82_3(&`VV_,0!V-3W83=C$-$6F.?Q1L]P!H@%-T@ +MAAR^[\3-$\MS"3@W[7'9#3IDP`S/8J"[?`@"S#)Q*[)1R0%,=*T'!!9"ZP$2 +MPIE'.HE]S1F._*PD,''1OJW?A+$$"J.[/QL+9!?;BW/9'O\6))'6$.VZD2V" +M;N;D^)G*)IK1D)HQ?.+TC!<O"QN3C*Q[LXOJ`<=9V9KBL2@=@C,=-_QRB*<T +M2`'\;87RHFO>J?T5H$#\09EHV>.6!2G%:K,HC;G[%ARL8@'932:*8/]C(!6L +M1X-/EL?AIRAR!DA2WF4A*)_#DT/UFX`<6PX*M;-U-)T+)F,,I.:AMF\7[;^6 +M,=;,E73J)A+K)-EI1B,."O]24$:]K1Z11VD/UC"MD^6DT05$M;$F`%F"XDC_ +M\V:,&91>V<NS[83NO*%\0]'!`A6S6I;T&WNIN@D9D$T6U86+<F*?ZHBC>>+? +MYRNS=;BCOF*!DD6[8_$E&S/+'%@J2Y]KME=?%>`U8GF;^A+/2W0VR?)6SED+ +M$IP3@DUQ[E)W5@)>F\FO/3H^6,)89%OJ(UL7G-4$^V/=)M!3%*[;+X!7B.9V +MA_%T/@DZ'#LO(QU4F_G5/?/NDD\9R.!QLL3Q#9S)!QR=89=YWEX':@(QK.?Q +MH<CXY&&\F9=B&Q_]G$.,*G#D'*`6&#YE]VBNP7"0T;C4T-1R^:JETY\YM&>( +M\IKQ5S%X(M8=A_[!\H#(`];@BN4PV@?%PNA_?I_*]P._294<@X*^;[ZF_Z(A +MU2>L%:S->BDL=3,SJ%B-->A[)\6D+G)]8/)[^PI#P/&HU%\N]1+K<22'F@0- +M7IN@*RC@]CW9I)YT:7(JW7QDR294AM#DA%'.6AR5PN6/G@[X+]"JG!+@8?22 +M@,7CV_PXG8@V:,`\CRH#H<K]5]'ROB%MX6CM3/"LJ.!^PX3^Y8K'6U>]<(BD +M6V0<S!S(^6)*T+-%0TIKB#]B%>N+)9]"RQT;?%8-V0]D1!S*(_NQX?/1351' +M]:^3;-.H>&UTL'YOE9\$5KZBRQ9UMH@AAX.6#QH`V0R0:W&5'\/FKD9_`;&M +M"[1068%FO4O(`<ON*5.[I<^1DE+R'/2WE#%:;0^WBO9-(7MWR`UY3`\=&*41 +MBO*W=+!QA9*J0J3\$#@"]1&O%=M?LI@RX4)P?H.>2:I`/\*6*!"Z>+-)+N^^ +M[3,$R^Y!$+%37,+*?@*U!\$:1Z"@BHL[$`-'%/!Y$7@^J1Q`1;8_C7+)4#OT +M&LY!KVE</(7>%_)D=K4O\@:6%71/1Y_Z^EH_P$N_[H2DM,D[KR_\=*B>OQ`# +MR\$PRJX?:N@'E3_JC[/5/L#T8T8$>YIGW:+I_V9V(!I!T2!0,U(C@?VD2!K\ +M6)4NBIIWMF;(1S6<3LM%6<ST-9$$PY0*O)R`/.0$%47")XF!H1BM??,`GF6! +MB4+_F,Z&H^UO;X;@6T8;'.-:C4<?/?3`"$""%&>7US@[:G5!9L2SJ;;QI]5F +MPOGAV,Z;NCI%EQW210\,9,G_#D(X3URSC2Z4$F.HTZ2PNM8UM/-3_PX#^6]A +M6E68..&3$WI7-R&CDS*??.D\F$3PDTFK?Y![C&46R^_"%"1NS=$VB/+?C5:] +MN;@N=/8:"V#0WY52QUCA?*FD(8]]H)E6HVF`A/V9JC1-41TNLG4W1U?]-;QD +MUR"[*8R_M(0M*L?#XU+<3_0TX!\&.5C-C:Z0=L@#NFCFGRC>'T3?7>EFTJV3 +M]G1R<MP$C?9,^K-$OC6,K2ZQZ:C=$S?.>JID.-!G!GA*L3XGP[MT>#B;)JH( +MUL2QQ((A9-_I\V:__AG`0^E(6*\`0]LVAH=)#Y)1?.'YLC6![^+)'SG$L:WN +M.1:"Q:!80"G'?&C.QVI/?98Y_L4F=W&O7DN]7H6:P)I\I<>O?;<=()SM5F/- +M[/(3@LD_D?47*AJ>L&F3U,"L>;V(.Q&L<*2ZT&0I?>F);\NU-3V+NS$OT$IQ +MH^M)LV\MNY?+PR'_V9"ELA5$LG:?9;A=[<VA\)M><_CG,1UCWJO[2P4\%V;V +M@6[D9_P:"(!N]8D+/ER\Y8SJDY/6HNS$"=?7('3DKQF\&E1<Q'JCB%8_)MP$ +M1+.8-O8EDYO#5;U<CFAYDU@$IVNR?+CSGMX]S5O7,*%0I]N+.7^.W7)H5IPU +M+&YW-EHC:`U)<6)-#$F>ET5JM-<@@^Z,6##X_J2(1R.U3/?#AO9>5CAA.#[4 +M\L<LEV[^WPU+]VJ=P8Z!PRMQ\MFK\<]ZJSC3LNS`TYN:*`12(E]"!X..TX^I +MCMPQ:!O'E3!RE\6HZ5>>'-LY=WNP]YXEX_%]63%,%3I:2:!$X#P2;I=13_^Y +M`W`)JK"I/_P]-!%_);`VVMG#@TR`HZMPG(ER26T"DCFRS,0902@F?6%&T`+? +M2ZK@]<&5*Y+GY"]4WB&^B7\R_K5<G@O;(_$5>3.JV6ZCJCXL.[BP!P=.1L=N +M8&D=IEKJ<G"]M4O1>CTC)%4(*-<6T"@S+N?Z$[H9>^FZNG;3JP7U%-8TOD!9 +M,]R".H/DDI1<C@H7,D^%<)GB?5CW"';6@)0,2Z2095XWQ+;R(O,@!2G[BPWL +MAY<-)W`Z:=`G$2DB&-SK@'?,FZG#@[SB]/^H>YU-#9@+HJ`3(R&>2^&Q)9SM +MO5)+H8?)BJ0S`QZZI9+%4=XPA^'$(6BUWV1LFN#T!F;6LN0K^_]Y"3("1AF3 +M0PG'#LUAC"BH&'_9:8.][JO"S!PI)0QLX:V.#T688[E!S]%-2T&^J2KY(!#. +MV@?O\L>[6?#-<!R<>B%CRDPYA0U=Z,%G>MDLRWEY^QI(U-'P(-(<6K,@1K'_ +MH4UV;]JC/Y[VT;[JP1VA"(O`(`"#`^E;]S)%AC3$1)2P%7N$4W\?:5Q(#,'Z +MYN>9B(6!D[-,O`/X:B+7#1P!J[#F(^5XJ'P:6Q:XZ+19ZY-;7-66?K78C]&> +M:#O7KZ#%]@QH-_W5IC+;2:`::O+HN[>I75&#IN`14$STTFH$B)X"UD`CF+[\ +M48ASM`H"#1M2,V6!!GL474=L-P/K<*O&('U0QK@<\QUS[\)=M0]-3-*#KCBY +M&YIVF3I5((L6%A4(8NHFBR(YK:+4>3UBE82G-.6>[%9I_^"(17JHOT+JW.I# +M$\"LN.UXK=FD[3=-:@W%7SL%<ZV[>1`XJ<_I/GZ6DBUE!,H*1:\7Y2S9(FF9 +M_,1!D#Y@T,LRR?65OS[W]%"!ZO^JJRKPJFJZR:M6)!`@+8ACOZ6KVRAQBBV* +M_?ZG#4-L0[6E&3K#]-%35QD1-84IQN16Y-!F!M1Y&[4`_%8RZ=-TV\$$H=]H +MM)=;%(*WSCLP.M)#RYB>*+&H%5\*56^3UJ[5&DU09Q<BKOD_H+;2L%#/2.\: +MHO()-$XS$?!268:][9.,2`3Z_?;XZC/?+C]V%]B"2O$MHP<HNUKKR/W/P'=$ +MWP7V8KWS5CI3,,`D^1EV]\GY0]"^1ZJJ"M'^F'II%='_XBRQ>,^7QV(>?W<L +M-H_@J:QVCNNE$YN-T5:G@$$J3ZEM-I`+BD`SWRH`D5CVB6J3:'TCHHZ-1T\Y +M9^)EX/%.SA]L35'ASHQ>QR/5,Z&D4LND(P(@T:Z0B\&)SQ@\X41<QF7>AB8F +M)S,&(+_`8+7-"*I,_V6Y&;6=+9G>$))>6HX8G^_3/RM]%*P,[_Z?BY84LF*9 +M*4^-0V,KZCC6XM>LD<H*\M,:WSI@X]HB,I6'7F&S<_B$571S0=5XX>$$]A6& +MN<JV(>E6RG2?7]R3:O>EZ^+<=IS,9C];-(\_[6[I3[`0F1.)+0J$/..74%+8 +MDC\VB3*_5_'\O29$,]V^U"01.0[_;*.!)ZZ5A#KFJ11>R!$`A0</IMZH5[T, +MG\\1)GPX>^W9/>'OC="_OBXVYEG%L#1(;*@Z9L5?YU7K-C69!`W#A]M%>(LZ +M^X"[_@PTVR$XO]LFY-\V<B2M@O7B9I7R]U)!V)QCS.WX;@(AX0!ZP$16_&&V +M-Z9_RN$6P^(/G&5O+^M111'J+5KR?M0`[N,NV"!V2^AJJ+.B&M.&U+V@^T3D +MT,QD.NN:6ZETZNS2Q(2VXQ!]MG(]L%C58MGYWGWE()&.(/X5*Y[[Q(H1:Y<H +MOWQZ4\W3;DORLI2*PI1W!02*YUS.3Q3KFL$X]&(-DIX^Q/L+V^?"1BJ]7E9= +M^K;05<P1V<0D0;(W"-'8!><KPS)#M0I-4!M0AW8E`%=3QT9;A\$UIJ=J[?G* +MM[MN>2@[5E_%V:Z74/QF`1)#$F(\67?I%/XS6/48)'6\>V8W5]9UI>J2%EDN +M(IG+>*$1'YE+V?#:>Y+K,*&1A]:\K.[N2\]:;'/;R2KL+[O(HNPQA^&N$VN% +M`=0C)8><><E>A=`D9&'I+^8CEFU.&2T+X:%^$\T_6D"W\S%&<*)`TI`@9S?J +M13H/RB73?FE8L33$.))/@6QW;<!(MW8Y00D]1?="X>ZXV"O:?_[*,,J[%[OZ +M^\'CC3GO].=-ZPR8]@1/+BC5X^Y?!E?70%+WH;N$S^F;ZUQF:XJ@H87+I2@$ +MN1;172D$X-?%8@Y=ZB@<30*+'YDX]<^%G9_]TC#;9A_:H^,/P&_20##Z?B%Z +MSF@DN+70L*]F]P#"REXX\[FWH#:U7.%&PYMQ.!\ES1I\^6UJSF5>#R@-3GH? +M]H=36M@N%Z7\E"232VN\19:^M,:3WP8R,^2)@HZN5\N1#`Y3F';(?0WK><'- +MRW^)WX[>--%D."^K.<:4:Y0WTH56,:GRX^LB3@'5H3-U^MCDKIJP+D\8B)'6 +M2AHO3L^]7\?(M&YK1_+J(BE=&"(;L**H'EE`<F<@L.]*,\BFIEU@5-\PD:KX +MJE/(FX8N$60`^,(._9[`TACL6'=93&BD1I79H="@]KT%FX/''*#,<"?\HF%1 +ME27^N/[*'K-_+W'9/2O3!1\R=A%*Y_%481\&LU*O^U4M'854DU>2'LX)K$;\ +M5G.GZ'7#>/&Z&S3*J9M_GHOM26+(!DU5A)0T)A<T?3IW`P_*<6Y(""5%<0Q\ +M)D,``0FD8\S>LSJ.-F9>\A_IC#8.14,(1ED'W0@J!QU:(S/6BBQA$_Q)3YF5 +M5@Q<I]N)XB)&:K!XOK=8WQ/SU?@9?]#0[?XIR%R.J8J?V'J5OQ>ZR%).)HN^ +MT.RM'Z>2*2TORS(P;`O@>L8'QR`A=YV6$0\*4^C0=5WB#9MS`!M$3SOQ51[+ +MU$8RV;CTC#=C!/&765X5@0<8^0==RZQ\27"HS\VJJE0DFDK(WI%&"SHCTK1" +M[J8/9%ODBB,:N5PTN<\-IQE.U>:6)K8_[/F"+B4Y'?$G#J-:T%KR3,<40R46 +MA=1'T]+_XCI0U8)5L48M.SVN;L*K.G&!XCQ>;8_BR=T8?!'<3^F0J1"8T\4: +MPW[]W[YJ&P[5AG84'.'V5!?&DFR>P0Y*'?Q\'<#0UDT0T*SB,)Z['2)'8;GP +M;+N$M:$)L_7CIY((N21*F]->:(N=D3`N[U\/51O^,U:[VBG&II^RAE9RWC`C +M$Y`R1E&!@B_S\>?8K5H=_36J3#2?P_[.%7^GDQK8$V^&P37:1F4(=3(4[=K: +M*4"NDVF?_#:V9C%8W.<?'B5?`C[--WT\AJDU3)$?K:Z6'B<O#L#S>,1%!7VB +M\!VLP=F48-EW36EV(=R4VZ_=&"9G+C2('+6W<?A$53_@^VIRM-N?POL8O+?- +M+Z>=BQU\_]XM.6R'MK='K0JB>C2)T?';2"KM8U9PP2Q,W;)5`9+^&XZ(5P3_ +M0T+Y$L"XHYQ:?ZCA-.D;`6W:03O[:FUOJZ(H?V;31P5B>&O&S3%9D11/@K<K +M%<(#QD-].A9Z_<_I'3.@(.\&^(LC/I1[AR'\O&0DR6C`8$;I,9>6'A8GI2Y* +M5=0`?.>WNEZ;QVF"9F2/@MG\`H-@&2P=M&9U#MZS"[&>NOY0_"J!:!QSF<,Y +MC`4-H:?UQDE.2.R/@/=95<!YTC;'HGRM%(F^0UJW^ML]P27=^35Y"K2,:&QY +MP6S7M4-?C\H-?8%3)][B[L^DGR#/XJ&]CX@'1=X9@^X_#M!D8P9!^\1UN0", +M1#1STUH/6H_R<^"2B+DA@265[16GE4L022][7HA#AL07_^TX1[@744(F]S#) +M)RF[M%/[6KAM+L#!?I$4L=J&,$IMPN),<I`QC@M;MQ"CCCR^RCE-?5ZP<*0D +M!T_A*F\,PJUK1F\HM_*B?5Y&*,^68*+/VXYUD7X%OM!)!9+NS@[7P2XM*WOR +MT?;S]N@9.$8U^7RM-G6I?=@:URZ401;W4)72-M;%G+;])=<EXL5_X?K\Z)*1 +M%/#1<DB9PBG58Q4-U8RVV[W(`\PH@Y%0:\?X]"G(A%:PP1+N<@;SI=,JH359 +M&W0'5YRNS=7P^<>4FL;E@M26'>A*4)[H^-4@3GH*"H:4/+_\A`XOD/@W"<)= +MZYSL$^?'US!6]5OW`/NFV,63-P4]!\!TCUQ(4L[O.+D1J!M?D5#]-J=BHV#F +M,_8DM%&D_((91N%=/"$64B>2C-Z5X&!"9_2,(LUQUT/,\KU'\\*LN39!@JBT +MT=Y'+9BQN\79J9IE-EC$X_MS^K^^:E>9I-1I^+S.PG(53"$,3$@E&@*SAC:X +M0ZW57ZDGEFP?U&!(0&-D,#?M=Z+"_,XCY2>S:**3L>8<4[NSYB_>,/4&?N\R +M.^;KQC-;<U#\]T$&+^?6B[%'O3L>!HOWH;Q=J+K5&0T=O*"@+CZPC(WB'A'T +ML"Y4=CRJ4R$1W0NOSDC*89X:Y4=\0G(`NI6=,V3_'3I0PG-B!#*$\G?MR8X< +M74,'E!A`;G(8R]"*2,@;&3SY.I@=`8-I9@W1O&)5>@UA\TYUD.$QB8XOB.;& +MU8ZAVK.YZ/B'$Z./L`2'SI^B'Y`.PS9*Y079&D<5^<=Z='VQ9O956Y?`V26N +M%"+#^E?WPOQZ)TOD*Y\*OU-B$&Q(#)2<2!:?Q-F_E:H:_0_2PDM!XJ"1/1UZ +M0B2R\+@T5`]WP_WPNUD!8:PK**X_UCNW=Q!Q8A]1(<X)L[ES7A.'YA&F,XHC +M@]JG5%T]6C''`69J(R=4Q?(H">MV_$/D\*TD\7[KQYY!-[WA?"<)A4[/@[4L +M9V-/P4C-5)V"TPTO/A7609"S'J/>JX^=.=YR)G=]9!T-3+RE&CM5P@V[MR@. +M9WX8-$8._CO1/,"I$?^^G'XM&J9'K6[BI%$M<;I>`/=(:L",%OL?/D[P=90: +M.*!:K4;\82,F[>)\B;5[,4W\8I[<ACT/7_>*",(JPO_7\@(8\*0/*N:SMB'N +M#0H2*`0!#3ZE9[<(`T$&Y`Q(/89F<@-3&6>EWJ(,+KB,ND#+T.LH`3_"8<[A +M.>I!6#NHC_%/-,4V=Z,*;%:;-I]<5_(U[S2;0YL"U50<=;]`$5/<P^7J@U9C +M2YASL\ZDQ@)HRCU5XG<`AN;+VAO#LF='.+_[D9OE+G\;):;U,O69^-/(#]J3 +M.'0>)!'I%`V\0$(L$@=YN*F,7=BV,`[5#;+$I8Z=XM%J>*V#,H5E:BM/F2KW +MW[:D<REC^\?>UJO[A>GXU</JO#N`H?*KX%16F@;V=F2L5;2&MS7RV_5<T+PJ +M`3>0/>8!8,+/$;]D*:K.0YAFB]ER69,(X1U86H&D=MOQ:ONP/[49_A4?SLLM +M5A?4&G3(>&CV)_?W2>%DLUND)\ISM;L4,^.7L)).\5&,;KN\A1R'#LL&$00K +MK&2V'OMMEZ^CT'L(5CY.<8ZE>NCH"!B<04^CNL\(^C:\A[=_"G:H_I@\A:M> +M)F5G35(/MJN)+#7S'K!-JS&BSSQNY7?CM+T-*\/Y5B\#&7F0M=>+CAYF\?Y# +M.JH0NYV.;)@JBXNPR`LPD;(0ID(B$2VA$^*_;9>&Q.:!4Q/$$O?N(C]C^"?1 +M6]/2D^SNB8WSH.&4P%_)K^<B]9'(+^PPER/2J9$;3L@9=-I`&UWTO9X\G8Q( +M"UQIK$F4Q8'Z,OM"2;\J#?8+3Y1"LI[Y+-'_&)O]\_!;OIXM`'P;F,-::FFQ +M!-(L;+PJXKZ&8;TQ4"<#,0Z-MW;>AJ3Y09@\&`D`_A+*QBZ^B^YJ%H7D-H(, +MUY3`FC"*]P\7%PQB=Q#)\(.14NF1.<+JFA6?./=CVPZ``J/27/2J9$:3$HSS +M%%,E3_\\4_Q@&`BTOPEPL"*XP=N=FL1$9Y<FKLI_#Y0B!NE'6P18U6\9$-V> +MUANK2'WEA&TKCCQ8VH'\@0)Z.>Z0>:;STL3,>'(!TJ?KYB#4K)XZ!#_U(?+O +MYOZG7,\BOH7`A51;2DU)E4PDRNUQO%1M%A6?K6K"DF`H*A[H`?Y>\C&&OLP& +M,;G`2O5!S6OR[]:9HV4G/]LA,\V_UM&]3WWP9W<,HA:$"P[,6DK0X_M1B%1" +M#S12BA<>"X`F+K@7LFU!OMQYPE>,'&VAWT`39J/S`WS24Z#JS?^A'?*&2ZRJ +M9'[KV=21RL$#$LMQ;$*F5O`++[R50D"!E-!<3TJQ/L"Q/&Q02P,$/P`!`&,` +MC+`.10````!&(@``K7(```0`"P!.15=3`9D'``(`044#8@`D?WCN$]"5W!7F +MI*0FWP^MMYDFC:IYZ0YCIL.S:#[^M[G?MOMSL5$1-R9'<NSSY\-P+EZE"N^F +MT<$GN;-)N],O#W^BG(._;L23F"\RI%V<R#]U_M)U1>8@%2>I=M55D&<TJ#); +M-F/AF\>M.#-CE>!+1#?MO6+]/TR116WCCG\FZ/:#CXTE74P<:"U?DBF?^:QG +MWPQXTIOK^J(HW,14+'S_[:VG5\LS6H(@3L`4L4]5N+4)+L,M[0K=E`=I`4DM +MSZ["X1!;.N_\B/)(!O9**)8D=YEM'8D'4F3$H'SC-8\'L%/H&1ZH:$NDOGMH +MFXF"UM@D$(*QT]5W*]M")"K78N9Z`-U5YV+&*XKM/5Z.VZ$.8^9`L0?/T5&1 +M%P6UDX'?R_=EK?M;[G_N`VX\5O(L[8JBBP/NW[6+3P=\.^!Y%X_Y7V%VD8]F +M[,VH=6AWSY!L;G/5';!YLWD:\BV@HRI_P+[Q^O/A$MB&BIK:UFQI?C4'$%XX +MQ1WQ&VRJ#__NB_[,49V+T')Y8:!0"00G*2.IO@[P1'A6;H;UC0.@8M,1,O<N +MZ=RF34/4R7!3XZ!D)&99WP8FMQ0^`.^=KK=95;G)G4N386(,'ZF'1<%9F%M^ +M>=GP\N$U2MW(_SO!&"7ZZ%M)M!/'13+<)&F2%LH,EI@[6@3FY\G+!&/K<B?# +M.ZZZ*``#R(U?*I?G6VQ_OR0\Z:K>AR&NM@6[-5UNC@PJG"S1Q9&V)@3$@,OG +MA:ZDKT'XQ,.5?2C__D'8(.2AUN7'EU<T%^MS?76;=\\QT:\$$A*6MH9.L,GD +M6@J&4<7XE8#)/1=ZN16?E;BG4Q/VFS?H`Q7FH3M4)$`=S8``EI#,W91IYW?& +M"0`ZLF'*Z90%O+LK/I1]^$Z&VA<"+MI@N0>:Z(4RUM^*NQ7)XY=7L<8PA`J: +M3`^D<22O`QY+^JDW`FJ1$0`,:AO8FKF"7J7OE$$<F"2/60?PXVT8AYS,5W?7 +M,%LY.>SX0G<9?Y"0Q-BDP)=%'LO3]RL(K+7O<S^Y:E`G3:V#Y4%RKHVK7"=T +M!-HI?0>/=CK?-#,[(']/!G#G;`Z,?Y*S54`28)]QFB[O5>@D0[#%9@E=AK_- +MN?I]APV!2"(JO9R;27OK!%_<4_5:+"H7<:27!JU]ONZ0L?>C&Y]C9\4.G%^7 +MKF?7&)?X#3#-355YAN3C&P*634A?J;C:K`'?N3:WVEX(,-Z7N:8,UT-JA;SW +M+U!%GK0;Q]:B2<,K9\6R@8VLH^M<AI>$6KI\MVSU_"K/:--9U[6G*#G8VVB< +MVEQ1'HFJ`K!9V^_^0.U@'#9\+)&C^Y[2&0?=8Y'\#<'`SNTG_L7W$@$<H^GD +MQ>>DUSWH56YK/E#A$0=.LM@.9,D.>:F%B=LD3<*ZC,\;LEF775ND1D-C'WO5 +M:2&4Y+RPAQA*$+OTT^C'T/TZE%%0%I\NT!^PI==_]#];\^V72Q5@N,C,118! +MB:]\TE3SU!=R=^7/<,8,PN^#.02S3G*I$>_33C@]4<`W4?R3'>:A90PBEI+- +MI_'00_$-A-7B5'T5S=N\"Q"G^OB/"R="\LD8.M!H=)MASF6NY[Q@.I@;(KP0 +M@`WR93#PGJF"<Z!W#NX&"H&Q9;JV%8IM02#7"=+@9+;-=/XH&NVEJ\?/2:G* +MI>?/T1GE*FOF8%B<,EW?P_<$TF;KA6"Z:>)ATT)O=.C#\5Z:T4^EQ-O)88R[ +MEQ199:<)%X!"48K@WRWV`I?2C8#E!3*_#$565G$6KN.P^L7QX^;F"K]R7OWJ +M#@N=,-$^%O3!%3+&+IJN',0S0+906GM(Z??(PA)0ZL1\MM<H6RZ8G.YCT>DJ +MXDR#J;[:WG1^8R2!;Z@93,03!M$6[7@V$K0`J<C<K"D>Z!7E3<M*?WQ(4^__ +M7Y'O5R5IG.UVU7F8K9Y3LZ.''?PVG/"!F8-6/JQE\$>]J7P`P*J+2U8#G0&6 +M*PJ3M%RL))+G=*&)?SXD(D$\OTL\E/1O].T/"W^O(#X;(+:MDQ`Q_`]5HL2D +MT(J)MA;EW/(PY5_*&<LM%%PH+N$*-]`XW#(86"_\?!)0J/!GEN@4-]!$LXGE +MF$;T@<C#E--@N=^32C?LT`98A52I%FE++@Q"=&^37CDQH+7G\,#GL^Y'%YN\ +MK)]G9*L6EY]=I=%8$<%WSO%UK`8R:*PAEF841EH'3&QEUXD1;*"-,$KM;M#R +M`?&IF,A*>>N0MG+?]82B-`"MWG??4`9WF^&K?J)ONVRW'?P(ZKSZW"0,Z\]7 +M/R;2=*?M`@+YJMRGI-(*QF@SZ,:WA[\M<(*Q?.EBZ%$+%$[X2R#"=#SD90H` +M*8K/@.5,"^9!`2Z]'SF&W!-^F)7T8OI`1O3E+_U(RY#A\=9D,!<E_8/RH5K! +MUA>![R\,$",#ZIH+.$@N&329O=E9:^*<4-BB5-LT>I//R!?B$W'_0=PCJ[H_ +MDTM1BMKR<TRN\>\:?3>/R=-@"YL=8^BUB=*\JWND%9Y,@HDH$8RQ5SK@YP^. +MEKFO2+7Z>P'<C5PPW8$#I5?<4$/ZYZ"8,-E&+F/;Z!Z\$/:F[=.8:(TEH%U3 +M_6]PCX?`L"P0P0,!>$([=8UKP*TZV\M+H`[L#96+8FCKDO:$-E"5J]$.:E(B +MD!1$0,8(!<D36O[KHXNS5+G_[G#'QQ(X.3:>`A%5`22TK]E;[G'D($N&\VY? +MUDZSP*(T"OB%RK_3.EQ*R8LPJQA>K/@J=1PI5EK/4Y0&R!PK%J`[>8SN,]%M +M^K/<G.=N.$-L$UO4KDG4/3;`A.L!:9/./">^IY^7Z]<+>^R_-^A'?<=;WIQ3 +M>>IJM"0-%(1=!=-@?)_PZ*.^,\UX5""HO0!:JI1Y8Z(L!E3UV&C!9+*87'?8 +MP/0(B:E(C"8Z?P.10C#R#I,VFR!D6#UE8Y;A:<-OS[`3]L,?DE+SM_&";T'F +MPE&*5LA^:6V[[6-P#VJ0B-]FLKC]I3Q4!1CWQ^//+&L%=A,FGD/BROEU\7O\ +MQ*,O4::'1]M4A?=1@LEMELR/S-.<O(9,R561_%ITS)\4R[Y)F)+(Y_6O3%0& +MSU`S*PPHX,FN1LQ2+>O7X)'K5%T`Z!#$T@3*J3\QN<HB)EC&"7I/;W&!P.79 +MF0IZ/S*UJ/A\8>HN;MM'&ZJ(B.@=*RKVA\]GA4+$'ZE4NX5+';+(]*!`'0W> +M'+(%Z6$IXP`4X2*D=K6SD#`".HKN"+B8X$WK9GO340VU.\AJ/JX'KX6_STID +M::"Q(/)(1LB=)ZH!P1$[?3+H*((\!!73,+`%L7B6:,,(9Z/F#TM;IK7/*1-Q +MYV@G,R5LWSYB+0?00X_7R`1)U$N.;'"4^E)GDRNC?*9JOS,SIV_T$/F3Y]#+ +MF3E)H2I#,15-G)NB0306Y5GSI$^+Y18*(%Y'GE<(R/QI";NJ$3K%"UFJV6(S +MS%J.RSQS]7IV84%&P3ZFO3KEU__,<HB3JP<Z_5QQ1ZSK_XX2?%5?SB#^^D'X +MHT\";Z\&'PIP,D=EK^M,S$V1>K)\GX)=6('K5DCY::-</YUFNC4TZ2]O4T^^ +MPZE:^3;M2T%A2`N&YJKU(5#O,52#]Y`^-_V$\)!>25$PZ!)LI5^JGVSHBL#D +M&145[$92<%3UGC6(VO^)HGB':ZU,14PG6=BFGN"B&)&H\&6)X*8\I7FX\RTV +M2Q&W1Q6\G^6\7$DS%LEZS"#P4+Q%E]S+9`,&GN\4T1C.*,J5YE5?I0L5P\8( +ME801(;"[5&%!.F\M](H?`*=S?E.<1%/*D-)&\E?4E]S7('2^.$C126UT<4@* +M@0?SM6Q=O@Y5S3(O+AK"LS]@'Q`4^"6!D((X"8%.E!%.YDI29%!Q5DDDM?=8 +MY>$/*3W[U^=X+"S=UF>+W0-%7\699L-`;G'Y.T]2&S($&XV];5J5@0H!U!WD +M6LNXZK]7B\LZ.&F*T?BBPEUO.0@^R?]K-P=]YRWZ2HDLW'8"'2[ZOSN\^I%( +M1F%0-Z48T8KS>U#QFEIKE>:.:4U[,*NPR0^.D'H<'OLB5<-P"2L\9DCVB31C +M84U9'BYBWSB3&RM/D2UG?#33J4KE:<I,O'!&5'*9"%%F46J:3E4@`=G)YTA/ +M$`G9(*++9C$IC;_OQ0]N1+E+)`J^?MAPDK1'X+1)Q6]RGJ!+:G%PW`@5U71_ +M>G,DZI)19%7\H+5,R+3PJ"O]X>8+M%TR$O=SI'KGV[>C*'B"S!CX_ZW,QY%V +M$(FOG?S+(_L=K0$OQ_K>/`<U:VA>`6P+GHG?;K+\C'*X&O'<A`UZ&%<:YSJT +M2`(WB#JB"9L9<!GA5E;(OK-!)7-@Z"';2H1\MA6T7%8)RLT=IC^#BFC&0[2P +MCNSY_\:B1L4T]L>OKZ'$WL4^=9_8P@]9X0#VU_&?%*`[==>]JVS/>=*VV[DA +MKV4T=&R2T7)S^46])RZ!BX\RM>"@X&>>$#I..4<Z+`Y*8[5%\][4K05,B?-9 +M%-G0N,3F_\4%%:LKZ5/3Y^C3\AD,S*+#)3*LCBDC^R,1A!$=:XV!3NWZS],> +MZF!5?S#PJ#\T1'BD]@K>OH^RQZ4J@FY#(KEP$G%W3%IZ@083`T>+!J9$_2IG +M=#W]6Q_),>Q_JYHHT9#7)=81\^'W8:+"N`7!`#JB["@^W</5O=;@0?<N#OK[ +MKS;:@&2_)]Z)VR(8<JFSV)^T)O>8:GKE)'-%*!9C&\Z^XBX=_49>,X[IH4J6 +M5:,P?BTW=A,/'-?0(8-BB)D1"L6J^2O7HN7<10(7N!8NH>]]H2@")-99+^/X +M-22A#X\MD"?A1/GPM2IJD:1%'5CA_YHH![U.@^RMBN/>Z&CMS;&PO%9>T$EY +M)L#0=,4%21&VKVR73EHB5W^(X+.=*V1U0(.\2%1$JWG_23(JQ&XSFQR)RG#5 +M]]L+3PYG\^5#`2P-.&6C:0>-7-KVZT&MVENV><EYO_U0`D9_-F1HPO.`N7!" +M/$Y2>2]KB>W_.FL#O#R!#4E)7_BP6B<9G0B1]54;.8]P!0EGTQ:%"`JM4)4V +MN/U#)A'02;LB&VO,TXIFX#,V"-$;OX\HOTBX/.R!+S_E]$6G3P/><-CZV"<% +MI^NK4]OI`G4YAQ_1JGK!XRK?81J=HC5-!E:!AF#7?:)O5>FOESW`"#`6P6B: +MU[=2==5KSM%"^X,D.OV['Q9;\.2@"EC>CDV7A-G$NU8R05V(_`O4=2X+`@,A +MV=!V%^GYJX#TNPU07LY/C"U1D-D)>VXYI&02<!E((C")[U`"PDRG"0%#6S'F +M\1B=P@OQF,<NTF`<.QR2$B>8[<0FK9UG/3L!Y:J!+1NT]F<\K^Z=,J<:CRF= +M,)()9SON*5G5;H*J[5>V*`TDC^M)PN"'_G^?0TOAFZL:`-%[XT4_JC:G9CF1 +M.B$QRC?!PFGP,L(J?<LR0T"22YOK<!CU)EXFA;+<CVKN!/Z9Q04,I#S4;`?0 +MOQZ6-P:=P6Z_M#:U4$H::XURD5\R(V>C=0T/NY9?=0<_35HGDQ@,(3;)3G&K +M7M3M:I_!Q,*C>3<E0=.0`N".AJ'?9&%>XU?4KN+H$YB_POMN5+,'W%_R1O(O +M=S<QJ\RH?G0\Q<VX!1FU."UL]\CCE"OI=Q;N(!QNQZ1YH7(J`)2?*<VIB,RV +MMS=Y+(=T.3UL\OC!HTP0]<<#<_6`[0'<)?2E2GN0]^=%<.S?1G4)()=;@RI+ +M2>$I(AT:JU*%]IAU_-$//N0:(\Z"R/DH\YP0=S-K56^8W)O(\]_[233\T3K> +MFG<Q%%^V6[M__RW?]QMB(RZN[/.$<F\^A&T/,OE&2S+:8.MH#GLKX+>]$6)& +M`/Z+>I["Y([Q1TIMQM&%_K6A5X9)L(3Q?!HQ^G;2EFF%G7$Z1$J^1,'^DG'" +MSY*()#F*"5Q:374-"[>1%IH4PI-CM.N_/E(5#U6C*X'"7>/68_UR2[KYHXGF +M/&_BGEB6H#0<*0@9JX,<4OY2(FU?[1,N4M/]_"7@5NJP-=FF),Q:)&/<O2#' +M,"2'VP6A-)=D)`QM,HE)CEC.*W3'^6RY+))IS@ZG39B6WM(])XX.,%7RV4U! +MCE.->44XP%JBG@?TP'J)6I@"3U(E#L[+<?[?$64CODCRG+S[Z6S=/G0-!3-` +M4WMD%AO+JK*$J8X+$>)\)?S^]1?ECZD4W4E%JLDK]#`I9G[.E_1T%)W[K$5I +M4P+=PZA+F+MO),US0(D$1"=CN1JSTR:O9>42,P`44>KE\'^*(`'^:*9I>6$7 +MY'-N)L9^VG$$AX#+&UDG;!D1X#[<DXL??KNMU:-<$\Q1#6RD3Y'0;@17?J?Z +MGB+ZDCJ.*83$X:_N%;X\0EC3I2E8B3.=V#.QBA,/X%!5#5LYK`LQ:9,<&G)Z +MF]Q)31>G-/U>8T-D^N)Z-7UPM6EIYQ;"(X9*2'3C/5PM.OTD9F/M$TGQ,,/; +MTXD3:&#]#2QRJJ/#\D[CK[_:.7F^K%,H68%W9&/^V-8-D\LF!`BCD=",?$?= +MB!_7H*,<?@7\M7CN$FJS6@#P^;^>:)=J9V&._6>;T'\$F_XZ@[@]CT&]%JJ@ +MXA\&RQV"KY'>&6VQO)6S;F=<B\XU]:?(4F++T@@*J&1.W)1FW_50S(N@C]2N +M=9[<U\9O0D9-OG0?D#K\VJ:6^'0J+R/)3293&9A./29<YDVBIZ;.EDE@GC5M +M7?@S(MP=C3@O7C^'8B\-N6,8NZ`JSD6EL7J/F*`0?OP7@Y`;Y4[.(!-%34WU +M[YT!$A1O1&LU(=H[,35H>IJ5-L7$>8\=TU*1DD-O9=:DA)%7\-["=P<VK"XT +MGYMU-@#I<0P`XGG4!USD!8>[EI_:\#P`)E#4:`,3N5SKGH,YR.?=.WBPOHW& +M"Q=S)1J,]4^4VW6!C/@WPF<.'YLAP<<A>1_MB-+..L^/SQ=9"LH?_A3`<^!> +M#"!0DFMXH(D@S+W:-::UR4=WQ@>M&5Y^39$3.^ZC'49*&A$/EY/P,)^ETY6A +M/\&TRU+T)&/F9<X`/KU9N*[Y'.70-2:3[`OPT.43Y:BAW)#6=Y*QO8.KT@OP +MN45GYL\:-XG!?DLJ3HG=`EI7*.<$@B2I\'BCU.VC&R(84.'QTR-[0Q>&UO2S +M\@![?'%QM\XG'EL.'>:7`SSKX!(R*2GY(6"6&0X\=`&9=5%H$>!D,T<53U'G +ML:HPLP-6F!0P??M<N,%I@G):/LR7VMQ1IM(?GS\Z8'>XIO[I:D^]+X.,GH&! +MYT.<MFZB;$6D;N+N4$?FWT\WU^G(%E-M'SG-<DB90OER?9@O.;Z_^6GT++M2 +M=%K]@6IO_=>38F[4,#C4@3G#_(880;NHKZE)5]`4I\=FM6-H[&1>H=MA&X-I +MK+EM3R6,53VZWL"N<:CQBTBL<!^!=+?4G,A(*N?G@(<3#G>.O_@C\5A8I<;@ +MFHN9VQ`#5$JV?[U5253/5Z7FOM`*N:7Y,NEC>/]I%86;!L9G^([SJ\Y=S#(+ +M^NS&)U2#Q\]4=H8<%]+@*A@%&E0YJQ)EL&AZ_("'/WNINJ'2_;J)ZY@D=3.V +MUDF.BP/H4?5[PPP/=B"2,XX6]TY3DO"@A/MXU%:RA3]VB;UFDT?M%(BC&*03 +MR3R[[=[2;OM*;'\3:68S:3Z0FKC)X2L%<PT:4L!>^.BOG1@7G@/B<HO+725H +MO\#@"YI_O]B`%Q+/`;-[L9D1"RB9$%92>468"=Z&'@>,\P<`CFR1379[JSX# +M^'8)3ND3WB5A*7$LBR%5B'W*_S%9+3I^A87+T_+J=63/(]FR[;.>C].&)'$8 +M$.N!#LK)+BK+SG]0)X\!U>L%N;`EZ,"Y85D-U^8>!_/=JT$_W?(E%PA8`T1/ +M&?G(_]KT+Z`4\TI5JJY@T:#&[&$:W'ST!#X(#!ZCXGQ`XX+K%:M5[^BBC6'4 +M`#89Y`0O9C2AM[(\,GSMA<@M/JC+@Y]A94$?=*$EPI.ZN^[_E[NWT)7"%F>^ +MJJVRA:DQMI!\Y!"Z;AR+FFGXZ8VGW&94%+8:#V4"](PKA6<E>+,F5A7,][O7 +MQY2/9.:Z]/>>5DBBP&2:JFW9854'&XHSF1=`/P`F-L'%WUB#+H')H.^`X9SW +MTME\=3#]Z@[973P?`ZT`U0[C=Z+\B9AR_TQ?/>7@=0R#D1F)(;J6[(R6K#,W +MMVZ&%'T++_69K>V"!_+8/S[=(JDW2W13/ELPHUPX>Z=@O7`U#8^L>5^I#,^^ +M%0X(UR=UC:7R2;GB[XAEEE+.>K_X%62HRO3?_FABS=6O&<.4XP#1#E[8136% +MML[E^QKI0]!LXKVXA3Q)(NK--N],<F^=;:>:01.E6*Y#[7_#>=4"E["C./() +MT'830[N8>TOZI5+9+#Y,B>Y&%>_Y2WO)9TM5/'(/O2/?VTL1A]]J.[?(YZ(Q +MR/RD>"J%@B"2V!^%YR67T+LRPQWK3"D:,V&"`+\C95&#C<A[45\Z*_R;BZQZ +MR&V<C$XT7BOAE(I_@;_^[N+'U_I-JH@3[(2FR?EH%B]J2LL!M]R?N;'+'3V& +M&@COEG635EY56>[J8W!14:Z_R9ZJD5;Q[MJGX6<DXZ9-N(',JU`O&>!4#DBV +M,#^CO19Y2Q:CMRZ.IX4V,=;W6Z#J8R5C>U>S^HK8!"%7\=O\40#SCQMX):K@ +M#(W6>W!<+N9BJ+-ZE>IDFS(FD]+S"13#0\]C$66#;F;V+BOEQJ<X@GBH)#32 +M:HA(X*J=3\_/^AN?,F>;'['3MTIEPQ>[?=7K.V^##=MHZ1Y.C/?NW5"?.H(! +M@1YLK*\\6O,9C]B7(Z;C)S6!YK$[ZI,=RT)F%8Z1<KI9%W8],T*)>P*M05Z2 +M8(UTP"7X97>6968X]PL41`(+0\=]C!5J-=(T)21N=%)XM?)"KK390231+=V_ +MX4[NQ!V:,K:?%V:@0V<;_NH<BFD*SO1CJLFFPK@P1?/_'T<<03RR5$6L!F\E +M4]I$3.49GD!;S8V=<-W#/+*`7,VX`2%Y61!9L4,S;]<'DQFX',PN6$IZ+=B/ +MV?DD8\,NI-@H#EXO8"9M:4!S].?`G:4%([%]=MN[ZV=E-*0PW0V\L=KTX?.* +MVJ>P4$>H_RQGS/B>MJJ=CDW7!D>9M,M$AE.)^`HJU&21/7\&P#XV,*(=VNV_ +MA&1]WPZ4%[!M1WN'-I;WVHU;_<AD*?,T6Y=,:U6>`!ORG"2_H%?QLA299G(4 +M],2Q"PHR"A1S_"\#'U_I)W8_-<_810PL7LT-8?:+)TA(KMS!43&]FUMJ)B=O +MC,?"JC%"GR%`)NK/P:_<K1:<F$MS0VSZ`%?1\_6`E&Q14N;L#G4;%9%M"G07 +M"*@%XWLTO>:U\36DPN=J<A%'ALVHOB5IC*%`HN&O+<"O>&LREW'-<EF#Z'9* +M)\QVK,CTPA7X2I*&90,X?EU^=9P-A:*0NT5:GJ)HK('O@VSV%8T3&(!_&RE+ +M0=`0C>EV,#A9:Q@0<5"V4NN,N&FY3;\8&!WWZ\U+CZQR:75J"',:_ZU:=UG` +M!KS/LXBR$#H0KJO,=4'\2#1%_<T/D"#3'#LR5J4QO[^BKF:](A=UK>.$JEDR +MJC6V@LS%VHH!,&+K>(0M1BBWCURLY(.=#+$T59!0K;$TK"Z!J5U!]C#6[KI0 +M$\&[T`<X`*X^PL=\`'(1!QE.%J=]2-<<N=K@KF%U;+8+]YJU8T))^UV,Z%BI +M-3?<P./1_G22W97+@,9(5'G3PUGPO>G>T^.3058Z">UX^]I#W!0.@0\^NHRS +M&7$/.K34H6S^B"E0P;-_O#XZ25]2DDUDG@1%\!O%8*'RSOPU\"C+P1J7.U9J +M0)"+']-@[A5I?,L'P!*7`C-)0KX4CM.1D7U'MX"[=SRW2NW_O+:PZ:_04)AX +M_3]#O/!P^L4":P4HLX22KR4CU*HWD1M@#HX85+IA1$^&*[R<!(XY%U>&/O)` +M3_@:D$MW]^>Q!AG-D`&)8JV+6`CNKE"3/;JABET)L.HPH`TO1FN&')48-QIA +M4]?]ZXS;&;;8*:_[.:UA0I6]24P.Q0@ZKXY<ER_'T*U&3>\WF!.$<]S+*=>= +MJA`!H$G[!>]DKDWA)BSI^5RI<[]HOAL:W-91%WP)MF"%<+GDJ:TG."SED1]J +M=@JGLQS$'[G%H5$2M,E1[+S4,@=/@(F8=-;V7[05F_^`_Z]GV$]+91,!@D=7 +M5;>DW/YT1E](=(9I'0IE<^")#)[>H995]["Q*5IS5E&@=>6CU8HTZ/C&UUWW +M;&`&&2*R:8NX991N)_N3UUBCZJ;T7?>\`+Q<EHIOSC;[*F!M'BCQM8E4,8Y_ +M0YKX+TF@3?2*:D_#--&*[PT9V(.V>SCVTGA.:HTS+P96?V?:G>APK;I.Q&V\ +M754D'^V]#,I;>:SZMT,C,<)IA;_KS$AJ5`N2QF'<00!@Y\83Z;@-XY'P*Z27 +MVP'A[HU,_]MFX9>2R2YE"BA<FJWR'YS;G:PHHBTYI7+`SJI&6W7%<G_2KYZ/ +MG?6GCADD=/,KW9,(</6*436/0YXEWCWX%XS78<VU!N3/\`'R;CT2&.'P=;UZ +MEV\VVQ5*1*.DHP8,_?/%S8T`;3(?Y._&B;PXMH0=1K8&997:4/H(8E"N<VK@ +M*>ITJ`\EK8G['C"AO7"L--B?%*OF+5ZI>W`JC"7$VB*;1*&C__+>T%JF>&[+ +MH*JRT]E4%/8@=!J(U0"*%7QW9%,$=LI/CR<T(_U7_WST!:S*F$:D^17$=T&] +MV<0'51*.TVEYK.[S+%4./%-VJ^]5FHN*7M>J/M%DQD%W_@P.W_)]#S@?YX,2 +MZB\>JD^&*`D83<O]\>QR1LRW8-UN4.5MA$H1]QD'=/P.OKF9D-?X%V6%+$J# +M"U;R8B>+)^=W%)_W]5SHP<7N?K)E@G?[N=A_D>D)?GX+EOEMM5U<Q(00(+TZ +M&CA;@!ZS@J[M1**5BPU/%MZZ)8O&JOE(FT0DJP`U&:WGB8G=37=';&)/NX1# +MBT2B#0\)F8G`?OV%<]<+D2/\X]."9JO,\$=`I@;?V_E<3A#2$94DUR-Y`5L` +MJN:47$!=MK.R(Y59H.JNH$Z$6^DC9*M*_78Q-]@]D:H4I'5[ER?ST">Y*_N+ +M)YF[:?F+0@15&9#CPSU?N)DARY,G*GT<F3DRKE^\MW/>/70J7,GDH=!\SF'H +M1Z>J)<_%+3.]^"ZA)J/D=9TJX)3,RON[?Q\V'Y6-QKP,'GFIMRFS_O(&49XR +MSS<+,YN-3:M*M>C@>TOJ.NMR6.2U:Q(78[;MZ/P/X^;14P]\#4)Z8L=5C3"< +M<`;?-<8&)+7,)2DQD]RLIGRGTJ/`^#5#J@OQY%/=XT$/^=?C&NB(@!`1]K3; +MH1]Q1\^):Y@1P"Q-+K)L\],URFD\W8!:7:]G(OA%@,GBYENLH\E^-P^*]$<9 +M,1;),P>1U)>[,5M/SW@'6DWD_;$&)_62ACT7&O#T#AW0ZALL[`CN)TD(;F3$ +M\-04XM_J"PMT'E,YJA6%;I!18X=$#:N)!RJT&O2\W(YW*<"):W8&:5"8SG=J +MI7[3N6J.`XPL#SYO7(+S9)-_E/D`EF6Z9O"7_5Y`20N3H^URAAU++.>/JR[Y +M\<PRT*HM@70CO'(E?PP?`)1656W0B(!G=1[^6T?-&+*\N2[,%A<<_A(-H5X@ +MZ]N69PNL*[HF0+_WW11IUU?EK++7F87`G_J/#%;E'"BXH43JY&PI10(KA#?A +M#1>RH8.FX6&!'_52H8C@U8!1"H#'\0SJ3#8N2ON1*6\K5@0?F03AT;8C2=WX +M$'1J9NRKS]>MERBU]M"^`I][);+!D>0<T1O![EM.X1;02L&@?X9=-D^W6L_@ +MO+SIVD,;E;.M\?DHI4,#:L?^*5*:(GT%D7M"+7-&W`J("%\C*-1=*W\S).&S +M'%?2AP&(YD%C@S1X$NR+FERG+U?-A@68<^5.1$H[GY2:C5!+`P0_``$`8P", +ML`Y%`````$8)``"B&@``!@`+`%)%041-10&9!P`"`$%%`V(`^W3W(VRUO[PG +MVS5`-(1K)IOCS+#"*%U"ZZU$?#:)#`^95A0NJ!W#>W`K/=IQ;X!/.E*&G;D< +M'S6J5JK]Z.C/3U0GY'ILQG8%V2W\CB=EO,^?Q78I(Q]]%>4=;$^_M+3V7#9E +MEO\[W&W=Z0%TSNU_&0]9'%A6RF9`3?F-$N]\KFM63M;+TT&&[#")&1MD`08X +M-9CA?K"(VQ"[_>:R*\NFI_WT16ZO1/^$1(244G,YL*+!2?KC3(;:$K+)<'>6 +M\W(19/O>)KU8G(*.A$P-@LPE+NOB>;$R%P/?]P6S8=C57_"X/PS+P"WIH6TX +M[@F$V<2&-ZW<9/K$L/.]M'(^%J'_E*#COC@1\-:YG+7%3*8?3#?1IN8S1\H8 +M2O*L_Y9[@@G6\56&LSK%K3A(<7\6;OPG77UVO`>_%G\3TE+5KW:12?#^E+ER +M?J:)+IT3>O%VGQU:@'S&J._.K1X+IN+W/%$[T/<B%,E^2;F^.GOY(R)U>`Y( +M?_LWO%6I9KP)B&F:DNTL!Q**Y68;V7M;5FT8+#!"V&W\YS\J/TF?I%L/+XZG +MU:X,T[#?2%L;=J-,5=&=\D7*=D70:_Y][WR'!M&,%S<))'`RY<K+Y7/Z;=ZB +M$9'WV?$6(3AHK"U:DZ:OEQ[>P=_GSDUW?QW+NY[J_XCK@I$J%L,)Y4A9S531 +M!AF+Q0![7:./^B#M*)W6\4#O+K/#GPDUAXD;))'O<L%KMP::*6+3RQOI?0$] +M-@.JK:Y][E_P%_K.VWTU(XTU%"$!O<ZH>9Q9],'='!>6'>^^YU]7J'F(5J5- +MHL="/^+;SU46LJJW/'%+2[+&=52E4)'+T^R7:(0/KT*WK&:OWKD*ECAP!I*& +M*LX508"(??K@"46R1<9JK%EL()&%9*;6=L_#1PC/*"$W3V):XC:#1^S*&''G +M]A?ZROJ8?GK"2!`<?U:+2=5=<!I(AME..*-&?9T_GA.$]@T?*E]R1F`^I:8T +M5SV6XBN(=JBIC5[M0N\BDF3EFK1H47C7TN3;$`P`8F@NDO^*A%LP$3#S$Y1X +M1);;-^,DPH"]MIEH1W"]+YA:MASLFL?DBL-]#G)VID4(;A%+8T3HEEJ@_97O +MT1L52H42",L9^]7J5U)*NE^[3CE2C>#1Z4X2CW\L.O%D93:'WI;87L#Z?A;< +M+P7C1>@BFA42CY?Y<[^Y__OA=\W2H(N.2VF!)8OI1C@A&F81!NBQBK;QNM/C +M_BWAGQA-G7=)=B[7#+LI,D_N+PB>8\(!F%EHR,_2WP=EJ*D$E#.AY-H:Q:$Z +M"2E:PZF^$VJ0HS,L;BI;@W`/L(#\8@Y]));X4_.=[GQC<Y>8`YV`:MW*[(LL +M"V.HS:&CZ9[233XFEF6+'Z%L'^P79TI<JN(@T_UN_%VR2&K]GS94A%ZXG)N@ +M['?GC$\/44D@>CN(PXZRQ3$LF'"'M&A7K@O+BV);'-UN547DHP!\VG9TZ?@' +M"T]P>4S>(Z4B1:_>;&A:;P9-R+/_C8<6XQTY1R0@2_S8*IB-V/F?^/[AF_J% +M*OZ0@QI!`U9MJKJF/%G30@UFZY^)*<P4W=(X.FZV^6M%95XHT::)&4YN$+3/ +M6-,1>V""RB4T$LDHPSRYW?*$UP]YZN+4BYA/*N8K+.9+^*QKJ9R4A#<S,!=! +M$8!&M(@TI=*O-<^4V%Z%)4%Z&UY:TLD3!>-08NGP?K+&RK.V!+`B8^;:\7)L +MAG$'7]\-:I6PNF`:FUEQU+D%#I*54`XL$Q'R+Q/.4P]35LA2%B\)8'>PA)>T +M0QHW.&E^?KCIR3>MZC<GMEG:*ZN`_"ZO&6L@Q/_O.1Z"B@U=$;(M<:*6%P$9 +M?ZNV_(1$-G\SGIA7Q!/9I#6T!Z`$X$]#]6H&O'I-=+MA>ZVD+"L#Z>\&DDM% +MWQ<%18B7DH!`(2T2=%Z7[P1@RP[E>``6&#Z9FH&_JCA4<Y!0SD?IQ"GZ^A#] +M8+"V/1^:LA.*ZMC_B2_$5`=7WUE]2*FAM8B3+FSI0,E8C'5G5+>4K`G#Y:'A +M_BB7<F]V\./\SNF0N.JL*>FPS9ELYYW$0(*S^*V@NK^D(KR3.`Y+O`I-/3\V +MK'=@7MVY_8"[?Z?H5X>@"#RBD)"H.[9%MH[0OJ77&+!.^YY(V:C`L,XW#&^< +MH-(3)][D9$;1SWKWQ*CTA1IC9(LCF?$AYLB(4HAC"V::GD.%)ZD6,7JH4J*. +M,UQL^":[9/)3L$_JI26O\XTT?F^,Z_N52X!PG7S<7\[>.X2Z%9,2#2O]?FKP +M]=\^5%7L8C2=BM/.:,##)+VZ0IX'OV\G6H8W>,X/@<_^@<SFNUW78H!>NKP( +ME(UW7;D"S2[CMP,2L<W@&F+8OQCWKQ55F]X:+U)]TP%-EM3'#60N!C;J\!W_ +MQI9="S\H*,!V1V>M7F$*O,^*T#%TY="]4%FAT38F>6HKMUASI@HM@2@>FX!^ +M$@[J-#0L;[\$R-.!=HK!VB7D(=2>=WI6N=21>$ERWO4RM]_OW#KIRC)NE)K0 +M-#,A.YYC?6#&:Z#4=H>^R^TQ60AI9#Q\/3NMAW47%I`(R;O#'<[%<$'#.*AX +M6?"5(""]B?#5>PPKQ&\\7DQ=R9RHO:06U`^/;@5_8[K#7A(^!")'K6=FG9H5 +MW'I#U5R=,B_2;X21NVJZ8B7T<1$D&M5S)[49/M/>K,_#G<702&-%C%,Q$>K\ +M,/QQ3$+"W"W;CW,*T\@/*(K=OZQA,D(J6`0#/"Z5XT65.=I:K5<HURCNK,N= +MF![V[(ITC%^SU+IIF_A]7J8OQ0L7,CN0QC&O0.G!<"TQ94&2-^H1YJD,X\EC +M)409>H/.Y)]X1-LP)K0>O8T<#V#X:1'TW-EO"("23`6TC/9%#E_+>B)SE`]! +M9V,$98=7+;H9\W,/6SV<<.";@*Q^Q'?+X)9C?>5R2RQB927U3(!9]8;.ET;% +M.VU!43T4%O*,0Z%^&UM=3T-\OPP(WG'U'J:J,_858,ZR#;?"X_E1P(N3I4[E +M%[CWA0J`!(&[^I+#/M0H)=Z*@1\F?&8-P":7BU7Q:\D/>;F9MM?,Q?ZQ>5+: +M6`\1@^C3W$OJE[$ML*Z"W[FZ^>2!^,)*0>+NZM&03X"X:%0AM=>_=3\8A>JR +M65C$AR[XZ&QM$0/)%T:'_AYB#A1.K,6'13QNQDFP2]ZSGO44PD_[6<$.4_@) +MA=#.#2Y>BFPR(K167\JAW]HBJ)S;'$EOTE!+`P0_``$`8P"GBPY%`````-\0 +M``";?P``"``+`&-O;F9I9RYH`9D'``(`044#8@#W\M,/\I_FF^>QBW/Q#WB3 +MU9P3Q!W310Z9(J24<#H%,;6S#?9W8'-I\AGFD^31>KETL:^^VWK8!MPG8?/V +M"%6V1IK[H7#T#A!^6OCB`(6.&7DM/8!)2AM)**28"8]0^5IAW*7WV4^@7B1/ +M:"?>P>BO`0.,[I"C-4'`'`_7Z,;"$LA)8W.(6.[`1\"2Y4[8.J$(:P<JH<LO +MXA)+`/\1T<]Z:90E54A>'4JMY0G"*V!6%Y.3[XZ'>##XEA4TA<,NV],9F,$% +M^(=A;!-><JJ+HFTI:DIH&,H,)7Q:2#CZ][^$$^INONG[#HR2?JK(R8$M,:4] +M86<JDMA8,4">6:XZ?;4"-U<@[0"<I9!<0$&@NPBR[G]5'P>36$0UNAB#YS]R +MV\SM(+CE.,!ZD0/+^8UE?&FU:0<`F?@RNHU%;EMRS[DF:C71TLX2+H@X1[B5 +MX,>6\?P7YJ6$_O<_A.NN9$K4;RHU1:=.W6WV$T6'$`BR*^,&'[YO'+77SR)' +M5AY@)`U4J[9'N6A+^>G6ES&]</1C6=/)`I.BXEZ+$>XAG5U/]S0?A+F>>I.B +M^AC<_J3(D@)-G"YE1XMX1G*,!'Q89:C@9O?<3'$/6`Y<2=(Q&6&B-SKKB(>\ +M]1#>K@5#AVQ9-7I7)V#U)UV=]PF-%O/X+ECL'0&#VUY#LU_<J69+&DQ;SA8_ +ML7C2;ZHS!@]S*WIDY[@36/0FA0QT'DX*<L:@+\2<PM"VV`9;T8<J>J2T_S#! +M^V!C^UBR++AL'T8]W1.":9?-H=83'_W>=DZ#8RQ*O-=S"Y0QWU"Y+UTC9A86 +M\'CGM^';X!J+,6'0GZ5VYO#]'J,R*@8"SW6WNN/]HBU'A?XT884WC<L#B:70 +MDQ=![Q/4F09$RE(BF*Q`,%=,0A4T;;OO^WJ2'S),#FJZ1$U*.3]JTH@V[;8= +MT+8DZ)U%#@VFZ6+('(C_<RGCZN!6/ZJ\UT!(X1"+7B`<SVZ8_#[48PF<$Z3Z +M(Z4@.---IU8K,,[I#7:=?1RDZ3.O(;\F6@WG)OB>#K2%O[TQ-@M-PL"'[,U' +M_P1C\YC[IT!G_3:5AL->Q)Y;EA&IT=K\(@](Q&@$3'0A]R*80WO>!0"0/C:G +MZG42!A[)-!_5/.*"2SG%"/8#$.;W1)O7-O&Q+^8_$@6$;Z=GITIADBW5DFXZ +M]:OAV>LM]KY<`,JLYUQ'>=\P0+D$F?A::CPFK/DA85Q)K4ST?M;W;@PE[#*N +MJ$AN1<OZ<@ZAHZCK$,1G?%ISZ0,P31J/^GXGH@1ZE6B`]1NR#>'3H0J[$_[> +MG#Y3GB>YI(>HQ8/8#*`')&-Z]*+'YWE<K-6_!,M?A,(=(#2PV;F.A(?QZJV( +M)9AR+;/$P&NAJP@XI(84R7E5$1Y-]/PZ#R:9C:"&H4!#T1#]]L@/74PZ4L6T +M3LX55`M&]ILGY*_`[,*<<PDW6U,'*A;7^L=$IP<*\$?_A+J+>OF'#='!#`_3 +MU=5Y'(3&`E]Y>^*QU=V&)S^-(MY"([!D-9,C*<?K,.MYEMU-NYX3YX^"@9>! +MAW&P0,SGM9W[1`S@SG;1JN(BSPM_>.(RE-C89B)THD@<BK(1F8+Q\11S"_XF +MFF!-9Y2M3&I1!1XD9L%"A4=*M6!M"AI8*)$GQ/8;YWXC=LQ-EEL0JY#:"=N) +MG=IRLQB3.*D52F8P)U"2BP8R4$],QSX.CO-*X1<:U@AQ+_V"->2.N-:-5/"7 +MDG40)O5XXZ]9U#FL+TF0OZA^#ERQHZJ,EOV,94X$#!:ZQMJ'NP6.05P_5Z!C +M)&IT.GE@_KFW;"L9"5/^T&29$FX-+U:P]N&6KW^^%QB"!A]3*>523(ON9V0A +MJ<A-B=*)-5?5]K%.LF?5?4<[UZ2D$+6+WCW^KMF#$?N'#>;88JA"$].C=KA+ +MF&9+^H89$ZTH&Y;"76GT%*4GO,+2K(TV+[9A[F18<+,"KIO^+^+Z]&^60X+\ +MZ8UA[1)XE]7E>;"@G;M@"7_[NB"I`0_6U-IP>U+3PSU:T,-KW-Z5-E^[I<E7 +M!L%8\"QF#@;!O(RS+^29*D46N$.ZC]]J\?M7X7C0V2!>*.\8B+TQ="D@7,.V +M)&,`_O1GB(*<.H+Y%II(URN477+#2^RJ*4B*/1S]S.OZ#P.]U/%+"3GS:Q=5 +M?&]APC33#.ZX^%PRQ/KVS76R]^(`1;"$YQ5(U%12]TRJMF;12I?C\<"BQC@H +M)L(SVS7<1'F7$I[.*-D#PQ:CC7^V'!U?KM6=BL'1$AW?79M3-?&'+`SPWW-^ +MASVYZ%T:XC=8A3S]8$FF$K*VA)?G],LS2*4P?6X>ALUO<MI;%UT2\ME:189R +M>&PW+G:?8,@QT3&^^*:K^:.XO:$3VU6<Y8?:0LL1^LZ&,+G+DI+#LR>7=.-, +MX5_+#'DT`'9-VO4+Y9/:<P.;PS38/7``.=<W[<9I(BY^>'WD6HCZI0(E`(;T +M%'QUXJ=^YRSQ)H$/H(UZ!`]^!E0-UIJ/VG!@3THVRX7O6I&X>#,YXP!)Y!F4 +MW,,9,TB&N98*2K[!A!0-V6=_-W2TEB#2'/K9E&+#U:T>2,-D-)Y+/\C]?'&7 +MSDD^JU('TXA56S,/K0T'CU5O=,!-3!3EJ>U-#7%JZ39,+%L(*GHT1*"=6X"N +M^:>.0NUK,!MI*+OYG+`"A_80UA?>WGM0_U!#YGU7_,7+N%_#*/]92W5$IOC, +MR-S=F*2M5=-?/S<,<[`W2B#F$`B!!42"%J![)%&^E\D<R9VFW@AQCF6/A'R\ +MZU[4^'F[QX.;0J6;H:3X$1C6:K`P0"@@GB;C.^SZ8*_*^83Y>,2+)RGNP]D` +M47Z]`U`]]0N\J&QGQU0-S\PE=N@L65E>VV+$3Q2'D_NJ*R^2Q.$!=I"H>9_3 +MZX?4XY#_SA/*)S323P!O-IP7_\0=-9FBR6M0498Q<L.<'$N"AC.[ETN"0\]X +MXW$!3,@;;*9Y1P36*-!W[5@E;B.XHSGF[J_,L!LW^"0I2(+4*^OY@)EG2G2: +M`38MJHD^V3RSX'JK/R,BK5D(NDD-CJ78VY(I!"JANM8!_`FV-F_!F2+_=&;+ +MK!?^`!0,J<'.;RGACI26WJWYY'05):E^%VX6.7\I(N5-[_YSY>5LL_CV#2%P +MTQ/*M0QJO?5Z\ZM#$;0UBXEX)$W<@H,WLD*;@@)]S7%IC6'FGVZ=%%@(E4'L +M#1%:*0JT9,T`SE.E2#5UMF:_C<M/"51&7P2BIUKD]58+,O+"[(V,5`%JW-A% +M].\#S)255N&;1K,MAP$Z1VB"9"$4,/3)FF%+EBLK2X<,!\R>7G-!]G#25$"$ +M*!HC2JM$GJJ(Y&+,H"1SRF/8)./_HB*_XD$,+1B^!OCM@HVM6E/VL+7=652J +M=5CVY&):J]`:@Y]WQMX*O4+JA#&%((H[Z_BY"R%]!'I:D2'QAB-`F5X>;.8H +M[BT-)B4#Q\(_T@(!SXL$.IXS*-]!WN=!N-_@AZ!_N3:ZS6^9M/W>UQ'ICKR' +M4>K6/[P))9@[DX:4'0&=Z?2]+37PJA5!3J1*\P(VCP/M9W@2*XBZ5_1`$\U" +MFT#U0IBW14O-Y3'W:=&2!W(N""[Z([^H/,PX<3Q/\:\VBPX%?;"3CD$.W2Y@ +M:P8S._-9-<KA.]3P(^7ZM0?%VEAA`+SRM)!QEC&<L#;UQ^9J_.,IG)"7&&&T +MP4QU'8INU]Z.KH5R2_``K=X4<P0O#8D2ZY^I*C(>ZX>L?$6'^:KBAG=RFP(< +M><N[)C:Q84<[UC;F!A^)AY4:>4X#_X[^B:WE:K9,?8A1\Q\Q)8MH6Z-_+]1( +M>"^0\@'#!-6[*/:QA.N#?)V_4`4@'FXPN9*,UUL+(:CWMF"M?K>DM3_FK^R, +M1)&M,KDBZ9#$NM[9:V';0`6F<XU953)HY!&L?KLS^N3N9<7)./WYM7Z7`BZ$ +MWR3NQ$B6HI>^78RZPK0IC`3O32C0%Q)^.;LQ"[-_T>(>&T97P!Z39(T-T^W% +M2(E$.*.50G*EA*JE14$9(V;`%U[&I_Q]]U1)+4M/%#6O2G(-9DSS(.;64<K[ +MH'AE$<A9C9+OY$;&D&&<X84=K>$D^*AN&'$,E6]';E6!\`->ZN>@8#8?T':( +M4YS9L-8:+#OQ<K%+N$^7^D>GF1<S%97X/Z9&KGF/8E]=_.1QKH7*5*X"T\(E +M<DK=IQ34NKGI-SP2A/'B2,X0ALL,=QM>EP#I5PO0N9;\F?0ZH[G@J)W2(;UQ +MC&$\.!YZ4+^'+#;C"0!?9596LPQJLJW6IVN@GR&";Q89(VPY$*K,8M<YJX?P +MLPL*G.O\JA.9>O#.I:;H"2^EQ;'SKE,QDR<9=U^Y.W^:XF%@=&DO=F_\!IB^ +M+1[&6"(1>WX!^8D2.8D6+YU'MEVQ\58ZQO,TJ6`/_FL`V*S.^%S_'`!4QX^N +MN&YSDZKL(A*%^Q=JG%*PL*.H`8[FUOE!/"KBZN@^N<2_I`&7IN$YP@9W+A\D +MLWGOWH!`B?/HZAR_7/?R+#"]YLB"VT&""V/$-8%O1;?^#!B?C:4#;L0Y%%]" +MT_/2I&DA9U+R5_B6]U0</+.,=4`221+Y:#'5AFJX4\M9B&'#/,Z>>X[?E+\U +M<$EO<9'FK8`V+5Q6OM_.F"T#'RGZ8$:*K<]PO;-]85[X4(8*M*/'22IP/WG@ +MPSU3[2@$%[,CO])M$DE5S6:;U:$>R9G[F#-"'12\%80-*VXIWZB$0?WC^)Q6 +MJ9K^T7UED+:(XB"BD(?[1"B7?U,5XDZ%R(-@K@`TK%D=N0'?/O7$FA7K2WB7 +M(([PX]NFTI`2X\,SP#BO,2VYKYZF4U.[EWZ1QXV(3WGVGNF].3#"-`S23WX+ +MRU@`MJ:)\PGQ\MT\9(D^);^^\OF9UJ0TRFMD67UDBEKVT+]FV;*=<\7W<BV$ +M`)#V94[PLRLB422!?]I;QY/A(0Z#D\*>D>+1<U_00SV3M5<[HU<^ZZ?PMCJ< +MJ-E`6+T<8]Z+ID+RS:H7T>`F0DXB;_WWS]V)'B7<LO^#K%N6*;UAKVRA4,<B +MZ?BK]%VANV2SI&=\K(,8[D[["E"%4/6U0.:G>X,!D`KIVZ>_`1MCX$89E]L; +M#.PV"Q7<[A*Q0W-;8EPY:AEPB8I@<QH!=:FD(UE>-1TU?P7@]&C,H&OUNU;_ +MI7QP)0O7Q+<LW8J0B9SGI$8E6J='1$%,JBQJMW%HR)$1@`1"5S-R&3^-G9X, +M9Y*/'CI7<$-\5L!P@9NTTEI\RHB]TZ\PB=H>_&@UDI8]@3?%DDMW$FS;,CG& +MUV`TZ>--7M&8*DC*R,#T6R$7F+N5O&W3A1!E'XL0FIV(/_MNDQHL_DG4#$($ +M6C39MX[+K@L5&#[D#G=FD!'W!70'1W3"CB\8.+BU+3L_>Z-8IC%&`-%V2SWP +M^14R9SIL%^BM:*'3)6W%V)\TB6?E4QY],&2QRJ,\=RN;!P/HKI7!&V-I7"0Q +M"(;*6'M]P%F=_O0U@4<?:^_7)H@SD@BON'0.&LPL/4T[.V8[:-2@IC58-1TB +MR=<\%)43:Y[.Y%C?LV#737E:X+126G9*=(0LU4Q;$P!>F\O/IU,NM5LB<Z&H +M5#G%'8/K&3G_;CX4?1%))O%4KX[RC5=P(=B[C(*)KD=N61)6%]<I/'D(YR2" +M0];(4M*,;\+:(W_\>B+-+O8"]-H4E\Y2?)Z'CW1*>B-:<UD:<EJ2'IW[J=>" +M,+UJO3O1T9=].(&1SU8VT;GE!*U(Y0*PH4%%"7X/T]&#%V9]B=B+JUO9\#MK +MIW!M']+NGG8O"SW\.B3C*Y,(%X/]0D'.K79&1C#"4/X,Q5N%0CT#O,*0:LIQ +M>+%@ZF`<@K7*2TP>O/&D0_35?.GIF$NHW<YY*5!+`0(_`S\``0!C`/BN(T4` +M````E;8``&LZ%@`(`"\`````````(("D@0````!-86ME9FEL90H`(``````` +M`0`8``#B#W"YQ\\!$895YPJ>W`&)/%;G"I[<`0&9!P`"`$%%`V(`4$L!`C\# +M/P`!`&,`C+`.10````!&(@``K7(```0`+P`````````@@*2!QK8``$Y%5U,* +M`"````````$`&```/%Q3`[C/`8D\5N<*GMP!.E56YPJ>W`$!F0<``@!!10-B +M`%!+`0(_`S\``0!C`(RP#D4`````1@D``*(:```&`"\`````````(("D@3G9 +M``!214%$344*`"````````$`&```/%Q3`[C/`3I55N<*GMP!1FM6YPJ>W`$! +MF0<``@!!10-B`%!+`0(_`S\``0!C`*>+#D4`````WQ```)M_```(`"\````` +M````(("D@:[B``!C;VYF:6<N:`H`(````````0`8```IHN+<M\\!1FM6YPJ> +KW`%R<%;G"I[<`0&9!P`"`$%%`V(`4$L%!@`````$``0`C@$``+[S```````` +` +end diff --git a/libarchive/test/test_read_format_zip_winzip_aes256_large_xz.zip.uu b/libarchive/test/test_read_format_zip_winzip_aes256_large_xz.zip.uu new file mode 100644 index 000000000000..5af7b50ab59e --- /dev/null +++ b/libarchive/test/test_read_format_zip_winzip_aes256_large_xz.zip.uu @@ -0,0 +1,1898 @@ +begin 644 test_read_format_zip_winzip_aes256_large_xz.zip +M4$L#!#,``0!C`/BN(T4`````X`(!`&LZ%@`(``L`36%K969I;&4!F0<``@!! +M10-?``71[/`@3-8%7,YT3>IM,M6WW6<\@T.),X%L%.B="`.!_RP5.2,7!<'R +MTE6&8'L\!1DZ%LQCGO4&L-0`/'?XY5@GSJ^G%[D>`3[-+324TN&9,@<4=WM[ +MGPH?CSG1Y$4OE96FC0IRRFC:U^V2-!S73Q)/`!I`"#HIAGOTM/QD4,D."-9X +MK2M9#*'@:Y>Q\%=,H<\HL,*G-ES[*H<+,5?ENKV.97SU\7W>/0\!=3Q*G@H= +M><1D*F;KF&>OOR0@`98[I@(^>14W&Y!0KWVX2Y]R&#NJ3>D)('$+P3P7"\<Z +M;5$3[UI-U3.$Y-]9,"'R8UV7#V\0H\P6T9"7H9?FC%?`H)B[RH4OM!:8RS?, +MA*TN,ZWKQ9_ZDLTH4O=CFI*<)?<?!&]+3@.UBH_6B1BJGJ%HL&'!1'#20J&Y +M&I!G_QAJA47+="G4FV/`(9KA0F=I.D:52^(:_SYWC7&8<5[8CA3"!W?F48(@ +M:SV[#T-[#+_<-)-%SR`/^.H&K1=@YVXTAP"CWKQ1`J%I"4<EUIL.N*[#DW#U +M40.L9V51/V.EFMFQ;SA]V.]'7*WJ)MD0?K(:-N;@%C=$$?:RZC=$&@U/K($! +M#YA^Y$4<[O@E51+/,N9OX&Y&LY3S1:W3`;'-4E:HD?CYE0#I+G5G:T[R+[NG +MG_:A))T>98]ZT5]P3=$PLSD%<A8N,3"M;G6KL1$O491JATUC'7%=%S.-8&<W +MP[#^"V$SZM@&@WX!"N]<=9S4"9>6/R@W-Q']9+.#449)*8D,[KAX!.4A3A6C +M3`5T9UC&R49C`2_^(T:>!<+Z6@6X&TOI,\"[Z>?^+%+OB]K"6.N9];3BG9EK +M'M4IADMG0>>^4V&7[?(6HF@<SAJ"&T2[%F,I*"N/,89;[.?4%3)W4^42&'\9 +M^^/_<8.'RZCLY2^A2"3PC=`2WJ,4):P.2\1H%Z$9*&G9%\ZI8Z(CY8:'HM"D +MA%R`CS!V+`MXJDF8_'\*MZ]JF@]?3+_[IOUE]I,I!BT`YA5I+RJJ]H(,3#ON +MU2G)=%Y]L*OB+:NX\.7<D>(`_OD_$P$R*W_0&1R1ABXF24X`8+1$\W=`"=5: +M"/!P@#0.B["?:T3SQ>I6E,83B[F*OB%Q:&]/<]7,M2.3V[8FTET7*W_C4OLJ +MV1)B1#452FQH#^2#:N;"F4B19:TF]H1CI?+3%3/FP>X_8%'J?+`SW8&]&[8] +MS!U[&%_+NF'9B?1("P&T@9UO3L^%_=<RG=6&T`7`VH@"'2$<@B/$)4'FEJ`H +M3L0REBD18$+6O67W*TXKYXG-(HNLXWRKX*G,7[1EOGC>2;,<#N\)=8IT\?.G +MP@$7\DG7#N&#J27X!X6M%5W=W]OM_F*AX7@;=>.W_+0S]]00L$L4P"YX.V6T +M/[9]#6]C?Q$8WF9B3^7_0!'ELI8+V=^>C8[4-\X(`9-+E]6]:?R+J08^ML%' +MH`#U=`WAZ?<CQRI)"O\]0H]<;M4],&GV_G:5W(,T:R_N<%$"R\!A)`!K"A($ +M-(0,4".:F$)&(9*F.;3W<FGU?_[`$'W*R^<ZJ+,(4U!UA;GPRD9]@6M!VXP5 +MPWE3!4;"EHR)?A])>&B(+@RB/W:!K2&QM7Y'*C!L-H].XC&*TKZOX>C&/H2W +M\]/1^UTKAZ_7CC/,="K#!)6KYM6X!9D6`H*7(3YI+XEV.84>(&_4O5"-)PF_ +M9H+%6(_%<&6DJ+V)#D5]XQ7.>8P7WW!PA;O@U2`^`T@<9P:@*H?9(/>`JN3Z +MCSA8)*]:G_2JI_GPHY'\)6%#![^$:W+)KC!MN.[QVFW^DN+.>N\.;>E+>/UI +M/>4P`-J._(0,#T6*TPT9W4QTS9F*H47[08BQTWL,:URM#%E[3X82RYQ)ZOY% +M/.$1X2V#.`7VVDLL78F5.B^$UP8M/,M?3A#)RQ.(P'$UMJ040Z?5UVR:HPK> +M<"2>:Y.WVWJ:F"R,8J(75W9L'TK:#&!RGP-<-/?'E6(?:+#\ZFQKPT'SUFK( +M[Z>]&R"@55+@PY.+4@`-]N1;PL.$`&4R36"K]."2V(0-N#;"T/>=/WOGKE46 +M>_ZRF;7B\2>P]=[&C0TK?+"I"/V/<<M>+3X<C4:7'2WI64]Y#4/D3DYQL<X] +MKF<ILA$1-PZ#">>R__;U<M\2=>+\C!..0<&H/9?VYZZ;&OA[A6C!YM;.7N3L +MN=+4(JTNDDDRR.&MTI!UO[XQQIL+V62K/[]-M[!A8RF]WE[DZQ5QEWEECS,V +M57')I\I"8(BVSER=9>_HLTT?/]*I+CMYYS/E]I>(=]^=M\HQPPUSMQ$GBRF? +MOV/4`LXR41L4"P;YAQCAUTCRTK?1'"P-F3N[LHSPLI@G[Z^?5:HX^B;S0_U" +M[]=*M"DYAFAOEK*:K6%ZVG#6&(B;$5/B#A/6FXO493J;<CI6>6QP#D`HT(4[ +M9Z1XR)G`E8RL'V<[32+ED)5/10SX#YV-#4E,Y-X_&)DD>:2;<?RD$Y4JN]/N +M^9F>^QIJ&I1%W4X+9F:R.=DK\.$`9H&G0FVKEX4$X$GA</?W[$<<)U;B/_%5 +M@$+<U%B.A,TQ9U[;YH7VSR7)Z&=P2%=<K8)-!/ELK0*8Q=EJBL@%=!#0#J5( +M"'AB['E>H_5ZG?6!T+T.P/;-ZLAJ._NTX+9_0I0J)+[',-4L6I=6`AA?ANJ4 +MQ<%!HNX^#Z_G1IG,S$$<I8*---`4'.8&L86;+1E+G)HIN#3>P<IC)L[RYICG +M^N`",0.E!?+;LD[!?;9H68M@N_<=/S9_SPU!5"!A%.DWX<U!00MK8\O;J6@S +MMKW@H(?M?PYT_FTL)Q):UD2(B\-8$Z5+EZU4@L_",8CM.1^/5]G86@7@>1UU +MJ4PF=8_+N8H>K,_4(5/W>!0VSLA1[!(7J735+]0+?X[?),-N9^GBH2=PLTD' +MME!#C]K!7NQ=0N>EV?@J?+THZ*1?4-;VQ3L*"B7+(,`&&&8/*1#D\+@(T[A1 +M*)T!%?KV!(S9TIS)_$V>**"/KL3AMOY'DKO!V;37D>D7'T]OB8Y6/?QLRUN) +MSFS(T\(\[28!@>)(XZ@X@2SUN$%<MI1,V/_F=8ZLQ*3$7QKS,9G8P\&ZKZ/& +M\72U'"A/@B@YUZ:(8;5`'G?<\2R;)-US_/+L3X2"+J)58784U(W_SHH6;>!] +M[T*-S@-Z7X+G'(L]_Q[-N,D!ZKXR6:\-(1$&1U.?9#Y%-]T3&8;W4&S@CB'B +M9V+<0ZS(FV1#%W'MN`L1V%)G7_O8%<Z/[29XXU4E-8:).B@50;8OUF2E-5GZ +ML%,90SQC]`YSJ(HKY[D571]#$<+/K3/J;E9.3Z+_)>>V+^_!5AJP6410_4LP +M*<GT-^YMD/1F79F"F30A.<P#Z09,U!S,O7D9?=G=,E,`[:]4"%J4+YA3(`__ +MIMG]LCE58!`U<M%>.N>\(>H==^57IU;(SJC].Z"Q,R^/6S[*V"&%SQ][.!XK +ME+AHJD+1\=\>O?XW4M/SDT7:IM$O1X0EN.6UH[\TM[W"SYZ:B+A&&3/AH-82 +M2M[L%KC3,%1DU>F^`Y4K'DYP`[\FF-*1U;%5&$6M42IBBI1=;@"U49'#^[;D +M$=3&*M76<34Q"IV,W(6D;:J0(^7W(I8??8-KU1+JT!X7"(9.\J2_9[\![_H; +M9MQP`:BQ#Z,)8^NV('^"N1+*I.TY*(+^OD#*8[Z,EQ4M%,T"E8WH=(*A3U;@ +M&<,P8*>JC?MMXAM%:J]R,`(J.[&^=#D^`N&]'Q^3N6@6E@M9'A,M+W%%HP5* +MIBY0+_P;8'%@KW`A4W-@U^+VLHDSI\WB6-LIBE:\#XTW4JUW@WZ'A@03(580 +MM)DE*4/Z>`2+`GKJ+QE9@UMCM@;;?EE[`1_/BJBY8^.L/M1JIX30"&T5^V\8 +M#*@]+A^JOPWWEM)E57F])NJ&?YYSI??(!@(DKU/AM7.A=I&,(I4)?V`)]C<: +MUI)B#9GCWUJXX@Z%R]C%G_=]``(R=,3(P(0UT_IGJ$7(-,1$5`#9UD).S41- +M$`;ID?L\_4$QAB[Y<T%MSULUIY?=1D=NLT<O\"/4J,MKT<=PY94=S04PI1I> +M=>*#@]+:N=@.PJMK;AMIZ7"4W"7K!H<`UEZ0K_\=<!W&X*,!?(>EU5D<,EE] +M*%+=A$R\W[@M#E$[THO]\Y-]LE[@K`[?V_*^\?2)"PMT^6D*@0X2$BW%7D#D +MN*>B@D@'%'9?F;W#I$X15+""EV`E&0.&M`<8IAU?)?O;OSCR629,,(,H7Q&; +MAR>^I+,M,L(T&J:78_S8F<"/24$VV>-(7B+@V4'ER'S!LA`C15D7Y2_+?6[X +M3"M1`.>Y\RO8N]JF/G\*"QB^C"NG^\<)SOK&NA'T5IOH>,X7%RB[(XE?@G:; +MQ'T0.=0!W'JV,,3`^E>X"`G>%<XU(M7&UR7&JGUR96*\480F8W@RU]_Y&&V8 +M(DA^RLQ_!<M$.1\01$.#%T+9B>,&8$)C1.K?%$>F$^SJ@I!.B>M/MFD^,H(R +M_-%!0*F=.#!G`T<I1.Q*:,:C%XLO6!$U6\%.%_YC^LF)U,Q7>_K\KS7A>S%^ +MOI+]@-I+T^H7354:&[0:#[AL5P`Z+L8LX1`(*&Y'Y,50/&M^*3&@5!1@/&C` +M!?AW6CS0];[VSQSN%3N#C]J:6OMQD]9\,D+(;Z1=CA"ZV!/534\N/ZU);.:; +MLO^;^L/PP2T*']M*`6BY36`F]"FB=5NDM(Q"YORXH^1#L<AU/H:I;_Z#SZW? +M_I_?<9N=X\NIX*JQOCJIB6M-40AE$NOI[S"WF`FU.);`$JLS(Z`&:/RC@UJ/ +MIR(7&S!GX)P4F:R&NI]F!DOS>91%`J&'4)@2,N2T_+LO^937/UQ0N)UJ&+>! +MAXA&,V)9]2H>CW4]HXM;CQ6,)$(34;P'X6_YXZT>C,RQJZ#Y-0JZAZ3LFOE+ +MWO"S#%EHK;^??D:.V7L0G$5AU6KGY!L+B+&A=2R!^WPRSD?"C8:JHZMG=@P@ +M69F;DLC%<I5=-&J708C:MFJS]*8=1R(^F!B16H`$KGW%/F)%+]SE<']OJ1*; +M?2>*D:EF.KO`0MV=K*+>H_^2?X8@EKQ9@:M_FG\#?5W.+6/_87X'R9+KI%CS +M<A@Z+\.<([L'1")AS>L5RCH!1=P]5N0IP481<":FWD1A<XO`QSF%^)T%^2QN +M"`PN?SCZ=K#!L%M\W^8UP!@.]S)V)\!J@<U6F$EWH<>]?^?O36-R$Y-AMOC1 +MK2'JP\XYE/.P'U-?I3"QG4W3D"S7/90`<KQ+3:U?85\=E'YP*Q2_-K.7[,2G +M2;@K!66?OT[2D:6.41V)-D8US@#IN7/<,2(#<>5=*T%HB]_\B\1_<Y7NQM&= +M5QGY^_DR8>J>4U*#C%L429S"%0F+S^5G/SI?_3V1M#16'A>*#E!!^,?.<ZMU +M+J;U(]5T?=28ORSB%5X/0N(JF94P?*9<(![S)087Q8123ZR\MKL'3:%.M'*3 +MP\_PW#=0=951_#2\M:A)([&=)`+7JX<2?:!9(;#GLR[5RT74OJD'Z`'K!2A& +MC7^(;?`"U%)#"F.;NS&`O\$)L#=5CCA[J/,_$S*I3'Q@Y'??BM;!I'AH@^[& +M9!WT:(P`]9[M9I.55(W7-SQ<87B%H$B:P,7*HZJ(,_-.2AG`@U?HO)D^/_C@ +M4CQR@=,/7<3<$8X,2JI&J#V6PKLJ\M5[1R7-:_&-SYS#4_2>]6'[_M<6UI+5 +M7_=%,.T/.O%VGN.<CD3+)TUVJGD%(Y^9!7T6D`:XJD3[-DO24I2K3X_?2E,W +M;YZ[QG^PHTHAH%RQ7!Y8MWS<VD-8?[K-]:\\7[*)_(/6*%:W)..N<_4%D(/? +MS7[;X*`VFCK"-]<#0W)3Q$-Y;H'X=+2/R&26@$I+(ZZHG1M@2.J_U$N2+*.N +M/2`-*A:<)B[ELQ`U%2YP++7A:^I4#,`SNDC9;W!J8(SU!J"\1V-/!MV8WQ=Q +M`T$'-+F55D.0"F#8=`E23**2%"UQ&*45=_WG5Z]5+>"3T(>+_L,QP4BT.3_G +MAM4@4M%;2:J&;@TGZ@:_,$'T8V(2SXN'T>FB?KZ%D<B!7\"@SW(*J:3KT=T: +M9C:]([4;+L?,;GTB1E+GH<JI0D]3V;<`,$7=P.QRO0-<(EG(#+"0P>3W>667 +M0;JQ-U,&K:`M`Q6Q,+:>L4H`>#U^.!5#O1C,)$_;J^<\3X^+(*7Q/S9+]=I@ +M<4$H./@!0?2(=X./#F="6V&QS4$.'+J/B8*W/\*BS9$1'=B8:L.Q[FB7PBU= +M@<1#.3:&6KO,*9M[D-19NAC)8I:2"*2/FV4?'G$D4*S;3--A!/+X45R[I^'\ +MK(0CV!DB*?Q@'O<H'7[REOX]3B[L?_JXI2=(\GWNI:#+2=ZIKXW<G?J^QR^9 +MH%J5@GN9>=PY%I2@NK`FZ"`Q*ZYAC'5C=Y"T0C`>;/;`B`M_0P2]YH,:M^V' +M\B<KO]`>37`9*=A:H!?,T0*P\P*OU5H#>8&M>TV7T_MQ-`C_]`<^'1.\4=CO +MN"!6]:^>MK4),DW#`6MR-I7C>YGT)[V$QM#ZEHW8UO,\0H$,:*?0=DP#O(ED +M_;K+FQ*"2PYWA-!X)/1RHQME*]/7MX]B04=W8(O&?Z#5[#\PJ%X\Z^!_REI$ +M!="A"4_#1AX+%UVP\J$+M"R\5TX9F0;I#;KV6AJJG?('WH(XDJ4-V2ICSK`M +MS8MA,MB>A/TNM"8[^C>IS2#H11/\#E8`V3HA`LPR:N@K`%1;5K&5)^DO$3F[ +M>*$!UH9Y,"`G%WL?^#C2&Z][/!JP8XETB&S0R@)^83,2^ARF#NC2KX*G*X)Z +M-_`-XG"G,V'G\'#4RE?7F'VYHT:9V!AH1.X?@?+(Y)5SDX/9=]TR<+\?^#S% +M,G1("3\[6/-_Q%I2S?O@[8">3%F`"=4D+%/!Y./S"MYL/CR2PJ.$D.`PZ"5T +M9=%6C.Q<;>5[\,X-@RTU_B?[?7AVUW9S+H"(4'_(ON@WW`S^W*?%X]3,Z$5A +MH+G0YU>T""+R2,)'C)>1E3(=!U2O5&6^EL!3$RD(*V[-FOEN98#ND4LT7B/C +M%I2`N(#7FHXIU!B[N4"`[SN?-GI!&<F:VRC*?(_C%0^83<ODT4`3*#H?+VD; +M;$)HW*F9+4DP04=F@EK5`M<B]4VOH3N4C;#20"!+:]PQV]-QUZ@WK$DB1WJV +MF-`^=XE)I#*)_B]^6EKED4+22ET]]>JW+"=[6,FVS1"L%UPD1LP;P=LTL&#X +MD4=#DFQC"%8DJT_2WC;,RTMMB[T?LF.%T8;CJV)],K'`\R7H^U`I]5(.%='? +M-*7FT%/K(F`CY`I3G=Y,\S79&$]-GE.OY*QN!XCR">ZJO]!NDB-@[`B(.;1E +MV\)>73U+P92F;42/Z6MN#?<X!IO+MR*Q+[*B35#?D_*;5*D7R*P=X0EOR_6" +M>C*BH)N7HC5RQ_@9:"I]PL"64"DZMG%-M;MODG-F(TE;X3?VT-LIP0$\[[LY +M0=^;7DGO5LO8+[(E@HW9WA2"=='VEQ1*:S*Z/5<<+50IFXSZ-%+U@)`*ZO]1 +M='!O^*$TIAL]OXP'/I$ZB19;=GSI!:`.CB7GN&JT[N`/!J=^>&][)JNNV,AB +M8)[-X$W<N67E*:8*K^%6'*DLM%M3]_]/!P9M0%]>+,.JCG*LX`JTYI3X9416 +M\;0MGB5G/E.K&=J9"KL3C4D'RZX)XVI/'-RP]QWNK0]CM*#YJ&BV?0/?&#-\ +M/_LX75]"S7JE[7+\?`#4KJI6T`V4^*2X>1.*@R;(Z>`CRCFGJ6;%-ER.0VXE +M87`;=HTB!XLE74(@OL'4R9$%GJWMTZ9>[:8M9!!_(>D@L^&`:T%-.HYE7^&Q +M,*(/!)O7#5LS&ODJ&J>,!RX_H`S8!\U[FQLA"*&"[:\+($027=!.YF:EZPGM +M0X(H'N-*(@9Q(#3Q;DR3LL9-I#=,I.\'?L6ZJOXXE7K!@1!V1W(:A.9\'+[" +M<4^5/DTJ"LG,]EXR,L:Y0XKYLZT:K6T0//**:Y]4&2J]$A&PVJ6[70X:P\0? +M5)CK0:)*E$^2=P"%.58613HO>!LO5'!LW81FA4+0<06!#G;1`W"YJ`1@M8<O +M<2.[-X>2MB_N^:AXN3!6*K6W18I)T.=J_TXJC4V_/O:GN(;)18E7!U;Z\PXC +MK492*</,Z^\?RV0MQ*,'`ZW'SRW_PJ.[1'SWC7+74KBB,/YG)R4%N!_<')V` +M)#+-L#=8E7#974YA\1W-%&!&RO*$D]N^D>:&-O>3OIN1(=8-)Z=]I$>A%-9+ +M=D`$&N8M5J2#]N!VU8;0\W2&5GF9IJG#X8X>&!U40"RG*VPUQ[+8>XB?#O(\ +MC4-]?>VO1IJ"W1*[S`)UL[SX6G3>A%&^KU\AWZF[.L2\N07)\"OJ.6"X&Y9& +M`FA/S3F?3\051;F4%V;\4\888[42F)72,!3-J\R-^R`],+B)6$KIP;B9BVW( +MW\,L8RPL5B79[>;K-P,KQR5APIH>22""/*O&^"\W`GIWK%TUYKA+O5T5BC/K +M^4L33&4Z(&HZ!KE1Q^$1O1LYZ3_Q;\HL=@UC@NQ/.JFS$5*P]V0IMV&.5+Q= +MU)EO]7?:)=B/G+KS=DA"=ZF<FO1GC=C[I!6,Y3V:11C:M>E(2BB+5U8V3$O6 +M:$PQ>'CR&3:>`Y*9RN7ID[F"B5>3-OORV(=AGPP^IZ>:U+118%*'Q*L5V\:? +M8DR)]9R+'S7ZACPZTBR.5LD;JG3.PN[:)^V]=:M'-^A5)^9X?OC(N;EZ;\Z` +MVH0.!<?W_`+BJ%%JA_Q$"%E'[S0%<B'#@6'SK6B%'C^93C(ZAV[YQ]42?7]D +MCE"[KE^19\<)APB+T$8OMIBQ[J?`4W:"A![*OC\,5/8]1&_57<,B8A`0E?@D +M>E'5X;*VZWNOWMOQI;H[6ADL+9E#^AL19HIOO<1C%939#)V93RRA"36UX!<] +M:/1*$ID50`<*`"Q%O^O?,PM7Y"'_Z6@:6\?>%]#>'*<>X@-XX5"GK4INN$N! +M/P0![S"[\A`A4&61P3)Q?<GA=.0R!F?GRBP78&HO&'3%NV-Z$9H[URURYR8. +M13=R12I4A*M#X1T7\,`$'U-?XX.K,^7MAS5]&`3"7]RR;M'WJ=\%?!:1O#0_ +M"QBF4^@1_+YJ20P@$(]CI4P[DBC)>&4'B'R`6+ASZBW'>B&8R?(U__`.-K1` +M/?RY(YX-6;/#0>A_JE7?Q",L\ZT![]\&G2YL?<,Y5H>_;5H%FW>ITND#NU!S +MNJ:<.)_[(_'9Q7$W=PWP+I=@T\:IT<G]I:LMS=$M3PT&PD0_U2-HT&X>(PL` +M$#[HYLQQ-'?#F^]SL.'4Z$OF0G[4V$L`S.]2T\!"7^]UA7G4\!#QNL`I-BF/ +M%.:+((.(D<T&O-"HMUC!NY"N9YJTJ?0^'0A\C/:B%`M?^/%U<M7@PFM7):K* +M]CJ)5-FT*$-[$YP:?@X&L";Z^6!HG>0Q8J"(<;Y_4!0KTR.CI:LA<,P#WM:= +M$J*EBS=M@%JP>].]&+6F-(K_6,4N2@"M)O4@ZB@/:G#0CR[N3ZW<R4#IT_"V +MAP3T[G.%0@P.NRI^(X>5VT6`6P/FL[;ET!*O,%,N&\C%S<I3G7;SSN)KAKUS +M*]WVUFOG%&[U4ID8)+ON8]H4T#!/4(?:Z:KM6V1TKICH,M_UHJ28V(.P1&)L +ME%+^46]7[.+&$4E6#\JV#XDVT^!?./F?I6.$BX$`3EG#JKUO;/Z'"`S1EAQ1 +M[Y)8XGAHZX<%*#\([Q'J!8RQE@=N28ID&CZ*F*BQ40C;5QOHU]6>63DF`8H= +MM3<%KVRTI;84)NHBY?NP::WQDRR)NJLY2Z@7Y;R.VS-91++)R=E=;N_;ZE^[ +MXJ>$;!NJD\98`I97B1T:X$F:4M<88)1XU5"C=G2LF8$(M)^$.1KOJ$BHF7[2 +MZS<Y6?B>3NM&7C6GO)7K3G*4.0ILWN:.2DN>2K.1Y'C[R,A4CNC7`)8P5/<K +ME@\5I`3:O5,Y@#\(0&B,7NKT6ML"WK7WK]`^I77U9>.V+QTJ1T@E!"EGY?OB +MR8*>6DFU&I`FP+^LBZ+>OOG<8[((Y5B?0?V6OYKND.X8VWL8Z]6+I]M9]X(9 +M$DN.!ZU[KHWG("B7A[8KC8AZXH4]413^D(.1_VM]?\I>3WK4K)9ZH]4I!&Z* +MDV-&;>A>HMN!QC%SK:/^]:`/15D;PT3"_JL=BB$F6ARQF#Z!"0T72!>BUV'B +MZ]V&;%>]HCL+IK5UKIGJAKG%;]7V#Y`#FF$1]4C9A)?XY[Y#@XGB9?Q_<4"Q +MO,ZBT0ZV_\J^3O:_.RZZO8G*_@P3KP.@NP]_'B90TT389UWWSF?3FYHHBH/. +M"@,^24Y`A@@SM\KW)WDLYM-MADY]U45,6$T='*D^OR)6\]'&&+5I`@XF1X/J +M>^LNEF002[DQ/_3:D.+.HY]<<PA3#+N("5JB:!"'2$#D3O\]?26W2[15VAI( +MJX"ZK;!$PD$`^B2X)+\T::U(!D<91:6%8!.'$QG"=-80"O)=O!S/Q+I2EHWT +MT0*ZOE3"M>27XKIYBEEKY)B361+,<:T1CB5=>)WK^7VW5/+[D=:3E,DB,=!. +M#_5H)[H*NYW=SS*L04/>:#>?TXLJO2BFCJL-;Z:-S]L<?IUSN#._I._9Q7(, +MF0;UH)\U;/D<>=Y![O80WG0-*AZ7JX2,X!1_\U02OA6?B)K62GS:[1/^3=*. +M\3RZN&L..!&R:=$J[FMOHV2,V'!ATGBJ^1$R1:P7TQC.L\?$!67Z7X8:J`[J +M([&KG^.S(9,@-7P&O0I7Y^7N;!,NC=_R;)J$CD<M=I+H*.,QA(!*E6APBWK6 +MR1'E.^YL$UR=UB$<PT1!/O#X6-/HIWZ.IZV%DQ+SZ8\I!.H<3"U,_C.*DE.W +MF/(LY&4$>7IOF-PEP^-IQT`((M"-R;\JXPN(<@_6&._#^Y2J2%'G#ZA%:B<5 +M8\BE?0$W',1>Y5:C6/Z[TQDXPU^CI0-B0S#(\:Q:UJ[`VHAAU(:ITH&K"/XW +M^BB/VX[$,G\X;N\^0U!/.ZTTF`)#A^>G'D9GT-2/-T_LK=A.7[P\.=B06QAM +M`(QF)P1[P&B\GK1"!NR?F."G\;G@K(A!SCT<>%9=A`#!JFS.M[0+CP(`<DEU +MT+SJ=M8TWFC-Y\&,7CO8,!$IC)WZKUYG72&#'.E\)M+>F2)'(4O,&/A8A\9F +MW2!R^%:#<1$Q$F,CO+&@+"ZV+0\J,5H6?#[J^`$R93!]H.!>$OT.0N&L`&V4 +M/A[AHBT0_KA9O"_9D_4R697J<U#*F@PA3/M\?)U^<-:(4.*('R*>G(AG?/)* +MCSG,Q(';RE7EZHZ1JA>A?7O77G2F6)1SS^GR86FS9#"C,`\;&_T!$!54Z6SW +M,.$,:ZMNA(U=V%D)QN@@]7D[1I*2B@O2%M[<O>7P(2HZYZ#IR/IF:EP:0`[N +M#V*9AZ2@Q<<67*AV&$(56L*Y=-5EN\PX'^E^W<*EH^->3?$.G[!+2-$(P>>] +M*@0<&:7P@UH*2W;Y:53[XNTI!X%R.S;0C\\1%`S327RA=`O"4BD*S'G\HJ/& +MD=*?Y__ROQ;9>4C:P$C_N^';N>S\6RUJO<0+BO5)$G9"@28EME.,<HXNS'JY +M6WJ)\P+ZB;,NM/DX":EYK_AEBD4:GDA)5.YY[K?7KH"_/_M5=2VW,-^#V&"Z +MF"G=6KBHEDZLRON1R0A%DWG!$F'.RJ)V,B="Y&!M+.7$Y?"18GNM!.J2\W@2 +M%)[,V<^H0RI(LF!MR@#+7RE!N&K=S=QALDO,\+9QG9Q-'J.8Y8>#960N<'7E +M0&V`1RY_#K%KR9E*J;K('82/>)6_W/=QA@.Z5TW^BB_>*5FN4<R>?RC9(Q^4 +MA?FT(OF&=WK8VCBUJ<6==B'3^0](O3=^_=&WA>IFEVMW4,!LM#N.&1;R3AOO +MP'5VAC".)".,7=MS3_/:DV1/V%_LX5^'U[8VDS#7`;&A%%+W!>2Z>7^OU>IX +MXY@DB7E.@CXSTI:_6.FQB2VF_QM'"EWEO"7Q4?R'+2!]5)KO@SNW7.]HM!%M +M$]84XVJ_ABK5<:(1;-8:I3N#=J<44V$K4%$/-6(?Q.<^LM].:QWQ31QW;)>* +M6#'"`/=9>J'1"D7":)SX<-J",G#J5`JA_7$[X6YFO`/=4'+LG?8QE&Z*;+J6 +MN(R^W<_+X3![(869;A^#!;AC:'4!6R!^!=1WE:T$>KST@I*[TC(L4_OR%59B +MR-*;H,YCKGEV6A)F:VZUWY0XF4WK$$>!YV+-'Q']JU2^,8YZXYM]5%G.F`ZR +MU\93N0!PQ@)&.K^@:YNLC>"H'D\2R$]0M:[R/E\N,Q6L&$PP'>HV]"34=;<& +M^XI$LJD-'S3"`<'<UIHF1!EYH)$J98C_^IV/#T"+<130$A?QBPU@,JW'D0+T +M[!56[:H%&/Z_QI0!&:KJ)X8QDGF#!(L<,1<K-JJODL4$'[DI7+00:C;+MR.W +ML4I(1)2'T`4:7QP"([X[FR_->@14-A9_5.BPUJ]7%N+$M(`C-?IN:H5)TN&7 +MNE#Z&.A4+0%;4*RM%>?/+SI<$KSHGP[LE5<2"YZ5KM6)\K8&HA5%X\LF"8^J +MO*5:FX]Y<KMQ\@&$K]*:?%?&,V42!W,FQZ14[U8]#?]`C6]'^;)@31US:5#K +M!PZX5M.V/(#N#J%%%K'5K%TG>_AK(8G/-4$AS#@*CV+!4:1%`[Q:&56O,EP@ +M(RK34=!&X-;\+22BXT,R3:P@W-Y+GR,WJV)H_\8O/4`HOE&3F'8='M!3#5\D +M_AW[0Y5#0[-J;XX2O?3P[A<Q=:76!PM5\?L]#.A]8JV$\)Y06;@JC572(^Q) +M:ZI.,1WL'UQ"#PB38TMTD0@+T?9BW9EP(K`P9>I>/.K!UN('B$&4]>H[3TCI +MKXB+QW<R-_!34/DC^!4PW%I%PA<]5QUZ06SKJ&R`AWWS@29481Q_3I%F:;(W +MG_)V3Q!E/)2&<,QI>']):"($A2J^3?D-,&>V(JG."SB@%@04]X^I-)*[^3=: +M'`(\T;`H\3-J`8RK-]?2&&Q08BIW!6R,6>78),_P\\RCR,Z<NI3:X3`DG^AD +MQW*O\R1A.4#ARZH0*9#.$KN?)Q!-/Q:0$2.#R]*9.2VER(+BTT>A?8A\D#+N +M[!##\44-J$1)UOR=U&O+A_)%`SJCR2+?R2S9#[ZAJFS=]H#RKCW#,%T#IF#D +MVGSWAQ@.[>5C;7ZTK;'K&W.&$8YM98OI;A@I\BDVVH1$!R(BIN7B4_."O%TP +M54@\9]NY]EZ'S\]>*K'QPU\7_;""/4X)K,J2+P-GL7Q)]44E!\KVZU"8E9#" +M;U?TA]U_:T^J4UL'B"<A=XA?[S5PB30*+Q:Z1#8Q#!QM]\(Z6_O-;L"LM12K +M2._J*R^^AL1M!NIO*0F*Q`I+6(4&^RNG-2!39DOI,R57'Y7ETG.B]([Z+3,S +M1(AHJ-J0X*$B$+SIIY\VCOBR<.NIUDRY\PS"]O%,X':FH<GC<L$'^7H(-@C< +M39A'*2X'PX,S.'9).6&=\WL-`UG/T6;'KQ_Q(=()[=T4'R9!WZTB17S]-XU& +M(;I'Z^",/HDB]S-N(44^2S*?K^'O(ZD)`1VI0<Q`R$%CM,_0ECP>T&LU+&*H +M5>M!?)R4A+$)X*Z5<N5HK>]'/^=/L/K4>\+M.,#ZLSP05I2%VH<B7%_%=UPK +M3L.,_R"/2<=`(PNQ(9<BSSDLCM:I&@B7=2R_)>I3\KYX1"F)E)EY,X+ZD15# +M&*A#Y53A\7)WGF_X5@H3NPQ1A3Z(5(R5H9$#`/,/4H4=Q6DU3(>TB@D/^RGP +M:?P9$WBDGM],KR=\5QD,Q3@33X&<[GW2\V#AM"5V]YH&\39&L581Q.F=''1K +M).DV%$R'QAIWV9NC2S<_#'2IK&Q(7*,HI#9.B_**(AV9MJ_LJO_H[=%J3-5I +MBR<9R0C/MM17'DX]2L[CCG+:YA^0;FLD?;$CHZUGJHE<S4ZF'4EGG/@F2:\Y +MY8U%XG`=X;6SI=J?"W_ZT"^Y6QB1\&V@`M8>*HK)/WR\!-)III$66[W5Z:*- +ME-]F.MIR)W[X63SOB68@59T#HC_J-+B+A2OWZ&HVQF!$3+I(]_BT*Q'*'5\7 +MV&;:H/*YG!"Z+F=:SO1"4X,4CN9@OQ3<MOM#SL8A]HBE^5P#^AI(_W2H#H30 +M+D;!#HT+=2$H<NG`SU0MX\=W*?:]8EK3+F)+UU'-1!=!/OS*1F8XJ4]_(;H@ +M3?GJ\M>*4<5JI+7K+%^-.WGQ'Z:!5T@H:J^!"K.D*0FAUEO0"0T;62C)`=)6 +M&R/D50N3"C<VE5M@FR\P9MQ]#7!#2*<FE^$,/N\!GI\"!^3\>_%T'ZM3=<I^ +MK'3&?=[5>W0B]RCF3MJ`NQKZ'*;RWF<Z4$3HQU_^*.C2.0)A2Q>&6%]$VYP6 +M$$GHR%+65(HF4X+VET(-V&/]#8MLIDL,NSJ)(V`TBT0B<HN%8E/;STF'5D># +M&H[0*IJ9G[)\+'.E".`-_4-8R?!KUZCU1X-=AORXM%F^C>.'VANC:W!:N-X] +MSB$--<FQ]!)G=.STC4+)!@S]WIL,*=`=U'`$Z7$9[S2WJR_Q2J0LNSP`-\I@ +MABHZV:'17F%FQ[98RG7DX)0Y;6PO[3=]RQ?;;D\/0$&2"4$QX0<PK!(C'$$P +MB-!3Z'G''GYY*J[=#ZPTV'A5W=.J1E&7<?!HU2O9TBVP3M9'43ST6&55Z38H +MY!M2``)6'_MC\;^4=/[_\5CHA$B-,2>_[)Y_B_@U_.P:FQSP,'<O80G(L4U4 +M`N.D.<:0CQ%M6Y'A3FSXV,:L<(C%FTY9)J#NJ?1D@EDY2D];;M/&]_`]*4^& +M^_%-*:GRQG(Z;3/3/T!5[&WR=V!_-';`(T>G,@^F^"E$XF;^Z1L/NE9)QQ>2 +M)WAO7]DLAHV=PL:T#]"_82YH`@D*J$T`E]KJG9Y&(C[J;<EKPE+U3&1+4`L4 +M@.`JD:B2UJ)[L?]_OMN[FHR0_]X!AE!+JCCG^F&*++\4]N;C9@FZG$4JQKU: +M8F=`B'?W-#5P3@"AAG\%H^V^Q?^YS^)GF!=@P,GR[OIU3_"Y)DR6\78%2/LN +MI-B]T7X62ZF`KP[*W%=-3$O^B8"FH8G;E&,6)O(^3KDTC=_]L''_]@G6KJ2@ +M3I-H7*2BX,($8M5'7%-`2=I#C,YWM)32J"H[8(6W%'0I`'\YL0*/PI[HEVC* +M:#8,*$I6,B:1O<%F@W[<&E"OSBK9+36A:6?T9*/BGE/8]""T4:/^D^&R2!71 +MC-UYMH/5.+0[[SAJ)>!>@&A659Q8O9ICW67K([35:;1E:QXB\Q?-)1CH\LW. +M6K/7.IPXX@IQ#*`9/3IR:056;7%]`4IN+?DO$!/9&8:)='BQ<?1.6%+K`2?U +M-`":8#7`3;B6!H/KW:N@YW&;I?"FTBZEEWOC#GU-TE<#JFH'K\]`J1TS*S?& +M\D$$),$3_?+K;0#_FYC0QX?-;3PES,Z%0N-.6:4'@/$H&*)T=D%>].VOAX(: +MP#^O+Q.NX!^D.:E<PM1I?X>9#S^+'%"!R3379K92WR^BB*7`RN8\W%%)+[," +M]!EL^W[A,,?RBP^6#F5@[K1KB_]1QE]4UU%UG2W]5YK7RPPK[+?Y>E@09VT( +M\+YXJE5`*PMAX9@E6&NKPD4I_PJP"IV]GO.<-5&8MS!^KG2V/;HTV[+D:S,` +MX#NJ+(9]`!-UHIL`LNN9L;;9"^<6IU[V7E=5'<Y4`-I.S6N(=Y;0(/J=;B5H +M6Q_GYP'*MB47<P`!IT1#:"?FL*5;`(&%[&:#B'GK[T]M*)Z\KU)Y=L=F;Z7$ +M!HRHU>9"BB"A]4%2:'>SULUCV0-+/?%0UNH:^K]!%A6$EYEK*7"!_X5E?*@C +M4'\[WM'1YR,BXT0/"$TVJCP'\6>SOJE\\$.)^T/<N+6\+BSH.BA`TXQNY#95 +M3@(![4/Y1Y1=X#MEKO(7@BW_";G)Z"C00A#Y-VPI^-"K:$.Y'D847(8@X8"- +M^B*=$_V-TYI(KT2T_:.%OS1-#G]M,V\A`<:1O*<'.)<\!(<(R@0:.<5-?IOI +M@<M_K`;6`PY0/\?0#E[DIK"'!/8$GTY3OO=`63P386*&69R*"52UCPT5,N"C +M>2J^:UPCDVB2:DO=C*84`/W<JQ[;O!&\^_^COW+O8_@^>>)>9Q="2QD(^)`. +M-?3K"&L[?F5#D(9+Y5EP59XM="!:OGP`0^;/E#S<NZ)7M9696`NI*V=,,9&M +MZ`R/#^8OM$NVQCX_6":,=TVW%IL[^<*9`9<A`E^A/MVV^L$A`M=^I=;3(H// +M+`!R0>**>K0#XZPR+@D5Q`P4(@0[\'+@%:SFH!V57BHZ5&BYD_D4999L[!UZ +M?N[+7O*FM&X4R]B(=%1!F%90]%*I_XBQOCDV]1UJ@=@GV-3Z/,XCH/.8\`R5 +M#X(4B%)FRTA'.W52DZ%$5UH/<83.E2'5.M>D`C3&HH31C7MS>1+7*%R^:>87 +M';1"E?"]F0"P9T*QY?W!"/_8UM#*>'+$".W>/$TXVJ8G3?$4KC#K$$577&0R +M-ZXKL(\A&4ZJ?X5KUW%<80O@A,1AHXH;;@J/8C/1W*Z,%1&K8@1X@+)Y.;F) +MACM]]-I8A'?H9'EHJ:J$TM?."'&QN[J5K7GU5R`R[2YT._(QKTL6ZR`R]:7\ +M350>F'%_4H`KO!9X]R/>OF>#J!D<[%<\*2Q^C!5T<JZ]AN,U-EY'T8$9/)_` +M;./$EZ13##[MG+_WI]MP>9.M?LGR*T_Z"J_T[IQ>Q5".9HG:O;K#3CYN<V+I +M=5A?JN?ZDHN)CU;W01E<;15_)83+!TK"8#+C*_<^.C:Q"!SD2N9+^!/H24-% +MMHW'];NDQ%Z]OG"`:K(\HFQ`0B1(&5P:#4)Y*="`&]I@:JA^2."#I=V5=.%3 +MJ8\HYSTHN*X`FN*UF$4`TRT))KQ(QH*L5IZND*4=T\IZ"6VH+9HG#%+'"$&A +MO)+GNXI(CPH^"KG*>>PH?%%5Z6,G$'+OASH10'.C=D(C1`/;PKQG=KJPZ,2Q +M\G*29Z:D_SPJK@'^%[%KDXI?^8ER8CLA(UM*^N5(8+P\,/`DI'&J:U7V8"![ +MD]B#*L[8EM2Y[(/<%19-R"Q=H)+5EUSJWVUFC$P<I9='JDK)1D8$0OL#2Q+M +MF,)>1-!+HKA`<^,S_1M*BTZRIR(`#/9F+X;O;%V6<X?)WVS7Z(R;')(W/ME= +MVS37RA.M.*L-F1M7HR&9>V0D(PP^:N(K).8JD\J%DW^`#+I>0[\V!:N:NE2= +M5ORW!K[R^O?(CK:[2RI-QDRS5X:=!/C328%(&<*(W"<0(,54.22?O6MI7JT0 +M&ZK_CSC2,IN5AYHVO&J7'YL`AH6%R),;1\0P"?UN(ONXCQI(B:-T\T*0V"D, +M;BAGM;2J7]%U5$3;-:M?6^"-#J#9L&(Q<FC6T\VP*%#QJ9\\//>=XH.=]TQV +M9C\2Q:/#3GP^PYD`)5?E&$N`\HE6%/`P`SF'D,)#N]"RLV-4('<[G],>.QB( +M20]D0:(E`9H=6&HH@DOTU#9WC&+5P=8D5)7D77`'3>O&<MH1')Z"H3);_L2Z +M\Z(C61)Z-"_JCPW/G3B&["K+Q2$K)UK+ACXT\'&L8RHRF+E8`);C2H"0\$\# +MW=[R@W#'2<'S<@0X]`AV%C_/]/_Y90@TQ-1R5\><((UL3E+V+6BPN<I5#V97 +MB!!BVB=MA4A'@\A(9YR>OWCVHC&#'G*>VSC-[U)*.;X57T[9H_"0]UGI>*>X +M6)#_DVU\VL.?2E!6^_K/,?WK:#"[ES/2!4W382?'JMR-^C_JD4>Q0M\$7=DS +M%A[ALQR`8XV.AP&@SBQW=M1=2U\+%Z1D>9.`2ZWV8C((",#?I4`4I0V!.=Q8 +M\P<(&5TED5K9!%SJ*VRT^9VB<_"\,8<@91CN<C39(5?3F$AW5B@?DF<]*A1$ +MCDQ1U`:!TMKO.ZTH`K!R2P)O,!Y:3&X8$]UYO7:I/[<:=#'_ZY:/>^8-AFLY +M"%2CX.S8"O0K'^P+,\F[@6;L07WTJN/;9@I?X6$JDHKHXL(YZNJP(<#P?F[Z +MCX:@A;4_VC[W7V%3"?@'&YUC<`=X?Y.W3]FZPV:;-"=3\M^RAT2V(N=M@5Y8 +M?%021ADA3"FVKSU*BM5FSO/,/,B,1.0Q2FH+)FM.Y]#,FN3Y+5E4<W4,/FRX +M-A9%CTI<V,18O[`K-QWG77VX6`4I/;:=W6:Q4+ISQ(*I.C7,7^?6>O-'XA,V +MF,AT/A'HDZ)VY>FH):@DA[E`GD6WBUN)!KKI6S*?`NEI]]OO%RD$QWM2[BU5 +MBH(DZ'%%-ADSG`6E^^(T39U>KOT3W'.;A%L(%GYJ0E.#9O30[#-L0HJR<.&\ +ME?/H!DU0B^J!]\]YO\O6,FK_R^1N#;T%J^8U*W5;6=*T^[3XBAO/92<@8CB0 +MEN+<+(DM#HW_.`,EH5'ZK&(;@O"6^`O&^%$?E0>4/&A]NAOP#B-P>CW(0-@L +M!R4:+W:0+F4?"`LK.)[+3`0OLSDY""TS[5<<3%?\E,9NHR>Y.Z9(]L'$Q]%I +M'R,Q,QKH=ZREJZZ\=NSU[;5S^U'`TP/='F(:.#MZ#8@[#[8FF(H&7$N1V.AI +MK`@@NX^\R3/>/_`+Q.KGIEYL3M&X$#P`_S]`OBQJPQ^Y'#$X5KL=^N([IS7F +M.X%SS8;@QID[RA9313$LJ!Z18</1+`4/,P6GVSVFKM`_YLY*_'**Z5]ZZ-S+ +M3KP4MW@=$5^N2KU]A$P;9H[/`$IC%`<A60F40,N0ZSPTDK%-?0/M]/(+EX3& +MN[X+D1^#4Q9G\,9X8#S.B0E`HCM%>OSLKD]/+#%.*1N+?*(S2""9P'_P'UK" +M-)TTG3Q.U_AW)-0.<0GS[CN)7O<F'_`?H(BI;+<Y2/C\C!.KG;M*PCP:LLK! +MFN.YB[BDL+`AWZOQ`_;9>5)]&1I\-6@C7#6+)I4Z,`=4HX6!(N'YL`U*=EH7 +M/0U(2?V;:-;!"3VV`N6+Q?T1RXNKMNK!#)X_E33UZ&=^AWKNIH9K8=WK/A]R +MY=HCK"U('21=CP]RW7O+.VP,K77*7O30:08GEHCQF;D6_(66+OG%K:IB[,;Z +M%$G=M"@:K[OWPO]5M-TR`=WF1F:19B?,I&E4^MY+?CZ0"R*I?UC48IWRG!^= +M"?/0?U":XM8/J#G[8Q8,<\7.`^-AV_T],*TW0P5&O&C.K=V>(=W`$Z\97!6: +M\?2R@#!":'2!7IF\H$#5:OON!U2OUD4BK2W(JG+IP42\][.0E55+:MP2N$;< +M9=:]]>705DW">4*NS>S3I+W5"53BYLCV=-**1AQVW:J%T%=@]DJ9Q<[[N+\X +M[*&;5=%E[$5R),<RPC!-L#X^_U;3HN"!NB8`GQ:INR;/>]\E&MC^[C$*QY$' +MX/9&=)5*47_?UM3.[40QRJ;'KY)O=_&C5=PF)5]P1<7[=,J^D.7](8$Q*\#` +M4D%@3<[E]UA;PV.9&3X4T4HE!N<V6PW3HH.;&]7O<,?U=6<>*3"_9CKM/NHX +M*D(:R\>B%%=?U5<M]U=UQ%6QY#N+*,%[XC[4Q,N<O`&T?GF\N75TEH&K]S:& +MID5/-"?,J/#$$<C_JG-B9YGS!S?.G(&KC5[_;=1>WWYIBF?4WQ`<GFW.L\FF +M[<B0/O'I=1JJO`EV`7WLC#M36R-*$#VA9<<ZR$+^+)$YGW=/$#+']H\PM[@\ +MH`-JX.X3G]12YDI42O;H8)@A$CI,QA:UT)54*=5ROUAJ8R6)?;Q,<GD$@N5A +M:]9R@Z?G>VV>ZDT"H2#7H',]V.13;4>A[\5T%Q`M-<V/0CB>R]^:R[]"%^BI +MI_]A_3%EPG!V@6R-1R40J5%057&N=>(4QR-WB@$TX86JG2<X,$UA)7YJCK!> +MF#B9Y71=J:PP-HD,K)VGW<)Z=>,),8*KC&R/UE*@E*T0H0'@\ND]<UI7&+N6 +M,W;Z)*WU;`Y7-D#063I;%[0,3PCAZ'/#"A?NE?R!G)^Q*!LHWQ4XR6T:*8;Q +MD$$-@@-#=FW$,)\`LJF,H`8AJM]KQO`8XO!,%5S>N=AZJ!K:%.OXA%<`&034 +MFI1ISC'"903=SDNO&%@:4C@"2=HN2#=9>R>\:YW7Y4AS)KS!8O>N_:IGJ%9O +M$21-P<_!4#\`R9\:_%J,Y.J\KL#ZN,642;&46+>7V60$J8F>C*5"%=@^@L@W +M=#>A\^%\<ES]),23C(`2WKOS:.6;%5:@O_M\TU_#12F[.@,W(&3*?=@H[[K> +M"LV\;8QOJ"D)2.;?TC@PL-4$&3):*B[3EC;8N]"&2VH+"+"H[5H=J7W[/+T7 +MGH,#XMDNFUG)S_M12R^40_!"LOYLH-FH(W`I['*E3"JCFE@<R\IM$JQ;63!G +M,%$";3+9C:<2<]\[/K\J6W@0PST#:=R?&!W`':V5C6J*D2\*:#!J3S_A.9?F +M<`*E95_C0*D[GY%@)3,O,R;J9P&U"U[DLH4L3-SS#O69,)N(:TST\_63M)FP +MK_=*.AA)`R58JCB+LH[?S'U>?DU^+RS@ZNO<0$Z.4(8%*0``D<51\W&,1V#K +M6%0I2F1!4'Z#@`8*[%%$V!1"\Y(A=BO<5CT;F'!IS>>\[C$!FPGP@`%3O6K9 +M!P%K9PX(QUEYS))5AL3*6$B;Q$#4[\%2GL']WN=*T[5QK]28G.K4[?K2@0UF +M<WQE*@&J54^1LZ%4$R['H)VN,53S[`',7Y!,K9C_&+=(0]Z5A(U];L$9G4*T +MZ>A*^LH1N122!I$?+51S4CQ#VIB9&/W5@C&M5#L\T28+(51E^<70KPC<:Q2% +M))F2K\<M&YN<[I%.)H*R]KD#C7YY0=.OX:^B2"EN3<`EUH1))EI'N"(B1#RI +M=]7&D&PVH:=W,WJNZPNI+\."Q[B:)0!X-\*-'"+-/K99["SRI'QC#GDJ^9S< +M0$#RR80<P),*B*;\W&VK(OZ+&/]X[E"I`6'Z:,_+]X`%XK2+\$E9^C_2FRR# +M9'7?]D"M6I=O#BD1B!CR#E(C`&>?XM*RO*DLX5&5*!9NEM]GBRT2G^\]LTZE +M%".P2^*P%LI189L(!:JA%FO1#TU9\CPTD<!EA,KY%@%7(&^XY`GG%S!`&*.X +M8Y&NWI&;UF&(B_FW6=[D$W?I-,%YLFB6AK42PDY).4&L8RVY+)]B!SF20QNR +M3&)-U6F!8W-_HL>5&HQ12<BDS/I/KR^-PM)2;LFNS86KB=,\3G"F?Z`5G/=. +M6C;H<X*^9,\K:JW*3D+\7,;O&9I!#)X3^0N\(6(,[_DG\#9T9&ACWN!MMG,S +M"OHDT'\&?^+J5%.?%%.=LXM5N&^/5_DJTSS#5M%BOEN+0]\;4Q-Q*HP+<.Z' +MICS,QO&S_%FR-7F_?29I2)GU;$XR/BP:1R_C*%.29CQG?=@8Y8K0K=NKXK\7 +M1_HYH_)>'3P9;_<>`M3=>4G_(ZU?M<Y(?'T`@X9P"YIHKLI!]NR+D\OH3EE7 +MO@6N%@ARKB4[)E6'<?)CBCZL9TOQ;(NUHN:^!G[DEJDS$;)[08UFEZ<"8U[G +MBA!M3.ZN"?M8-J5^GNX!N[CLK`0MI]-MX(V5B+>>L_0T3>SD"HDQZ&);4"FX +MB"$ZC,+J%(^X,JT82\W>,.SQ#BH[W,6<A#`&O>C%`<18C<GRL79GT6A4VJ11 +MMU0R3`)A(6FLCRX8[BT?4MW44@-8?*8`O]#!&[7^HK_Q!L=,K$T)"]3FX>@3 +M0T\HD@T*<7"TOTU/F\Q,0P!6WW62R&TDM,8Q'<A*!``0>FRYQ<50"JY_4<II +MYG23@VL4C!](@`PS3A=.D%\7C\O:$,#FEJ#IL$7-Q'CDWJN.)@0R(J&)TESL +MQ^61*SN/NSNG-3SW<D'O4J;&`D_0!?+_YS:Z"&:IKQM>3VSHRON.0#-Q@&5H +MUYP.E$##%.!XK[:>8X1:OK#MHG-W(I_OL+]%,M\()"Y;JH:GZ]^).W6S=B_P +M3J#=1NEM41#<=7K.06:"9FE/1?#'%@S,2%U:\'@N+>9T3126<=P-6S+T.]Q/ +MX73UI3X:+`8>M:`%;`OSD\;-PQO!(X@I&[E5Y@],!.58_OOR01%.J1<PB[26 +M$P5W<8[BBHF<^M+JC`@XHI%QSP-T>1+R>WF>IX?^TQ7/ZXS&`PL`EA_RGV_1 +MQ8_W_U9*J"H^&K_.$.Q`DNZJ@!/BB0JZ21B]V(A0R^ZL$!M,X4QW%D.YP33; +M0*$OS]6`=;GAWL$O]BQAK2Y["2A=F)!_%^_-[U6.!\?Z$%C'T<J_'1_?!S?U +M"?ZA]("\-_)?0/&E"P@QN[^CV!1\\0%`_S]057W+3YT357!-[5CA7\4\0Y[F +M"145RW-(2&^([[AA;&&8ACZG2V4#*67!-$$;D@.>-,NJ%/`!X:V_8&CR(3>K +MLK%#EC3822.D&**+^0Q\:O1VSX9IJC:0/&:(7`*7WK98*%_\?MPXY*M$S(W" +MH33G^V.++IYYR)"7'K)A.L,*XZ$WR5#`Z-%;9^,6*IC,Y0Y:TTN32DT*[S[B +M@^YTZ)O7&CJN]:,,*&7A6?.NB5A\"$P8P;I$'=U??!#4!DQSO(<A47$%>8H9 +MV>A5RP)/0[3V`+$)?RV7)QMX!W">$+@V11L:G`9-^M4N8&VQD*T*D6GI3O)4 +M6Z4BF'2R0,(V5K[H4=0<V$]BDN!(^`:43(_@+[6"=H2Y=0:@T>:-B5,XN)S- +M[&K#3Y^IFMR0/:_A%4-UBJX:X`/?[,$$8]6RH_=IH]"7:A;W$`521J>8DTE% +MXL$#SV"M!H"/GA!UY$>2IV<JJ*#N&%.$`O3-Y<\A:%P=ZO,\L$;?^*EB?_SO +M'=J-11A7YQY'.4&Z9[=/#'GP^0F%>@^=]C;5G%/O<XN7_6P4NWRM.?,><ITW +M6QP!W/"&;')["7D7PNPH"CR8E-&,\</CBYID2[;J7C7A@+=(]2-R$16E6K#E +MA:FZVJ6-47?DR8M_K;<7IE6/3?`F><=$RIZ2+@=LAD$83KT?/5MB_2[A0M[V +M4G!I!0DGXIK%H9G.!&PRWH7G_\7ZTO[10I*E3%;9BGNI[`@F)V#2J'\7(@=% +MVU:TO^O3"KQ@G1XQUCZB[?TOD3.#-7OLXYN@G$]+WXNS8%XXG0E-W8A:<`Z/ +M?`<M2!DT>$@>J`UN5HBF:84,/=6*?!XOJA3A;)Z&?^GT:.'"X"JB7OJ?\O-= +M_9/N>I'ZS1\EA47>'[1_D?.O9JBW?VER56%Q#+F5_^Z9=JR^GDSJ*O*>%)P& +M"JS8DY:)[;1M,809'KN):K[Z)MZ\]B.N&]4([&:ZE($)>;(\$*PI_Y1X:`M+ +MY*-I-"$!P2290O$NC'"`\J;\W:Q=*'R\JW($"'C:S%0D#-;H@HCN"@;Q`0+\ +MFUXS>/$Z&=T[]E2Y*)3@F4C*)SM&G2@1/1_Q@QGX-">"*,:#9D<:#D0_ESF% +MGUD:O4Z274J]-QXT4GUDK]G*RZEIC0\,%CG"I"`(,VQ("I:Y>8E1E6\/@78< +M^SG)\;(#"=DMR\?)\I1O@EO&QQV^OS:]/(!J3[%LGNV<XH#=/Q=SI'<64EUB +M:S2$_J#`.D.;LD8:$AUT=[IP.=P9%>5UW'I8+7\`0AW0SF(<I[8+9=J3R$T: +M!?D33V6"/7T\#1Z1T<(#R"E_>1J[6U7L(3CS<S-H5WHATUIJE@ECR++F%T8/ +MI\4+H32$4U>0O6MP1M[P+ZI7!;49H)WDSO>93AA6'"GOT`$>N%*7BMV:>JZP +MPX04M"']*'9>8R2Z!^`X3%-799+H&2$\N9&[=AR23;#3M]'@:Q!K;"7L!IA/ +MKH(-/5-;G-\BW,B^%6KT0+<A=MS]FU1"(K?=\ZY?CE&,<E*7,T^S3N3\V?@7 +M"IWQ9_CHE;>&>^I>'2<@D68Z"\G&^2?D;Z&[+?`W_7H=Z,%<)Q!*^,E1<VJ@ +M9(Y)^#GN*RJ`?-`N6TBH>DRNT^VS&++K)0)%3#;UDUSK.P1"$7G!_(V<N1B8 +MBT0T1+;(,B,);L^NX9.+V8$D@J16$5YRZ'DCR<.U,%1M5WB/I3.0'`Y_KZI% +M0^T&*CG0*,<-3T\8J0FNVTJM,/>MQWN2IY25-NR%)&)990(5W2:((E,&,O>= +MMV1/)N"0&>A/E*KE%:X'F\G0+V?+[".R9\X>:$A.??*_.=/L;@Q'BR8HDQ)^ +MVI8G_0-(X==4FM30<1*;N0X(<$J9+P"-5NPC?(+5Z!81A_"-O#7!,!#=A,$/ +M+A)QX/_3%2Y@DK*>K0Y118:)UAXQ[7!;9_635-SJP.IA4[7S,8@:O$8BMZ1( +MSR7J(AQ$$YWR;.F1WY+P+2FRKW5.0%KJO"IDE%PH<TQM%"S=,O"642;@8,8K +M>@WIG7PM%MU^PW#$CB=R*OXRGD@I:['*IRE60`.1./XHS;HG!JR)$;N4I"S7 +MB0?"+_5JD[#[#`U.?_G67T+^VN!W2MLX)97'!8C&GC'FC.7V:$B/FD[C/DN# +M^C&&_<F'W8YSZU6N%`BH/+ITBCIY*G%@NSA&;=3?+V"M,<BD7;Q(<S)*WPV4 +M^[1>'84$L27]9*=>OL:<`0%UI1P0B1^*M:^#W@X-#J;@Z1&RL=9U68)F/^3[ +M_>P63%?>$-\B!,D%P>B6#4CA2$;S$SB@\YU^.[==DH/.12?K$&PNR6N#R+JB +MH48DEF)875TA%^/WG#$,[X``4HB1S1*U2.F7GEWJHQ!$<R2A;3G@!>(#_D5& +M/1*EU0D@[%;J']1%S:*'D<\N<IE;:[$4"+0D1]&RY<*#)+G]ZIS#2-.C0+"' +M<LEDZN+L^#YF2X:GJ")>G*&2W8AE_YN(ZIZ`)-7&M>]1.3LG/E$60*74(RW# +M:;F()V-JE>OZT&^_*'G$MUHS]$.OC-(^#I@6#3$5X!4H#D*3V1=*H_5SV)D; +M'1B[SPB,@`RX<G53526:JW0@AW3#"U;&LL)>MP<=-'B8"@)Z1I>R;!OD_T=R +MH?R7D4K"TVM_D;GQ:T?:,KY!A-BB26DPGXS3B&4,E4XV?-H`PN9/0X:D-2O9 +MK5Z(^E7#F4Y"G10'*64D!^:?51?$H?9Y5[T_\Y3GRN<MQ?=7/4ET@8TJ*K$/ +MPW:H]+8SD96@A-[L!`+<MFOZD('-0;UD4_)]$-7HVL-?'(QT$AD5(XJ'>,\! +M9V-GXHG:`\9^XVFG#1FRB/U*B[:#'B&G_A8H?.U>T1H.<3$P,#`XI:*8(WTS +M'.MX@ZZ?\)K"&P8]!3^\0I>-ZQ>"R!0)C*GAUKYH]]R$D@:RC[O6&",/WX"< +M`UEZ*M`6C-29(E2P6HX+"D%I+L(-:_6HK#?WFW&,L2HNY6OR?L9^6NXS]'=* +M5.EL(_"4<6S:IE7T7!S^?#<@CG?Z8#58G9,*4I6&4I$M/<2.1LZ%4`S.,]A+ +M8P[R*7UCL55HL!J1'"_N!J:YZ37@>24HYN2@RT8:^6P34+:QGOFD'&4-ZX-> +M$"%0"+^!90R&Z]I^7$X+"BUE(2O'")U[9<K3*\"MBQ(.0'U-,@.@N1>Z@9UE +M93%`NBW;H:N'O'T:4`QJNZ^^*96%,N]-47-@S>C)'0AW^[`N<YL?Q)_"V]`Q +MB]XT]KUX?MEWJN8NK8S@]0!O<0VG*S\TTC@GB$^]S`&B&*6`.?W]YY[6-`?% +ML(@TW<_87T`$;[6]T^M*;(24YOEV12'$LT?R<Q5>DF+*,1M`MTVJ0K3QN5:\ +MI*5"!C>%4:4Y$*,^*-KZ?N>,*A%8^B7SVZ%+PM^X;8>B\K>T"C!+YP@XS>E+ +MJ=B8*N8)`GEN&@G#IOZDHV1,AMZU\)L"?:2^Z]7SQ)Z/ABJ@]?957@=\]$Q/ +M;_#W4_Q3G^;G.#$?=\X:]JILWE03$FY)70*@)NBJ^A[*?,?1HN62Q`8%WP;^ +ME;O@O=I,2W^XG@1&1P;R:C4@]5`2!VTLR3;/%I]B^Q1?H`J-?J("EAZ\0:A_ +MF)BJR^[I_]W;?NXW*,(D&0W"#M_3_I\G[!)@8?!G!3W,PCO+76GMQD2^Q,IG +M;15<%=]T>M=Y69V_YI04&LB1,L*V[4GW3PQQ#DSZ3%C@4W"4F&U$:5+QH'1# +M[OC-KO!Z-@GH2S#&2V;$,R0VKT*0-U8-*7I0&Q]+MRS:/)L=V@0O/#-8>#"1 +MH986O*F)8>PJ=%$U+F,LOX=QCP##!>6;_<H`1)APS;:N#<XW`-:9-0E[BX69 +M2A$M?)_@G719*.'LF,4D$<RH3-AF''"#5<\"^=6"F1`9?Z;^#0L<A*I@5U@6 +M4#;]%GM^W.F(8/-<[*%CM/XZS62=5>ZPVOS<G1LTJ$'&&I[\S40OFRDSBHOO +M71F>DEAS<</UF@,/S7B`[=$-8&].<]A_%QLI?QVG(@W9E_DNE"?>R54`E!N[ +MBML(#)IPU\^B`:7M2EI(K`(#"BKH"0O>`JSC"B6EJ-CV^G]6:U:Q<?S]0G=" +M3"0I<D7OT$KL5<K00X<M)_W7F/N"GV*;7;:=RH[$V.R%H-)26IH8?4E\")MA +M'Q#NI_S!"6YA]<"(_2%@4AN1G_@P/N1O;&,KSIY)><6"U-LJX9Y:@LYT#JL4 +MR^MQ.^B,0[-?AW+V$-R8[<1CZU:-:)>.-2/U[;J`JW_/9`;;+=(<KQ+-):C` +M.&^$/2'>\';:.0+"JIK#L1Z^`1(B$K_FW\(4<N#600BCYG)4_F;*"<&KK1Y- +M)1SY.5"#0Y52=9JZ\Y#3_[2H*D@7%$/N]C."Z`]6<0,Z!2C06W0\0GS#WB*J +MZ8P\:PZ.F9=CWWQ\([`H:3*^'*4J]<RKN+Y4.81NSR5$6Y'NMN1H(RTBB6^4 +MQ`]WDLBJ/+>1]=EC"/Y]1A>R(_Z+"_R`Y62$XB(,SQ62!L8QVW_-3BK[NP&! +M/N4]1SG<U%&D(QI%0)4)NR+K^IT.%LK&KWRBZ4URAY1/_D+@[>L>`RHNR48@ +M842U)0KOZ/PM*^8JIF7DY@&H(X&1<6`5@EO[`L9=;-1?>4B,)I'`S)OMT5TT +MT@1W]V1Y&T#+D(JG4#=/!FR+FOZUI(BA2TLEZY:`!.]"'V>-431YU>.)^H]$ +MR6YP5KD716@U]:?S]/JBU\QNN@Y/>L`7(CULKW&H;MC*5TO`G0Z'J_Z5[!6D +MK&&>7#66OX-Z'R::L>OYX)S4SW;@H]!DT?3!?L:189N/>6O!R`H@M[OH8E=+ +MT(0O,;)U]6]K][C!]#TGK50P)4[M:3DBE".N4VEG(R6J$H"N2;*'+*!?^<,> +M]8Z/X;B*:21I(&NR_W[H?37EZZPQDY'W(^$&C`/335X'=`%BH-=H??Y.,HTU +MS!UVI=^O2[',E32UMT-#L0OSA]F3FC'=F:3Q@_&D_EQ.3D%XS?[3\U!+.^;9 +M"@5H'EM%25>#8NOQ)-QTNH*_U=J>#A48C413HFD0?E5::W?3W;L5_\PVU%=` +M69=[Y_/1:3PW*2^+0+]\T?&;YWDOW`,L8R7^D+"PU,O3T\\NG/W`CJ?M4P&C +M_H!9=[KHL">0;`W)D^RJ:H+BVA+:^I^"P92;5KOZ+VP9=VU`KD04',4KE\Q@ +ML)\DAPY*BA(B$@_/2Z+"]_JK(FH7`[PKZ&;!YSA*VB#><T/HNHT2CLJ68US5 +M[&[2T2$UDI^U%5APZG!<1$[=!`)]BF^EJ!=9ZLY7L$8R_\&X?T4P\#,'74!- +MBAP7H]&XOZ;<:._2"4@ODPS(EVWJ&G<L!O;:O&/E''=7(#("-/X!(0))ZAV, +M+8&_QA+N@>V2H?;[!=Y?.:.4^/>IUDF5OBGXO&!VS)M1F?J$N@A&?;USHE0< +M?K$3)O/@B#=/CC"7,9?D&0$U[%J8<'P<1@2NAS?FHBU];X<3R2#"L^CVM[^, +M]Q'.E(BJ'4_:FV?=&WGJB!DB)A'23<Z\L+17K!)(*`@BT]\B#@(-1GPJKR]( +M'%1#260KZ:`[)9TTZ.INZS&+"6^U(7N_?D9[T+Y"_74!W)S4N.)&\HN-7?8J +ML:`H\*[<B3EQAG;3QYW^A^0,;-%.LW7Z1F!P#(KD_TY*8ZKM]`R,QK$9NG/? +MC<'6)E<$I!L7QIY1TWN5D`;()KM+7C.3'6K9ZZK/0'+V$CVX3X>#P]0/I=?E +MH4SN-<;)6F3!<0K;;_90I/4>`'4C]&F^>E)56$!9QJ]MA#,8.EB=*+Y\Z<P; +MCY339VU-.+0)[%RGQB,?`M)JQP5/;69@V1J&SNNTWGPW!5!["@1#R+-O=8IY +M`][F=1`7N>GJ$E7$]SCI8O[M>=M@1N[$?@/:??]"Z,QH99/8>)&@<UM!FZZ= +M>(OUTJ/I"'YMQ$4?=X,0D(ZN:=SX8U2*T(T<B&+[H]2H%C^/5^7N:_W-8XOJ +M8>MC?E&\`,L-!)>MZU)U=0B)WK4>SQU'KMS0/R7-%WY30'GQ8LG1D((WF1I@ +MJ[>1\6`="$62QO]Q'Y74(N`=5"C-5)K.9O8$$YD%[0U[S:.?_I4+-?;AQW)! +MS`:?W1GQ"8CD"XLC8T+R!!P6OWHR*@H/U,CCE^WQC/H2`@2"XH-ZRD%'.4OR +M9/LT$>R:KS-(/A<'Q2_-M(3)TY*3R(_ZVJ84HO'@6R<Q#C:,221W>HA^,DS+ +M(N[)6D8@\733V(><OZCIVG7`L],`W@B/R0`J1&VC\)I#6=4_O?+*<F1AUO[* +M<VVR'+*?-0[&="!L!ZR;PH\5'ZQ[5H8\KB*N*3:7!6%8A2=M3]#?*S*==%"Y +M4;<XBO*V,I9)(OJXUS3_*ZIRJ\HWZ%`23"4GX_#7&L7\5Q&.I*0Y<<Y)*=4Y +MX-K.OH,%^?9D7..]`HWSR;*@%6@B#^NSYXP&-V+F$US(VGHTP@FK.\$FH<$N +M.[@R.3K%(MY=TX'QRI)<\AF:B/8B'ICO'RE_2V#*P4'@%MQ82KT$G:^`D'%R +M<W]\'7.NU)7#0,W'>6+RKV8P3E0XI=&C76*]X?Z0&&PIJTD6<)DGRJKN_5(L +MM9U1FRLBCXK"X-6+W/V[E[MG,Q=I5QL`(PW;K*IV<&\PS:41855*-TO\4X(_ +MYN'H#G=%Q/1J8%-7'>&/4C10>'WAK552-;%"L*GM$8K60'83A'3<4+^'YP<A +M6G7/#^$1CX^1"F\RRIX?8OZS$PP!=\$1@V/XO<W6AEM#T^_>P[%L"N4'#F,# +MI;/WQ@7_GUP0:+E@+LKW!'7RG[DV(^B*;B',3`KDYU)8QW(F%+J!T-\&\LT3 +M0/HK:W<CWYP7023TUFUV)=AY?4I,^5B)5G!X`_6*0WZ1=10I/Y$N@II=N#HA +MBI//C+<4',8UMMPM12UILQYJ(;8C\WXKRU1*K-%_/$3@2E_595+#HUQ@\&]* +M+'N;^-F8J-*[[KQ4'\`KG7(`!&]R,$\@Q>9G0(;NI2GOX=9))GU^$1!`XYV) +M7<-RTXPR?L7GUR=)'2=</F29!(+Z'NE9D1=1.@]^,$1Z3&3=.0W8;T$E[63I +MMZ0&[+!%75"\*QU\`+C8N97-+B05DC>9VRG#RAP``T(4EX5##N]+#N+:Z&S- +MF5>^&.C0F+ISY*&[]6ZHJ=J9\%JY`CHKPO1AEPMD30/+B,B/A-95WYMYJ*5S +MVZ(>C;_J9`<T5T,/M/I!MW%L58E?$N&@A3]IWV)0^[C^".1D>I*B.V"ZQ_T` +M:$/Q^A2FH6C5=X^7:LY@YA@5%J:0`XC9GL^"KG5KSVX7NJW>J=NMT%5,MDNP +MV$KD"A).VEI^BTWQEV<@CK3MC+G&S_YS\AO2Q:FMT`^+GQZ773R:OV,@>8G= +M&+6Z:4=5UU#!#US"=L2(L;7:=HD>S72%R)8;\F,&G^(]+&*QJ-VVM2:];]/L +M+#>N%U%O\@H2U<4C"0-VUKMD9^ZC_A.B]O((K0[?]I,GS"'&TS[K^DI[5[ML +M&5]N&`'[R5?5D9B#J^EOP>QT##YJPVH8M5XM0KZ[@/AO>;;W2&GWS=UUQ7S! +M[@I"O2T,_O16^(-FJ96J)N['DKX"E?=M#UK9/>^QBH%XQVV7(0CDCM3I,@Y* +M`-Y4K^4R4_0#++==NQN"C0P:E.:G'0N:QS9&*Z2ZD2RQ2F0KU;X8R+>^5D=4 +M.,)(*+.4#,_MV:%ZBI%`5S"5KH:Q3_0C>0AVR9K0_8BY#9YZT$>KW2G7O84( +MWD/0#DU(I;+D7;*6YD?:X[!;D=#B!!6;I3_1@$R"*6#!/UY(_V?/#%'J]ZL\ +MO0MJ,]!_9C.L+05V`DNF^9<$(#<ZB&)?'U5-O^$46)%@77$:%DHH^E?O&-(T +MZSN4T.P(%89@7@>)@U:ZV'+T:WX`WWWEDE9LUCO^ZGE[<:#H5",.Q3:0.M5] +M,!M`@M$6>4T_MI7C5UV'=*+4#XLVN1?7BIN3+P7F$)8O2A$BLV0FEAOC^,_K +M<P&L_I#*->BUV,W,MDE^_(0%(YOK><#6>MQTV&0U`G&0W&HTL\VRVTG9+YI- +M$/S.IVL_;TM?2.(%/@XS@L61MNW\VN#4-I%F[95^^/O:JT$0D?LFO=;L$8Z, +MMV1*P18\G)6^>`N7OSPP`LIH*M1M(,_%T@%FEU.S<LZ6R^B4#ZKL[S%H)<9E +M<OGH;1!<5N6Q\0@T+@IO:KY_Z6W;!I65D:TDP3S667C9@;\&[=,<P004G"ER +MJK9,@3E&UGGOSXU@#"JBUH<S'W23U3<2R-.12WA03U-L(A*YDOP==`GE:2W] +M>C!*H<UH(/"C8;*;5ELB;7"$5K[FJ0<&V5.$ZZC_$"/;W)G:X2HF"[.9T_S( +M;MB#:A+<)1(+9T/1,OF$0;+[I./*AF8"S-`8S.IBA"S-.B#@;]C2.(H`G3U9 +M$[S1M8:!3*4,4>L,BB."[=P,<8JRFA..]2IW*IU8Y>/=L8[3@^1BPB:.?I5, +MI,O^5Z^M?FB:"G@71HB+";SZ7J>&'@D]#Z^Z#).R770=!K):X^#_%>,B%+>F +MTD^H2FEY!@W;'=YF\K5-_UXW&:'U(P$18SZ1[L=*X/ND$T/TR!U[ZI#E%&__ +M63EV35W$7'3/&=Z>#U\>`YV^Q:@0GGUK&&4CL9"D":>E`0=CPSC?Q4U"V=^3 +MF8B_`4'=A&),7C1D(`=**H"_]?T>VSG/N&#EW_Z8$4>\@J9QTY.<M_:"!DPR +MJ)G"+Q<WU\3B2$"*,JS@F*-%W/_!<.3S^(5U:=`B=M_61(+OQ>\A,O[G63;E +MWV2^^20!K3OCB)I+36_F*:+G@\KE*)(%%GX7>?+ZR%%`6UYH)2/ASE2EQ@$G +M7/YBGT\=(;=&NI_*CT[$.ZY!9/T31B;OAG$3+K^/RG1"7*0`F\U5:S-GO5UQ +M'@.XKWNP3.`V=`A+[C<EEXBNR8215[PWNDUD^:6K68*;O4$U5R8MV;<6)8`Q +M#A<L"QMT!%UK\(PJ2K]>AA$`^T.%&5W+1A3\5Y%S/=D(&@@E+,F*5#!>H32F +M!.!&A.T#6?EOZ3$;H`5T$P-R9+A(CY8%0A0XR*^[Z#+D[=]YK:0N8J4+S3GG +M@?('I!B7]IA\B0KIW`G7*RNV7?.J:S/P8012SKNNRP5LMLX4=CNAP#W)9FT5 +M#=7(/FV4T5F\WC(W/H)%_R6*!*!S[JX]@BHB.-C"@R@<KV'@V2D%OEQ<WO++ +MSB>\-FC:B3:\PEEK,T[X:XB,J$8@^38@)Z8\].98.;_JTV8N]YE8380$,ET+ +MTH?`^WN;F(S:C)X+':'<I/@>4EEP!44(C6ABD#_#.R`!?(*Q/X2JK%H6)UQ1 +M$"4L#C>59E33F##0_%(46\]41U-:^VEN:/,Z"1SALDBL,N"3)BU'ZW)0'=)8 +M'?)KEG*SCI]_JRR'Y;,K4"6J*+Q4MB7-.;$\OU1%4>5P7BYZ?,NBJP???^<" +MN+CY6S%VD)IPK?3E9:I^3DITA%/J7>[Y#N18(+C(0*>'^V,Y($&C)HU6+EW( +M2(5)*U5]!)S_=76UA.1;#;8GF!--G_"A+)3F=0(/#';:[35)>%-'!?R,<_X( +M'M+-YR)0A3Q[[@D\KM<G(EC\K(FD0"6]8MXI%RG^X".OL@2+8BVK08!L0(GL +M#FE.H,F'[3YZ3?Y,1KUDT%Z!5F1N&\*L)/]>X*Y/3_"VX.FUH"NV3672]('* +MU5\EI_?#'ED_7*8BM()JA";5C+<]U*8XXG/8D3WS#/QOD#UEY6/IHZ(I^$B- +MT[;X')T&+<Q"C]=G7#KFVX]E&HGR)W5Y"P991.028-S:,H$##6IPXUL[&ZIS +MNW-LW#Q&]Q/NU53./W>L6JU"`/I7X6V%[<KU5VXKR2DA,6[EWW3QL#?UUT!F +M^*;.7GPR'(*GREFV'S>#4;09'P99-%_H31]]<;:WY^A1<Q5'*]'>\?UDM?U? +MJ%WD)V8CB_;S([9=QHI`#!XN:R=L%)<]5)FL[/_W,P^(OW%;Y^J$;,D/J5*< +M]2%S$90<\M1?12-V"2C:KXW0E^_K#2M6W&D2P#%L33\&'&.Z,/AJCEM:DE2C +MWP)5>Q:$[70-J9R$K6*GFXZZ/$:>A\IQQ<A^@N+\*?7!R>3430"OJLJSJJ,W +M>KJC>K#3$8OL\<@K=>YFP]'T#`6MU3OK_T1L;CQHQMCU^[[%UR=ZAV(!@Z.O +M$7*WAR0/CNB%@_(*ICU7Z#&IP)R^N(&#@O`@AEEO^Z:JF<)P:'Q;_.7YGOV* +M$S'@O!2/[)!MN44_7>C>G_:P^1C6)+^A#W.%-BTCV((A0!M6E;6!9<TKZT[2 +M<&$"7"M9R?:ME/$NB0:J969;(K=S12D2F9>Y80@D4`DF4'#+_P8<N*"*%B56 +MLFC'28OLK6W?'L<,="YMH-/CP=K<Q$KC075*8;;WSZ6_/#!T&[ZH7!8I(-T\ +MAUTN>+MHEH!5G3DW>/9^2CL1H"^JRHS92RXU1X?S"K>Z93SQJ%)GQVG.KOCQ +M<T$ISR:"M;&G'9D*24+YE1#KRIH_'2D*8*TK*E>Q">T!RDO>,5O%_)`JN\Y@ +M/+CR",&`,@-'J;H&'^S%D-WDCE'L1R&X(A&CC9O)IV'@7`E7?Z,OY!"W$ZIT +MO\1@X]3,-[F`ZJYB!Z:$'F!C.1Z1^&3^!?`ABU>#W3BS5H9[-@87SNX:!<)0 +M-BEW,_?0@^O>L!ZWY1;BT#Y&:1MW*B]M@MM[V%6SW-D3DN+21N[>8'*QVC5S +M&UZ1M$_H1=Y#Z^K/@Y[%I46@'QD(*?C6(0=4,ZHX=Z=;ZI+V+0-:X$98CGMA +M#(E_:`<VISU!VB<%#>_C&,2IT$;;`,SS>W$-+F>N-L?<`UXT3F,MM2-$VMLR +M+Q-U)2GP?QK</HY2@-TNQP>(&N6!\^-@9"P!`77D,RAFMNF5E:/2_>M$`R`S +M=T]V`#GM-S0;'N*!>'PL/SRJ3<@R[>'/3?WT^_2Z@Q!+4,I79BW86W1L)+*X +M+_>?CE<1<D2%[5$JEV40M*]QZ=45M'E4!9CRXS>,2ZB_!\[BJ^*SX&$)`"\Y +MEFMA*G"L\7C3KZS*+-CY^?7N@'Y4J`&J64LNLL#X-`GIG3P6M-'0()*A\F$S +MCI]VC"=I+7`)_$4VD@6"4:LP%&X5K+=.5,S4#3*\_Z`YGWGQ:60=!]I)("TZ +M-A6+P&]'/"Y6]W4.65*Q:^)33]A99L3:`)%`_>`,$@%5.0M.)$]CDKBHUC7P +MATI-8L3HSASBT6.7KC5#:?<P5!LR*%@)-<O:(M<.J:5/<P+A\-QM0]\UB)]K +M@WQISZ7R,ASV1&IK=*J6>O237->>HG-\7[:RP`Z^I=.Y:#1?[C;4NXF'"(SI +MH1J]3G3HU^#NQ:3)V`"KEH3,B=66OM7JV89X(4CHU8F8E8!9L(2?]YR7CBK\ +MH'"?8>\3Q$;9P3ZIH?\]>?J*MTQ$IR6.%I,<^F=>9=<,3V/BYA-7#]=-_$=< +MFA#>6Q%3(+I4/A]$H[>@M2@^C'S3VE:'<U`7O7RR=.Q=B(EG_*LEM-";,=B& +MW!;7M^OEYG=VU>7'T/B/A^H'&*;HMMNB<YKQLJ[.O3F7-\4,<QV?YD)INKFU +M&Y[QYV'K(@5]H#D&&2_O2/J7?^L&R0?`A4]"GG[SYSSF4<5!S>2"[J;_;YZU +MX`C>GI%6->-*+;VV*\X#7@S#,6I)"AL/)%&V[C:6-E`YE*M'(I?E-Q^N7NTU +MF,MLM!UZ=0B%).6!2L2-AS?CN[;Z57*^+`)LG/5`$CX.;ZQZW8/(]NK/@M=2 +MO;P]+*NOMR)19MF>(F6\D'&]$D^4K0GRKTY=`=''*2B?@/G-"=>2F.M^J"HB +MTD,&B,29$$'QXY-UL-36I=K*5-=!MGIS_IMS1HT?@Y^3VK=MCKH@/MN;$\*I +MOCI'4]GW>5Y\XXQ*)"@#"=2CK5RS:UF"\B2A7MR?Z$\J]^Z8XMYW]%L<!"5X +MG7/53\YKZVG]G9#F&FRE)T1]-".&,#BAST=4X16_0Q1XX;*3$GWND.@:MKY, +M7H/H#T$!I^H*\YGMFM9E@"J897:\>6C6#*/2A#$L%O@5N+H?UL(IK=%<@NLK +MF0]QGY)3O@YEBS?!0VW\@YKH2_SX9`1_<7X$%C!,#Z!@O'\^8M5\/YWR!U"* +M(5:9--EIF:.A0C6(HWW7$R.G8R:>PNX2#)]RFPX_L,V2;XT"CT_`I7&7U@`B +MDYVL_VJ'%*7/)HWUV!E3E9.8=+KX246.M)YHJ\_Y>+J5;(FK"9Z[KJ@>X6!_ +M^M%PQJZ7_C+?7;:`.>62SV3IU_DN_AR`)5"O))KQNH:\8DI\5P0[=&3`@<R` +ME82@QZZB,==<BNI1@811RN35Q'1`-&4$$05][D/PA<*QGMJ7.CIANY\4%<!@ +M7*;)J*PAR113/$BKVJ<AGK&"Q!HP$<PX#<_MN4'G?9^]1^C=D`H?,2='`J-] +MF;UFR21PGKE+3QM!:_)_,QZB@CN/MM5IZJN`49B]YZ:C?&WB02HKA2%J'-6$ +M^#@XXX'0JVF"UNY>Z=&\(WZ!<=!-O+?`[H?W#XPIY%UF>J^\DRW_J#N=K=SH +M)9PWL4YL7(\F3H)]U_R$,C``@EV+E[V2W^_@V6`+GS"31G1OMBT*$*YUD5&B +MG6/%%\*%W*2X8E\`_0HHBU1WYWIL*OL$JZ8\9S>_108*?(IL`%SEKIEXO&LH +M>#_TOM!JET[V`4(1QAG8$GU]Y=%+:3)D)\L]+$@UJ4XB&KC9UT]0[95P3SUN +M![:\VZ?[,P8VZ_@989D3\4GKI:%-@H"2U73YEU.'ZV_X3\/=EW<"64,LR,*2 +M]\U!8_04,$;0^95!,,1H'W<!"O;&W(T#AMN67`%C))1)AV?<FO0?T5".Z+`T +M'Q3_6(`-.=!%_:T)[4VOCX4.^$7X&FZ5PB!SWD;Q<Q+S3F$"9$7>),\:2>`3 +MST_LFO"BD!76&9,%QBCN/L2@>'>:,*D<"Y2G-.[W6FYX)V^H@8*O<MZ2ES*F +M%-IWOO=TC;]C\D15D#RJKOF@-8HLR+:[L03EB<A%RQTPXD\0*;?T(#-?D\M& +M5M(/_\%\I[75[)!G!@$M\\VBW*\F79OVWO'"7L1],!@TH<#><;*\SY'Y--27 +MC=!G\FNKS@<\XDF8O,Q1YK/\33CG34A4C_@\K2J;K1GR(7SM3/>F6(6C94C^ +MZO*:@P$BU3LQQ;"(E1W)IW0":]9FH;+LK^/UV00!_Q0N=F-HF4B/TF6AL:P? +M*=1K14_%+/M_P<P`GAU7@(TGK]!@VI5D%WW[JZG(LL^<A:.K>]K-96V[KR%[ +MG:`@>WAJS!X8\.Q36V-8>IP[].@WY%CQN$J5'ZNM^U0(8K/#X`'%XTI2T%Q! +M\L:M>"@E]5.AU=N'`Z\>_?VFI+IC&R4C&8;>U/YIG9,WW?2.Z87\*+:RXWU5 +M92ELML68Y:K_W%)QW=``'8.<P+.`SS\Z;R3GW&?HHX3G;L'4?"&YB]E_=CA? +MVL3.I?L;'Y4#NHDZ/]`A<<C'3A:/8#5H4/QHQ1<3Z=0/0-#N:"')MI?)26R) +MDKUUC,**U(+L]GKL1QT*5D5""Z)=&0A$U_R?T/]SG/X\IB=7)5-M/5+R/BKF +M<T93,FF>5.&LF%^,=?3B^5WPO[=NY&K(4]8#6!'F,P=*!X4LG/&43X'XF2-6 +M#'P=Y;MQ&*(\[&>O'BVVQR<63'*:&,4ER[,[_VSO"%O]L2_.#SANJYQC'&?2 +MV!.J`@Z[$D0-G<O`8D>K-IN="YTOH[_MT(8/1V-;QQ/1>.!V'"Z`MI^Z*%:8 +M4D3EV<48UR@$3C$*0J.W-O4X&T(7#/U9QZ`XTJ?_(UO`N%U??Z)<->R)"4^. +M;_A<[V1P=-V%243*H222U5%GB;B,=&]FSR=D=S0*+9\4"FH1*;=+^?8<D[XJ +M=FC?'<BJ1'L599A66.85R>^C(O,@K+5-68`^/Z/(#!4@_!HK<8TA$NRK[7AH +MEX_HFH$_Y"L;34V$/RNS*D43GQ#(B<M:VH-'K[=.)LE\7D#@8J`5'%.5S208 +M"2)47FRIQ&ZP`I$F#\UE'_[*_0V;PN1NUW&PE78OK'DH2:B&Q"PY`$CFP+5M +MS]//$@5B=;6H8#L&\N"10$/$CA;@M6CLZ-55&%8&>3=](ZH@9)]*\?.(P99* +MEJ"\V!/9]Q5N<[<5!IS"HS*Z3!5*I]!!OKT$EP37%F%HOY%7%R`F"(!:'0T7 +MX+I$&G$V_R<7D=6"$_(]?O5"+_$NI&$F0<0KQ&]EE+9:0",(P.4S@=EN!=C1 +M#>.:Y3VHX?#=!$B,4XDVB;S2^VL+`\J5,CT6N70+#KV_?<@2/O,=L_Z]LIOD +M<V:2B1P-["17K8?X%]?TN&7*_`V9.1>@DY@`DE!E44.B>\BC%=#F_=3HQV[H +ME0F;J'`L;1CQ<(!#LN!3=Q#<\5/$KN?S?V<%<O_L2$9AQK#-3JW,+V3BHKRC +M/YP2DT].59V(9<V'O6C&=PXMK,6A$1<W'KSJR+!',`LHXW66)QS='O[")HK- +M_%0_QOU#?*6[2._3M,9!EBY@J@Q7;:3(>S7Y3>69.BB9CTOI"!_K=6-RU75T +M>D++T#B5X`MMB?CK!,C]4M]^8HRS6(R4]N@$TR(DH+B7;T&S1.1A$$[GMK() +M<8<#LHDIXF@?U'[12].]?OV25$]C4ZJR>+"AYL*4J4=\8`.J`4IS9J'NYU[& +M"7MDX`47HGW8[IY=NAIN[FCI;$)D'/2:_944#BOK/`DW,D(3RH2H*Y$JS]/6 +MX)&;C?OQ2%L:PZ8X[<6TC)JE`?YP@#4N1'/>N^-U&ER\`%,G_&8SB\A;L0WS +MJ6SK)B8.H*/FHLCY&('S8$G8`,/Z6:SE;-#*Y<82[C<S`C#LE10E=$W7MY[7 +M/G@D:KREH$RW!,7E:K+0`:_!A@V?=<;5-`RF;%J:.OMY&\QM"+05EF:0%;51 +M@!0M3;^^"4YXU4N';SLTLWVVO-\<%MD-:$.IG/20"-HL[LW)4K(6VB)(W-WP +M)4*VZAAC[N7,?=8'S6F@NZ[T,!!_54/,V.,*#<=K6KN(TZ.9_=LFS.E!8K"F +M/Q.@NG\<WG$%(4?:OEJQ30W?*:%*8]ZH9Q_GSM4WG'GZXQ*&-.`^!^3*CAPL +M`YH../)*NF';<.'=@N10-Q&#_J%*`SORF)4\[!LHO@KCSGJ.@51LM:K`1"M/ +M_&:"9`,1X1M;J$%`'HJ)9ZS`5:@^L&\BROH?,B0&OX9_G5`(90J\C0Q7Z7/5 +M^.D2K8:S&AC5C`/*)4DR5%'?(F?0SS079`AS&/%<F;M>,BSO3V8('&82L2'1 +M^/<VE]4@\-;")T-^(3^^U5WK70<(+HI'^5J4[Q7"NA'0H;?^<#'U5220YLE- +M2A\2J0!<7/=XBV=,%*$0;VE%AVS1PK/Q=OSA[5I>K&%,<Z,6O!A:0X9S^O#V +M(;:V2SUTXL9Y*Z5U'X1Z-MT%1I8)MI;O12&Z!+VN?H&SE972X!P%X%"X)QX> +M*/HBD@H@J.T:G(?MK$)(#VS+,;*-H^1Y@"P4H2KW\X9-(?2]C:W:<I=.HP.4 +M:`B)[EPR!':XW]5_R.7JC?SYV[(/T1AM)WMO1TVS]PD`7"4X7<&.=$$]PK"E +M[V>S/,_K6G@`0O1<4%<J5U8)>GXZ+`U==`Z)V1K<$P5PG-:XHFMKK\'PL_6P +M-$@Y6E12#;0F*+4'JG,UO>^H>:\BMJ>ZB']L>_0D%:!N)@..9-;`0DW1:E8< +M'VYE?PLO;)G`FD1Z.@SGZ,N5(&VJ?:PYO$G?G.*<*A4EH=>-G7"JN1B)^;-M +MLO6:7?7E`;D`4Q\'7ISADP(!3HTOP]9)%AWNNT+9V(&RC]*1)%^DZ?HR2GJX +M@V;[-\/@M<3U]L3*<985&8!3.G)<H*&5IXR+ZH)0-B:3.G;@L!*E!"1$$BFL +MQTQ;&1%>TDT4H<[QG^&D%N[(]Q)V;4(S'`5;I]Z$"5-N(UIIY5Z?`II?>0#; +M>A%D)[\&);8@YME:9]$4CBU3UJV;E%E,:O1:G^'9RAUD'PG:-VB23YQ/I3RY +MA[4*[/'9J$XZ+)[M\DR,1UP$UJ:.SE2V59+=R.7+K30$Z9G%&3Y$I,JE6B/[ +MMR!H_;__,G:6#:WOA'ZK[2E?4D#8;GK)GSWF^LH<X*)I6ID6;,WK0A/1^WW. +MUQLY,T3KQS[VZSX5TZ*2_"0RIOP!WG423]I)J1O/\NOXV=$.X2T4F=74'D@N +MI8TI.&P3I'`;IU9.D"CQM,4'FW1K*/XH<BFW9'.89!RMF7Z&"+%(<XY',A7( +MJYKM1G'>;D2MJP4>9;B*O,RUX"Z0F,QMJ_]?G#G=`-4W/#@";$H;E]^4+GED +MY^<JN@E##PJ9#%+*F(\:\'HV4VQ1[[YZ61&UNR794%5L@8&/)69NS(=&8:AJ +MOB)7,20=(S&P_Y/,5.44!2]X`WGM^F6T]'\T7T>3&WX/!:'DQ!-@0%0/!0BW +M4]2[`7O\B3=M8&S7#T?"(%YUS'>S_TT19F%ODF>!C3X$[DUEE[]H=W!.9U.& +MK6+82;6^GE<`*VLPE:YT@.[L5(FG7$>/;]5_^V0<KI]3J29NV"B<E7#^JOB0 +M8N80&;9OXO?VHR&?2OZ`7NV=<.3F9,4@*HK*-ZS!T>5E'7E@&UX$T;;0OD&+ +M&%#_-4ZBV'$0?6XUK]X-Y:BFA1D9H5(WU$^F)5!5)2K^R(B]X#/-]C>BEFT7 +MI6?AG=*U<!A4/R].+%SKY_!=6I[7H5A7[_RUYX+,+@U?J6#BS7T;!(U;K2B, +M@H;WH#MG*[P[MQ!^+)-\L.6<-[R'$8*H3M]"J.#JNBZT^F%:QVMJ:`=O!GAC +MHIC;^0DL"!9%2@UR!!/B^A/N]=$P+D`$FZ1:-AAF8K\]1Y/WX\]$%7@N')BV +MH$JP_;J/*'ZV<67)C;G/H8F:L5))2,^`6H^!S'V7=D=8PT?[U]U<,#;WT,7[ +MIK)9!HK\]*J"=)BN64N<0Z['']@(=%5%67CAE_D*E;-(`HQB5$VC$ST@W8N` +MM8J[<$X/M?,(35TN6#A)^Y6:3F/[8#`!Y#8Z9[#FIR:5OY*1O^1M):F6\7[K +M271*[>:L2LJJ?6]*8&`:I+2XQ@8\9`Y6PQ#K,FN@5]H93WZ&@5/I'Q5AO!@3 +M+4(VKQWN]1.W43#7UM?81->&_27"6R*^5=:%N576X1FZ;CLFE)S8B?EL/:<2 +MNT"[3,)+OWI1!94]V#@=CJ4KV8`8O4DPZ1I&`.WY_!GIB>(Q\<\77!E^V2CR +M9XY!^ZP6^6Y@'[RW:I-[H#A:]57G/VWRO_6GV-'7(<X`2R%R3#_`)BLNYN3$ +M0)D5A/XE#L3$G.ACZG"W"ONTG'9CJ09!]H^5@JX<&9^RE9!>@/*<-P4_QX)H +M?<>2X?F^><M,8.]B^7SEA`ICJ]5,"W.5HFIU#,UW@'T&@FW5IG=[Q2"H>.NA +M(&AV"V';$B&LSL1CZQ5.6=I%;<!D#6MK"2]'L"00]5,G77ZUU#4(>$]:YE%2 +M&4EG[2['27.4/UN@;@HT$A8,=A-0ESB.PSF],!E[`#,?K`SOA$;C7,V;B`!A +M;("?%H.X<4:F7O'C@AI04-IOQ:AEM6Q:I(52[YO)[[FD\*M&"1D$JN?YP\.Z +M-.G%97Z!64@W)6=7Q7F>(`EPY"&H`W.C`L1;T"!A16:TIW/1H/$Q$2=!`4^R +M\^JOV9E3AIV7Q3?N<Z&\+L)1HPQ4@C5O=-G?H>(;)LW0;S^"=MB;)*,^$")` +M+T*)=!5?O4T05D9Y25\'FP+0ED7H04A>9U^(R`T>@0N`7JR?9_8./_2ES]QY +M3898*WNF,_.X80UA34$?+`F@3FWY%FI?+X$KB_)JYU7D:$(W\9[[Z%"6!^PS +M@J):C`)0RS*^'R;8YI3$[2*;\AA<'($Q!14NMI+4L`)IVAWS&6_**007K3KI +MP,[F:%IXS]V<D#=N3T.R`(J@=8#7:NAPKU!?)8D#TG0A!#.I(*>D"^"8+>.S +MM@U/JQ8A/3SG$]+%1915;MPBL,[$";"`44..(.9_]@*L16HG=%$#2[/^XTGM +M?$1X1UE`[;!3I#Y.@:0]S(4MN`%>?.L?3$@"K>'2!?G9&`N(-,EE@[BY.P#" +M9\:^%O3L2!0*P*777C'X]JB8$N7DM!N*.'UYX+V!2?&8Y!<GB-KB^E7M0(QL +M*\P1[#53U?HSUW/%ZMF;=5GO);;WC\I`2QD*6I%&R`M;5T`B>82Q2'@-WW@6 +M%Y?TSY)M@+!J+[(0D5W(VW@\/1WY0=X*&,252`I\'7RT3IUS)@LAHBY<0'.S +M.*H,@IBBLYAKHI1^.9_D&2NHXYCT?(VC]LBY[CMZO73[R5FG^+`S_%2ZGUS` +M8`YE=39QGNL`B)46?W7W#Z@+H\!)TF<P*CH'4OZE$(020`YI.[64A5%@P5HP +MI7H_'[(R37S!R\+0I!<%UEM;PC/\)V`UIQ4I`RZNA0)K_$<`7R01<]M//QOD +MR]+^QGJ6W;IRN]'KJI@J2.@W)P`XJON!)8PET?YS_A\%,!<I:,Q`>K<N#!Y" +M.K;6H#LS?+TJ*.:$4'2IJLO(@GU%AO`2U`I^H4<\D(&4U8Y)H4[`]V:^2!K+ +M[H%;?-7I9H6X_()OTAF6AG/3P<F++)S:A8^"1HZC,31OK'M+N(,C(A&S9,L2 +MDM87VJ^64WYT$B:7\M6,@+*+9T[L2P'BOD8HE7SY.-<"9O>%^480HKM[?RP2 +M^A(S84Q'MJ-91N@9C$S]^/F'9A;[-O?:MQDI^!JNR-5KO7G/7(YPIA>)X+C/ +MO*"%M*]Y^0ZEK]_,MW79&(G1!B<^P=F@.&X(2)UIGL%QK[AVG7A>&=R'!Q\< +MOV(\6O7$5OF6MH;NZV+GBFJE8*VG-8YC6P:+Z"UEO]^I>*?[)]6D4N-50D41 +MG&U)Y<T>-LSV=^5I@KS@/KUWA,Z)(<$YII%E:J[K(T5/]+JU;VE"&"[5ILVL +MM2D&SPN_/>4BAV+\GKK7D_X?6D13GJ=GU.R:851@AM7EG%HC=*&Y2.M,;LW7 +MJ)G"*I,F)A+18FGAGH:T\2B4N:^4ZZ%:ZY-:>VGM"AS-]Y1[%`?!?,Y8#6P) +MB(6Q>NYM$8(XE>@$<-$N_)%!8IAT5X-T%*$7R(\"[U[,(/IB"ULE!"K;"(OO +M2M\C]\1"YG1Y'A(=%98&2@#6GZ_=^%,9"2*NV',Y,Z:%MT>6ATK59*:4Y'=W +M@WTIEDW!\^QL7U<,L4A*]R!'H^P3`:F_,)NVZL3^)XJQ@NU=CU4;IGYG4@*@ +M@<V"QJF4';\W%4(J(11*.CV5(+1%>^FP'@*2%I(IQRNQZMP!PX]P\>$)GS"/ +M+K8EZ+U__S&<FK`W?^,\,4V+A#?7ZH(\3*O5!%TF\,#*E2C7Q\6O$(D)P2]+ +M=G0F^>("-.:01$-Z<1-VY<HJB&H80:3*/%Z^^QIP=N"&TWCZD/VC-M&:=.=> +M'R@?T1"*B.+FHMZ..5WJ8O82^Q@;JM!''^QV*[[269T`82H#ZK@_]B4O*#3Q +MG&\<3>BZ>>A<66/)/E\2EB\VCQ4'K[C2(QC\S/OD<".=4;!#P&+0+667_JN= +MJ(>_VH\DTE^WW69;76WYM\&7L_</N])_:.:#\LW`"_H"\(5$)V372].4DT*5 +M2NQ58[QZR%I@%\1@5W$/KV,$,SV^M/UY>K6>U8XLA1R>SDMJ";>X^R7(G\PY +MVL^YD@SAPYHC`O`XE;M48ZD&H9&D&/;Y)]&^0M)36HJ\->IDZ!28"3/U\)1. +M?RI]?`N6#HI77(0/@MU#L(&[14[\,6:NQ](8=2E4(1M$JU3Y(EM1ARUITH3S +ME4>">`[O`X@!+'8HCH=&#Y)9H:.*5D1HS]1A-.V89C-VEW()3S:%B)AS\]L_ +M-<AN$"U*`]NM_.G41BNF8P52()/R$I4<#?H:?,F23)T<1"<XJJV6X!(@>Z`< +MH9J>>R7/$T0M*V1(@F.3!U47(J0^OA8AEGQ`[8&F8T<6AX7T,K_V7H0LPQGW +MXFLW?O[$O4+H*BUKCA\)NQMN_52A$LI&IU$^_=\.KJW$F^KKEH!UWEY@MQ-= +M)C62>ZOC?M=U$O,C>VBZ4$9@AS`1!B4,:Z?[?GR5D20R,ABI8P@^3SSI07\* +M`]S_$:6`$2*H:=H#02JTBM9XQVSMK*%F0N-TR/ESZ$J.(=C]O=EJ[B`:>?]- +M0V#QI`;HC%3NYT(V3'M3>1YJ*%1R/==`?"`QGR"@/=NK(W[L03CYIT7-B-#= +MT@Z'V^5.<<+8RV%'OG\B'=VF=!;"%"57SF`BCW!)XBS2S)N%C2K3H`+@+Z&) +MT(1=06ZR9`0!L8HRBPMRBT>T3^V-0KW<#B5\GRLCK3A;Y(/\+HLQ7UPZNQ/$ +M5$A0ZTBA1P+#DH%[4YVQ4WAZ:9H-B:GVF6D`:H[2SIAKV3"T]1**[C'MT;/5 +MSFO)5*:(PN71=B1POC.8.MW[H9*"@(9G;F`,FM+1O>RPI"F_YPW+RX:5*FI: +MR^2]3#XO+V0\E"^.0*8XA8*59V++U<9\_6"O8VH@SF(7SH`6`>#RS+N","I/ +M[1_I4R_"++'_+N9TAWT6N@8,O(<4X.Y$G=0F';/8Y%,'9X_Y\5H2QG?^1(%K +MB%E:GC4R_XK.NL5V2[L:DJ)<;R$<TI;+"!;BB5_^_.FU?^FIL'-*D&$CI,G7 +MY)G-1K<R*9RWB8[[T)9FG/C+67!<R.TKLV3=[;<>*4]1.+YGE68?,6[E(P7G +MSS.G_(Q+CJ(93QPA%0[S#\9OT81R-;-\:Z604-X;DW^@%J"U#)MU=J!<OL%[ +MI,T-CV%=;XAJG1V`'@"C2(FH8ZJ`NIU54J[74SI,XG['L_HXTW:U9Y/6JI-M +MWOMS:<#U7-Z!0[]V:QQ6P`TCOG$+T(Q9>XD>4C4Y<@<$H:.(P?V0\6>,?*/> +M"(#[+:=0S),2G\FKD6FXQMAC9+2^]-+RY4B)R)K+O-3(^.\"\RGN"E#[7;JD +M`5VPW0`Q7K@:CY3M+:57T:)X<R)S4AY6WV^'9LO0L_>\QE#?53+3822BF,]2 +MSY4Y*9$R`<_"H:!RG?'Q"A("';WI]@2<`[PI[W@P=A*Q?]U^-#^MGA(;LZHK +MJB^TL>[K>KW?Q.+,K'`S=J_WESW$2`>YH8>CE,N:Z\20AF;M?Z19B+\#\_C! +MFR2G;+B+?1B3@AR'9\-FOC-GR"AB!NF(Z5:1*E\>RBO=+7*!_SJ`B4NMLB3Q +M"@Q83,590#6MFE87Z\+2ZW<]YWQD`TA\SK@P;B`LH1:=#*4J#M^_]PD_JZ2* +MM.V4XQ9:4D=F%^%V]_:%%=LAZU#"GCI=0DYVY`D4R_=)&#-F'1[R`N(#A\-G +M'4B$#(F+J+1.24FAEYJ(68HR":SCW`-ZFS$,/U=SO_,6%_OX(U$6AD%,D2`! +ME/L5%X:<)GI83WVU@9.^-DK%^Q^7?&;X8`W.""+S0T>2BM:OA/,->P.8B"4O +M=F3(Q2?"==-H(EUP[[XI_"ZCS\$[ZJ-IC<K=5>0`<C^?FYIZ7FIV/#4^#(30 +MZ*+8%PIWBKE/<AXFK*1+":N;7[TT@.G0S1$XT#!>\5>8]&_B`>B7Y)<<^E!J +M2,!OD(*/OC56HY@XY@BR0H)L^_M-8T'@.A7992/WX$OA"VY&(CG$W2&4&/I, +MSB.]D5A2S'0J`YHU&U/2U3C$C17=OWZP6WI&4]^MDFO6#W),FC"M<FRA(I;Y +MJE]S[ZQVZ?='<J3]G.N^RM[6ZJ5!TYLAG@\%4*,U\3ZO:TC`0!12_X9?.!(^ +M2BX_"A/@0N.8ZKE?E,%'0IAI&W8X:+LS5[*_8_Z@K;-I4S1.(UJ1,'$>0^+! +MIB%$FK8H*KS8KA_Z!X2-B'!G=!H5YI$;P]&G,0Z?_I$4L<<D/N(R[QNBED6_ +MF03,`NVJJ/.@-S#,94N;E@8;2N`<E\MNLU2Z558DF1^GVY@U_VS4Z_2V',OH +M:MWM;5"L0/M`.WQ`PQLG#!CE(<6H3^5(>J6P$A^/NV#E?%K;#L:&U7[D:%YX +MDA>4(I\2Y@Q-MP9@G@@5KUWU[&*$U$#(F=(+WV`SS^@?PC65.G)).*#RJ#Y. +M85M]_T0EXM20S@2!^6`N8<+6'3%_2$PMT'Q#Z5\=?#@U?\;&W:N.,&7A^>#+ +M'P?YC*_H*9H!K2EY)$(@06-=%F0H7`5?OQY*_HV(I&5<XH#$KGV:@(][HV:P +MS=-Q[=N%=4%644D9X16'0X>OYHLZH`$,D!*6>!@=:D3#67,";"Q@N89?4MIO +MLF,R?'['0TPP^VK#O:9]@<TZ4,78',MO(NRB3BYTR%!`&=<<XBR7)R4`%\3Q +M,RSI9>H1&K1$E/)#0EHXZH[YG&6JZ+)0MEFDY#C@1>7TA4D,,<CQN=WL>+_C +M!1+<\S;@$FHJ`\CQ2*XT2A<&@F9M1O]Z/1GG?HL`VSY/(H[9(+]E3@;IF9U_ +M1$$8[K[*F0="Q'_ED/+[%S6]BX$"Z4:#V`T)+0WNI^#S6`0BA6B0OC,%+ERQ +MOL;T0?\-N=[%Q%TYH+E"#!_@T'L%O8X4=Y5$F&$I9Y4/[M:]7^_G13J;'\&/ +MF<=BY.?MPP>76_O!!"ZW2%2FX.SY`V,AZQ*#6VG-+FG`?)@L<[$$"\V!+O6) +M-Y(,K%8Z$)!\-R,JI+[K3SN$\B7[0*JF.'FL.)T!-O9L:6P2.4L4.PVO:"^4 +M]YA>/]0?^3Z;"?$'-2,L%3:9?;D17YG!!TT?Q]1->RXS6M5'."QG?9NNO@V! +MXX;S<Y5*$F1:\>3OV`R?I2ANP$FU@,-%&9BX2RJ-*`@O3'<TEQF&@AO1='[# +ML)H+71"JU)8B45"^DXS6PR='2WXIVV;MS.:_8697+)V>W;R3(_4Y^$03WY1+ +M+]OM1FBM+05O]X)U^@T.FT6QT#@R`]US%O"ELK9#=#I4MX&T/@>,8;Q<K*EM +MJ;;HNFR'9.`8G61,D+N..T9$3#]^110;+R:2!F<O8*7,LE0S-,TI=Y=]-P59 +M`5)2F46")F949&2=SU11E'/^?PZ+VV'.R+JR9*Z@JIVV@8%2R^3!Z:PN3N]S +M$=8/VW*[`+6!PE@J$VNXO*+`I,XHM,6";#.')?\U@KB2N2)=QZ)#FGW@Q@%> +ML+R/E:N=NV7S*-WY2GN6H4QKH9YD8"^5/^XH3X7>I/YO%CL\0A7KR8RI)6BL +MPP.5*AK;2ED4\M*_M."0`(0-C(3%E#NA/)XNR9R!F%*MGA.,FM[EU&>RS3)! +MJC?/SK&[6V94WMTA0QJ$_X"_/_T:YG>)QF3[\+":CWQ^[XO+FU.#,V[M=<RV +M=89<$"]H!S'X_1#(8I.:W4BYDW]DMWAFM,L1=!AOT6H!\TXD>]_G[Z".PX@> +MGU80(ATRO5Q+$":A^B5OPD3])I%@^[VV(+^3-(!-S$'.<,%S,J`=Y\>J"`%. +MP]G@/G=[K,6>I(5$,;0$`T-CB=217G:*7W:TQB_&=O&X1HFO8-LS=7^P%MZR +MR@Y^,*,-4B#<Z46E"A39H9H"RQX0B_NJ<TST%KS$8[($!R#:!5$JGQW\&I]M +M]P,CSQI@FCW*(8TL*1[(J#:V74_NW`Z0^Q="P`Y1L)J[+[OA1(X^R[*8UOBJ +M^G(F<2_>3R;,[JBA=-/#[EG#958L28)K/,7H6Y`)\$>NTNWGR,T+ICWKO:,= +M3Z-B0V/U0*-!DK>"5WQF&O\&GMVML(53C5D[$WOR.GI2[D@G]^3(!?)\FIIK +M#@L*]XJLB=G@#NA\RJ;=C@BMPD'V]E6=:W5TWQFI)G`-U/`<!VR(3>E9:(-U +M(RH<S*DK:T60%4]@.^QGE0^'NI;?]C/L@YB;J\(2N85.6Y^.L(D+EPL<2JA, +M+I\#%?XSKSM25V+?ONJ`_K`;P5M`)B#%!\HA&;Q?KWM4IQ!3.#=X\83_&9S& +M.8&J$Y0+!W<MM\TJ[!-9#%X(/$D-QDB<N[2?-96C<POW\P_O6A>8#R`SZ@.8 +MM1M`-I2Y]&8Z\72$)'KP+PMNJ@:,96L/"K*6*,#,ZX%_N'X"68+610O"&.XJ +MR;Y.,^?E/T$!;]%V;O;#B-\3XM9&^B]<#)EBN$.?-SQN+8M1X)_]DUI(=6G) +M9(8V[JV9:1(%S0]*;G(*UJ&ZL_EE9BC&8V5A@`,W0@!C&7+W'7A)!<6Q:)K6 +M9[=(D5F&SZZDSPSECTYR1@<3L2;;?'.Y]T=4V@\J@?C.444D.?4'`W,N=;D& +M@\FU'E<2JD3$GZCWG_CN-"46;IJ[_!-PPN(J9M(548'!A4"XP)FY>U'&+3+A +M`.PU_D/0O:_.43U(_2E7;"3DXR7_IM4KH[SF]/&5XT,-"8^GY'!%Z<]FR/I) +M.KV\DM6K.YQ8EPN'1:LTBI=!?VR82T;+3_!.C\,E6#T!7.=1P4D^J_8XJK5/ +M*MO3"-EF=$J-Y2S/P/!$VC'X'LMJZJ^69$^L$-C^>\(\E+!AO%T2>4)/-"9. +M@1ZN,503-NC884N]W)/;M&O4/FCGN90\OAT+SP/PT-8$7=.7T`JGK7+/CEQ. +M<;ECKUL#J>3,BS=M&[FFIPY-(NE&7J^^J1*,P0K)NO,;D@.LCI652,^!2KY6 +M^9\_N%]`ORK.<8\,%`\8#<BQ9U1)JGUVWQMN^KLQ4NXCQ62Q?&N5;[TA'XER +MUJ,G$"59+\BR"C"\\O*X;-7(&I*(AOB5L"^>AGBJ_40)N6??1B@B!JTQP@$P +M'RG[6I5NO=FL+%'#KZWL3;\XU1!5VKRG>`B?BS&-$9Z[='%K2.)7ZNVY10$[ +MQ#-MMN(TV$<MS/.].AO+SWS^Q0"^<X&2)$5G2]W(4]I)4TJ4)QJ1O*8`'>E6 +M/K]M?.[K^]7LA;?YY5:Y:7\LEX$1T*UJMGAS_L8O8%2,S$).N+$K1%W*^4U, +MC";NS.,T9Y#\O1"3I&2+!_*/;H"VL\0#Z&:>,:SJ;@"1[I9`?CUA5'.1F?,` +M@)]SC`>2.WYI7OAXX=9%LK!87J^7_?-%.Y$8.J=_FF_?7')YA?6!7(;X."SX +M"8)&8;8>_?/P#V"-">[@H^@WZ0JQR^R&#%(B'_*E<O[A!V=#.!?LJ^2G2L_M +MS0QG9^LW^+WK"_U8Y3$3&3C\6^A8H2^UWHX_9,O,(_7K']39Q3E7JENBA`31 +M-!+'?=V?MX4^S.#)/4(-*P/)TC)X;4NTX>7-#X%W^X2&"_X-S#:\$L?\&9.> +M];Q&](,[H&EM062631V6@9K5>Y)>C$_+BUR$?W]J(23S3K1NE+C1F15<@LHW +M*LVAW)HC*;"_Y=D[.N5X@3@**HF.;/7B-2T3T^3%G>47I/[^@LWP&'G++<[; +M#!Q;F-E'4M]VBU-ERY/$=>`*C!#1$HNP4312$?*C&]@+5-A%K5\DL<6E!NB+ +M:]3B5_SE.\G,)%-LJI[?(>MA;Y!Q)<R)'N+R_!!6+#YJG)><`VB[A1P$(?"3 +M7BD[0@@=94=3Z?-$3;K`)OH5-;;R!:.%6,M([,??\^-ZIS.O_2!:@Q(&XG&? +M0QRQ?I7TAG$\##%+0]0_1W*I[PRY"0YL:0OO<<BR&6K,,Z5=$?/GPG`[!G^J +MY+4UH`2!52,=_EXS`S/9-GIK"@GO_9T083.4'L_P'`XC_@\O:X8OVES@GJQA +M;'6N[&%201H/S6[!8/\V@F&8(AG2OE'9)IQ4(1J;ZV)62#YRNW?;&(NFN$U? +MLYTYSC8`Q?*VZ<H`H.,PFKC@PPXS`?89U$Q&XCXF0'][G+MVG6S/>PO[L^!& +M1`:^OXXH`;3%A0&T^($1:9VF]-%&P"*<\'C:$-)T$>@WOF^U`GS"G>PA>-P+ +M7[.[L7,2,QCIY1#-AC5II.1&E9\97LO19%^V5N$1FN:P5`4)/9RN++0(QO[' +M<;Y-%/B$PK=Y(L*O-)#%`2^GE9":#!B^-C%X'Y'QKP)BAX;Q1\5K`(N;+/5? +MUJ9Z*)H;5=QYND6PI,^=1_P`K>3R*(BZ%:A)L`$O@"2)$I;K9119E#1#YV>; +M:E6X\;&<X-MUQK^&MYU\R>5'9H&`Y1/1&WLFH#)1_S-6#DQ.97WKBKSCQ/E" +MN3H*K:#7D?F#8-FLMU/F_.\9'E=7>T^`HIF(*]&GD8/*0/.?'\5*U=9]=0P@ +MYB:;%^<I=LKH3DBBMYLEICQI5Y`K,^JCVYI^^0W0B_X?)A;LU6`DQ/O'38&D +M,/:0L7KWT1979V]282:?7"FU;B[]O2:G3'';E<$%XF:B7UPY4`.P#H)@N0'U +MF78*(O@()0KCU?ABJ(X"23]F&:&S`L*@$?;\D:M/(1@>K07XNKM8YI)%`FB! +M&CZCX6`T%^C@VNRW7M*OW+_8=3Z1R<W92(W-EYW_!,_X?7)A0'>A>"TU$W4V +MI1^;UU3-;8\<_9/]ZOKZ-X'%K/)51^QE<`%`*)WG$*)4-PH^&$H7FA-##L4C +M4&3E7[;;2X/S?#)H110N&!&^[=PWWS$D=\5HE0=3%H!=7VTI6LUH'1C6V"V* +M_LNJO!W`TC0WL;G;"Z-Y=HLT]C$9;`9G\S&,U)XL"3UTEUGUGXD8V<E"_P%: +MVW#6W,=N0P.R5D)Q-H6M^]98&C_K>EQXVKN!+PADX)TL\D6@8'O`ZQY)]=*2 +MM9/PRQ':?&&!(F?-X,=VS#;'0_\C]#4(27;9K;_L-^K]'22<&AZ,T-8,8)*C +MR&D+`\F(K^Z(RI8U.<.B--C?HIYF/O2[,<P&=\/-*%KP[O%:RC=\=0HG^+F[ +MK2PLBUFX][XJC5B4%^Y<Z>+5*./*#-Y/6G%-PPLB6F9[\289WX'N]LU),RJ% +M2]'W,`?1I4Y]P%>M_+S80S57U!GC4__XA$=8G=6VND4)!#3)X5RW\2S>E8"> +M,]\9Z>#N"@"?8WHZ/,@)0>C6-,1)Y`GMK.AAM7"A0AO]5R0\@1L+(.RE!2PR +M\:7*F2JZZ=7AEH2J1JGBL`R@(K"J`<6*,1'P\W.?N:W/#YU,3LP>JP+>@'2% +MA?OBC#1:"C(0$2OY+FO+E,V3H.OB%/78'I\DC+*T#P*Q=,[1#;96AK$%$+FQ +MB$`!\SXQH&NS$"08G0B+O;#8QO,P3=2(CL?M2NV46X9O+ZO4:H,%A+U),H52 +M%HV-Y_\C]F?Y1%_H`M<%=OO*#M4ZU(V?XB^:)#BP7X+@:4+U!]A2K^JG0%"L +M,X3%&"[@Y5.>6\S!PR=70)S@@[_$/[_D7L4_?D7,>;9]7VK1104MY+GN)A"1 +MZ(FKRXC3#/NXLW+I`*3S)3ATZNI?`-5UMC.Y>J?H94IURW)?A"+2H;87<-&= +M^Q),K40`4,T!1U!G')$F'+4N1&W)=)$G,\/']W7<.1E]+4E(S',\`K/FLAD_ +M#VZD<SC:O'8I;$5I66'B,WJJX[@*'I^9K-G6=ZSJK?4<U1UB8NM@5PXP5/Z. +MD^U>K=5R.L:9QV'F<&RGP,SOY4MG3M?/K19>8ZT9!,$S=M.0,;!;5#U.=JPO +MY':$67WT;0MC2%WM.-_JI42O+VRB+)3Q*08,KO1:DVD'.X.;]956]$@5#B[B +M:V0!.53?Y3T6B<>!0"GB@0K0:'$M_<MY1/LIV<3(60"PQ1-I_06@,R(6`;24 +MV`CG<]L%D_T%\EF_VT&:(E?G7C<WH_MY:#A[2.%D;=+NZ(G:GHC3$HG4%'2_ +M"KU8PDZN/?65-"D41EKV-%34N#OC0F0CY5F25^).W'A`[<7#84&2$%>X!:AV +M:)@--VSEK@G89C.)*YMH_VS2;/<HW]QGHJ?:2J;:L;R>1H:DSID$1(Y[=A[[ +MCJ?3\H/,<Q1,^WFT$9\9U0,*>4>+4!37F1$+<.46K)E]Q.VX7AVP!<N:;)@_ +M-J2'FC6M;X-BL'1AB:L.IGJB(TW3>J]M>VARO3XO3*.9-&`^1B1B@6ZA-7%D +M8DAR6PA8^D@?@$2YATJCSC!N>@>8P^X(@]K77.)6#AXKHP,<^,>_'0?#+U3J +M&L8R1I7D+_;2EFH8FR:W8\J!$S/@D#S;WAVX:G.!R2A;='TZF%6E.ONWAR'? +M4TTE"W?C?C)2V:?VNVE$(ZNB.^Z(0H_BK78'"J@'V=7J,@&Z,I@=M-,"FSB[ +M50F26JK?;::/J+@C?<-THL.\JT7#Z/QZ`,9]#2I,M(O5.N^Z(X6R4*FCM5W@ +M#X!JLYKG1L(:*\U<B=_H>$4&\"1@&``H'KYBZ;"+^@QN8&KL-$G!LQ_ESATI +M1(H*-I5#^*%;;22<461)GBDXU@?TU+&@JQAS0#>1&O=F54]Z:U]6(,_#>HN1 +MMB_=3_)C9"@8'1EXQ>80Z;$3-X6B,S`5=T18-=$DMFD/K&5`($#F0@%]GV6O +MTK+CQY.FA9BO8U*)R"U11'%#5XDAG[_U\?KD&8'_^^?M[IW0H/ZB*Z'+ZMC; +M-%:G/^_T`]IN=G2LI41-.7=DBIM7F9[/VBO\-PO;*'?'EUZE,*.Q$4,3%>32 +MW4`,*,LRJNX&1JS0]&AY.HR(2NABY;O"R_(X;`,.L8^,6[S6MTN#&]Y^T.UU +M]N:)JP-SNL#;'CP5@+$:9=DZ?*RB&/>%`YQ^.8>K6R+Q3VB*NQ)'1L%*29'E +M'X>9,S:":=7_9Q\;:4?I=Z;Y5\R[$Y+KSH7?=U2D6*ZL,&-OM'K[CE=.N8!: +MD\V,&G`'(.\(^\[Y;#?UM$26<7`W."4%ON,3_$5&2G[C-FSZ+)$'T-E;Y#X+ +M+)I@3T&K*).H(G+[B,5MJO8,BF-GNJ/)%U<X%[H[3,;]$=(*_4AUJ&[DH%". +MT-SYUMNG@E",&-([ZFTBAB1A,\Y'7@,GZC?-FOLA%2]J&=4C/Q3,=Q)]'<"- +M)^7+:():P%<IWM3X78Q8A/ESKE=(3L@Y,\6OJKEBDY(`:FNMZ6+AOE'Z&;5" +MXYO`=\SZ/AJMESCAN_^2:.DE7KC9H^OJ4@[A5(M*9VY)1'N+!0[OUR92-^+J +M[SJ-&ZV7;3GM];/6<95.ZQ?]!&#\8)RW"T^S`"@X\1%T2]?4(FPOJ9\7#X&# +MRMT3-#*4,CB!5@D<UC_:;*-'R8X3`&4/8-2@5Y/`E\\)8]#N.V\A,9^1M5T^ +MY,>Y5.K_1?70#L7X9FTNAW+WA[0+.;WZYRGV)9,C6OJFCBB4;=[+UH*3,@WP +MV@G%KO-.;\^,\NOE9-,0*S9C(Q8;[T!,#,>=#S+*8Q/7JT#>Z"=T\Q`1UH?3 +M_Y&=^6DH&@:Z,DW+O1IZI>P8;+_*1>_F9ETNCMZ?\7LDA1Z2D'6/G+%B.VN: +MZ;,8@++04\HFM)](\G`Y_1T+.M!%WX<+]?GCK,TH*.-+I3U!3"2K=E52/,$I +MJJ*^VR>S%;5]32?IJ-(=+A'SO5)>>_1WT;!S@E@-4HF(&IJ,?[V";,,VKH.= +M1)C+9TQH)MK3,/1C2@6K?\45&<<_C);BR\V^I08]'-=K4*_4^*^*\@/Z:HA: +MJ8+2W#RK_$3ESE#8G@_!+JR'&U]QFO.DO;(<R%]\[+,@#6)RM['S?D.V\H6V +M308"%B6Q$KRB*Z>'.MRV'MI'NYK6OU9+'7T"!T5);!_&,G9M^N(YJR(6A)7C +M7X@U#X3>,A0S.FH6K$^TQ-AL(A/DZ2S%=UN3=2[FY=J\5`1N7>:;2^`/1OX> +ML/U_&$]N^&<LC.('1\TL@HM0\@T:^QS!2@]FCJG-?M20=WE'L3&3(^7Q/5V2 +M!G/]V^"D.N6,VW/<+(M*2&=$8;4=:P#>/T\I@S,H7!=SM0PTREV!:_=X193B +MM2!)JI[O#KME'X]UUDH+L$8O'`(?>-W-7*U5N../%SJM/G9-3E1/Y>C:/?%6 +MN\Y?")FG!0LGJ3B*R:;3OBV476">#%TES>/J!Q(BB*>XXB15@)$U/7+9(GCF +MV6+P5CU:9CVNR]8.)792E>8:5M0_5AZI/:@.7ZG198(^S*\ORV*A`PK#1'&Q +M`]8\ZQ59+F+,G@;+=:)T4&2M2G<,N#B40%'"7E>7$U2[>Q5>Q'QQE]"BX1@4 +M^)08E&-3G?MOW$(*&WA%2HUB0I@8CO%/<2P'L*"*P@67HRTP=G;52G\6$F36 +M)?>(QVQ7,&7!^,%`FUS0&&`X*K7Y1LSFMA!`M"QJ^6RPXRJ]29@.2A8,QT3' +MG%:7W+MGD?++@+6DM!,KNR'HYL@F5BZSP;F[=H$IZ:E`1%VL`SDM"7AF&IDA +MC>/O%;>-H#-NW7[OYLD]6Q=]L^XF3N12:^IL`=E0AU=O3QYQ\L@UF^5V@91& +MD_^`,5,SFCO(ZH`&2_K.(2[)[P(G=4`(C<UIQ5X="&79#^7LXI]8;NO]W%-* +M@\$^UKV+[Y^^:KP3*UHSZ+,]X6S\H\2*1=4OID;Z]7VCUFL)FM(#O[:W0-_# +MLITJ"=P^S$%KE=B60@!1<R&,#^<(.=K<TP4J5V>P_P@AEN('V74PCG(7;.S= +MPZ+BW^0?O5*Z58#`U4Z`N>VI6.'H>9,E\-R*I3RGKOD5+!:"9PFZMKJ\LX[Z +M[5X;CQSR[QBMT@O#1!(LR3N)=A9F\YH,7G/CH8Z]1P78IM2W;Q_16I[)V]Q0 +MY%BRY$8(.'\!O(.B$#F04',@XF7UI?^A!*>B\WN4$M!I(.@[^'K3RL;1OHPV +M8N]GOD$&.!DNF`2&L#9,Z"U2:].V3FXGW-#/X)-/L7]&"T("@N"$WOJX!%`Q +M"'_BE5["?_D,^HF$PA)&8GFA7S+4YVUDVVJG*V'F8BR)8L%*A:]?1^DV7FU$ +MRN#!E\\UV^R$.S&EPW-_`O(:J-DEV4B#?*M%I>1FW-X=0IFL\2MVR_$U<:H6 +MY-T%NL9?S1\)/P[6@6!24`A)R;T#C!;2G+[`8K)#6!3FB\6<;^_$\DZN.#$@ +MJIP1KMN2UAF_P];T'XZ6)0KZ_/A,J.7JUM?H0_SLWBWOX<*#V3#FJ[8KB$G1 +ML3:+/L6Z"&_>LF/:=[UQI:Y7C`R+/MWQ^I)/&.)JVQV+`T^`Z1./I%5SR/2, +M:Y.<5`-N'BI4>,G>+0`\P<<JH:16<>J4(]=(M"CR).8O4^47B2Y7%[;25B%N +M:(X.91\=)0AL^%\0^L9NI[X]ECU;;'TB)IAG?_MP&[L5TR`\%R2@L+:F7:(A +MF[$T*\F;)^"&'H5??<'RE&^H6=EV]<<;]BRYK*KV9XN^TEZLP<NT@#1)SA7" +M(%F8RS,(A:J/Y_/\7A6QJFBUDQJ>0GI5'+,<\^CM&^36`&;0891C2"QP>'QB +M985L:4GAAZ,-"G$5(%7>@O<80`60IK@L\',5H=W/3+J9XNV>$%C0=X)^VMW2 +M*YFT:/BXP$];"SPX;56/7TA,NV)6Y?3&LZ[0%ZI`X4N!/JX#(^SQ!J)1SW]4 +M6+3A#(U822(DG;S@E%!5TRT6;V]>1?4W7X*4*HS*!%<O]J=L[0<]U9)Z*O6= +MK^$2+C[)>"&G4T6IK%XAI$OC$'/N:5LW88J=U@)XA^#5US!+I1C@-T..;-3; +MP:UNGK`N5J6F9NZ5NH7,13_)T\7:/1ZD#@$;,;1CO5+M"V7G^F"^(G[^'>@( +MCL'8M+:#<^<SIZVGM?J(<)+M%Y.4Q9D!WN7OID7PZ%%G_BQ:,:_4CXB-$#?X +MS:)%F/[QE:R%F)3/5AQO^6D!"6R>,3M6*2;288SAZ6U*)\+/BNF_NV-OFE]\ +M(6RWKD+Y>SV+9*G'4'_JCK><!WZR$5Z#7RD>WE8N(Y_$T+"OGC^V8T#+KSMZ +M`JY1M]8P:\"63[BE"\5*7&M,--2T"8B`-WO:!LO:HUJ+S(:LU3PW]_L403:) +M;%U^&0)I;3,5VN`.,^\8Y*C&3-FKC8![&'1D6;.:JR,)HQH?>?5>X8[;!T@? +M'XK@H,%0+(2E4XLXFX%$A)R",:6CHF<7I2"V6EPIFNK]YXW(X?-G#7^O*(M5 +M,Z>=WQ=,1_GRYGKQ%K<5YF]1A98Z<>)#\N.6"XG@I)Z:Z@.7;W@D:H)12"TV +M1(]*XKD;CE)''R3;N'8)_#.X4$GHI7>8T/JX:'[6XTT:(=6<9(7F(Y=SU<,X +M6DNB>X^(/6@*MQ_%D,3OVS1K^=)/IHC">0+SO31$`@C*RZ,:MZFI!EE_LT,B +MR8-!9+N+,.V]AB<B-F("!EN[)DZE>#;J$((R@LS>PQ$.D^0PDQ/AO1_!`HK] +MFMF.=FXM2G;RL33?2PN>8,TNLD4HHC;WAK+,/W<!M)I-!1;(!<)X?R>_V]GM +M%XDE(?`J.MP@^^P"EV7?4G86X`4!XDDTY5.C5:$6VG7^Y^3@U$F[YO6`?21G +M*C=<PTG8?62TP2#<_#T8IMG)9^C=+Z@9X*"]+F*!5C,D_^P)*`D"`Y0AI=AT +M\<<$6QEZ_1NF`N@X$*3<<((%$["1^^6E54K^*P6QH*WB7N2OG>23(YZJJAV> +M#:6+/I0R!3L(I>:X"C59GHMW@G]X28"BKN',A%UU<QD*\;(ILT"/*P,,3)K: +M%\B@M1]9>)*+7=85I7NK1S,LP**6$HA_IO)IVGLM9-0[V8+=(/#N?K]3P2:S +ML"<*<QJ9*CX4:BU/WL\^"(@)WXT<UL;UZ4YKH%L75=]`I6<@+8NP-RTJ<L_' +MZZ[?\?X:3D^11W"+,6Q?"W)%[0SVZ5G*^(1@CRO\&S>TG/\?Q$O%U;*O#X]; +M9BE?KPDS\A7EH;0G2PKT9@.PE;*OL%DFO2\\J$P&-=*_RZ$P6SE5)#`1P2<J +MO#+2A'>=CU`<H"PR9I#%7--QL33UEA[5FQJQB>^<60IL%8VY;!FZO=\PP.*9 +MN'6-5:'!9AMET'G/VK^*R+'A&!:UDY)/BU(Z>Y+EZFSN."<\`!H;[;(:<>%] +M6-3S?04-&PF*74L_W1`!T10OT78N5*,F'=S[+H/*O;$/F^6.Q+;MQ."*(S3' +MUM/1P*/=&QER20S(P=:08UADG*N0.=KT]F5OOZ'0D^GQ5AHRWL6V`\_P7&1M +M!<*IZ\;37Q15*R4O81Q0'R;5D3#F33]*J+=_XO9S*AR8W2WK-DI)Q<E7/.\W +MJ0M87F)<H?-IG6:&.\`I%<@%X[T);E[_K@K:NJ?I5+8G-^\?/#]P?4_1"-:& +M]%)P!CL':T$?4+#)<\`ZH]I<RZT05T,8C23<U00>BD0*7C/6FNUE1E\9?8(% +M*Q7&-^R[^N0#1+="Y?>FF2T#K6R3JS*RWK)3K>;X46Z9>'@+SOBY-8OA0\8, +MN"87O;`[W72Y"155W&06).>0Y1^KO)(]RR<!K155#?204MB^>I.<J9;&:575 +M$93A.<B3O3P!2OJ5*';>GVIWWK9(_?_X;X&'LKXOI^7C]&V\O(D.3W3&*,>9 +M;**-@=:0_A:(I?\L$-IY]GJ-%3=\CSQ-K4N[=,[72Y:O*E-[CA?T?LF4F4UJ +MT3L29Y15'2Z,TYQ3+4'%V*%IK=8LG%QF/[V,6.#X$0%X?UK?,Q^ZEX&&;M*. +M[`=D\8Q,:B!QECJ\A?MVD40^5D<4J.X9R\F%%1"F4_"4:P=LS^J"#<^%!+]6 +MTC^IHNE';KO+<@B85]YOJZN=5?$Q54>D/0O.5<LK9!\\8*=*%`YP+6F/H+R) +MPQUSU<>Z\6H_YZ*3C0NIY5Z$+I,)NJ263+K3TA,;%?5V&W1<43BZU2X.:U86 +MK!1^N35'0X&>:(+X5Y*=D7O/PE>45PCG.JA&@QM6HVM%P$2P#6VT*3)51+6> +M3']`K#2HO5<4<P`+%5YHG-,3?&0Z6$#KT0ABOY1O)*7!6#V[H/*`"6/UM-I[ +M-"S<?['ZM=@YP[**+=`M#'X+,<R*5DAT)VT=)DWXH3NQ9H%QBH3`#Q.G7QUP +M@I.^6),;*D^Z;)_!4P;(AP,^63UJYL*A^`HE9_KSV%09?;B87(-KZEU08K3( +M/^WR%.8)I'\*%,R/4TMMNR5M`CY9T#K1OQ(V]DMKE^Y1MB;KZKCJLW$,J"&W +M40\NE$=Q\;+?*%;QNLW'&HH0]_X#UEQT[EV:QVPOGA6YZQE<<4/O@+J1R1V[ +M27G3<_0R]T&LUVI!?9;@5O)ZE?^B-&N@+*"`;>!2X&"Q]'$XD#Z[GNU+M[-\ +MHKL%S5+3=%\R9O=K+8,G[/1D%$]FJ%E0AC[I&^21C._.VCX_6YV=%HPK12YA +M!3+&K"9JLOM4:D#/VNS"^Q`-3HKXBLU82>V2C8QQ$1L[1!LP74]TQR[0=]]T +M.?=L!]?)%^[\"H(7.Y2_SKW$LFB[_B"U;Q=:MQLI#@4H]I0(=3FC<B4I;QO6 +MML)AKK0UZ'R41?2YCQ!R<$4C!D.!J="7=P02:I8#R(`S;>ZE)W/`W5'>3Q-S +M6P=^M?#<:G5MPP7[0X7]K"[2\J1Y9N(M!W`MK7?D[D8BFD-GF_D$H?R!E23/ +M?4TEU[Y-?V,7)]R<]2?\9N03F>*OYYB7T\/3U,\Z+3;PL/1VDIT%#K:FBEX\ +MY[.7@ZZA*OR.@R"H:A&?U0P/CR!2\,'B@A%6GO&P8![)9:\SDD,<NA+."6IY +M;PF\"9\>&Y7V3L<ZAX_=V-5GEX9,ZE;T4&+19*&BAAGY:S$_2,:8K&I_`:0& +MW^,:8C)1GKY0P:&8`^"5B:&"OS]&/_N-CVBC)ALLY#[;Q)WT)@8-L#W=G!UA +M(%9M:[G\)KATI([J[(QK4IFTB^"4VK"KU/8(]49!-,LYNR#?RI<S;`SF&8`V +M:G5,P1`D09<0(KD3#%@2RO%$4,'&IC2>F%.*^1DX`=0N77G1/9[4?:DY3$H) +ML!&>8J+.'74WP/?J'"PX0**.JY>#JE:ZY.M[\@ILF'+?UM(9<0/R=)FD;%HF +M31'UP8P"_>N_:M/H:VAI4:'16::PWJUZG5M6^=XII*)+*S_?C6*!-<KP!/5M +M[M^Z<7DNH\2@)<$.5U.<K>46UO<6M$T7,3'B70$?QY=8DHQVOOQGQ@$1^%#, +M$%/,]7A1XG,&PB@O6HYN=PYD_QG%):81E&XEHU.JG"B.$^-*MZ73+:6$?=^I +M3#:Q/7"8KMK)0'0&_MF:V8(!!\PL?SZ./V"Y<_P_`0'Q1MTU_89,U&?D0Z?S +MK1Q1S\'.U]):W>X)=#NN!!S*XB9"[1I:1['.C4Z'5$KZDAQ6`UI]A&`-JGH, +MD('!X!`S!/N:^6UUUL7M-BW\9^*#^`_&8)K=<*!\X&?'>M$A"EC.#C.XN@#I +M#I&'<GZ73O--C7GCPGQ`ZJSH8SUJP5@-^135(A-G_U,PT")^J3=M@[BO)B9\ +MH81M]=S(-\YA)=9I?O-;5>0K7D(^XTSEU[GMN,W7$2?>:9&;"=L:LE"QV>"W +M5%W>W*5-';W,/"3KD69L`0;<TN*3&?L>9W#J78R\AO)BHD*F"7>@`JX*W;%8 +MT)'.:,&^XRRA9=?C:^R:!L,S&O6T4_G[]CD[)(:6"-J;6Q>$F>X-C1@\;8UD +M&X06K%YH/M#*Y0QUT=(VE'5/U'-.<<K%IW^<_5G=(JL5CZ^B3315%GBG';N8 +MGLZRKN1$EG!'GQ[RD+Q+C_E._=+"L%`EQ%D%@CBZH!@OIF42O0^OE>4+T3PW +MGH2G.27FNY\('/T]2GY^NZ*U_YA[24'P*>A[*\*+;]I<&H6&`/>>JX-4D1J* +MZ`TBH^V':<`XHJ=/Z"6WR*GR[1["0)1I4!7T>">^MEX`$8(,?-Z-)>L9Y+[` +MU0OXJ\5X%$@2Q"_UETZV:O[R/V<-3FV=M"++6@9L=ORGVPN+Z^6!KY/$W16] +MW+7]V>)F">\J#S2WHJ$+-Q?OT8&YUGXWH7=K*$.<ZZRJ24AXWZAP*DS+8Q(1 +M6/2M&W<WB(IS_?&;&=,ZBT//W1XMVY_VMC&J:UC5RQ/BT=0K/^U`QG"=Y#"Y +MJMV'6)LW<F7=);U+)S'[JPUH.9Z,3MWH0.XM(7OQZ%TSFI@>P8H4$U5P176V +M7N%G1,,`C5W"+DM/]5].UJ]@9B$:?XXP%BRY6[-O.9TDVWD9*U4&XR]1"XU_ +MY-V$B)ZHSXQ@B,)8[TE!PB_2'1-UP4DS1Y+1<*.#9WS*29C@VD1)_1W@W)9V +M?U1@3`8:(X7H1.4Z(`-AB],]NGCU1D*/]Z[22NC!B1/TSTL`,>+1UC;"IYI7 +MB*E'F&5J3NF"7W(/:;]!FI/2(:.:1EV/4RN&U$2=?DA50M[T/;%L>F9-Y792 +M9(;*!RG5>FPI=L,#Y^]<EEW_T?")2SA#9%[YFN_:-RCI93U/L!;?9LR`"WFX +MY0UM"<^@$^N/C,E9SB--,`<!"^I?SV=0H0[+,EDS2-VU.T$CP=SOND5Z?*=8 +M2_O#2MZL%2.RW25'+S.W_5HUHH;&OKZK!(#ZFF@RBX1-]"\2P+O'3!XRP[<B +MI;1UQ/P`0D@)/Y/Y@C$P:\^\.\1TBW1)+>M+]-X8;SB?$@`P[#%9R8UMC['? +M3'F.(I3"A&]<G+`YM/!D?;^>=BC*P$)1*O.PHV/:<1"JW0![D4@G'&O!`X%T +MON[T#U67N533XD<`5&A"P`@8"ZV*$MR4?0WG[HN8;.-7RM49,Z>>CHX7,5*& +MMZU@?^79<*7\C*9(OF,6FN3<[<,:JRQZM;-"_X5S#3:1I.^M5`[V.3_9+-E! +MR$7PHHJZL'<T`32:TCM-^[,O)6P%@$L((J)N>&IV<!!OY,M3/G-8`8"C3U:# +M:.J)QJ426A*I1<Q]70`\*JW:#'_P:U]U<MUM/Y1/?Z\RW0BVSJU[(-9JUJUG +MV1>?#8SEL%4U,OF=,8M*^H/K^*#WA"#/7CI'TD"CDUQ%M,/7)OGW$5-.M>", +M"BFYK)]J"]41-9M1W:M`I-\VF'D#`IER>$4+K,"13Q<D4I!B11HLS2E6-`BM +MR'E,!FS2C'U<`U51X`5=;EL/W<>]P-PHZ,!N)!UR377!,;8BSJ"^3#O8QWR! +M%L`KI4Y(T6->^%X[',<GG'=:<EEX\OP<WYD>TW#^DD$]#<0.&U^/'./]4'P@ +MJ,ZWZ<`++.T..YZ=>5>G[)G*1IE`<?@L";@C(X;KL2)/%J-W`!`R#LVQ0#A+ +MCHJ@QX?6"5[`(6N@N&[Q.6LK4;&QUH.3>.'Q`5J3E4UI:2AHV(1G`3QW>@G: +M<;"/F<.?SY&,;#C,`C#$Y."6B"Q7<7"T@)NR[;)&4,KS=YS_D<=SRJ2<\J\> +M0$&YPKV]RI9.<'^&WDQFX5(!.1."F%"?P84(*ZRUP1JKB=_Y0$R"D3`X@M)S +MV-UC73G>CBN.VE46+;6_WXTY`KN,&GC2JDC$WD79L^5F'D(93QUQ4)UOCNEX +M@^YM[#\D5C5MV,>NHUT,`<D)A:GNK#RK$J/70I@O5Y0.\4+8GF6@`!=.;R^E +MO\W%<P0*R*QHRVN21+>7*+LM,]<<X6Q$%_"8;<A:/W4'E/4T9>%4W+]3N[[6 +MVD4;M`-;"6>V?9!K7".,W0<P'186&N:)CKKMLCO:?F;HM;@DT\?-?LLB#J!5 +M;6>"<1L&W3F![':!PR)H93--K$@P(T/"[KWO^^7TYMO'Q;#6E`#;^G(OAYX+ +M(<;*<E7O+-%#;[+50;7!,UIASUH4'(93O7C\B]^B(/2R%#EP9`L-TL6^HQ3! +M':`_'-%6%PK!@S4Z2S[8U&6-,[S'XC!$@[9+,DZ4N4ZGW#&@&[#>MKL($S@< +M9.JUA\>%34?4WD#=&$?3VH>1%`3IB5@**L3F+I>/-^T4+YMDS;BUP^GMW&'X +MB<^!,5D&(,!"".H#%]-!)7\SQ(N4G<78.-F2_^['46HOWM+[[$`\"*A*X.P, +M_^+N.+%LV.LW?R%0/,>HQTB>][:X/+&LC?NLCL3V?2!KVQJ9`0!)I)#OC&EE +M/2SO8XR_9`7M6:)I.?=LLS]LQ#2V$>F#[R.0Q:Z79((Y*JKV9?P6=0/^QRL4 +MJ*'QOC:W?CZS.ZAVN=*Y3_U"BA%<0M!ZU`M9I4LLQ_TB@`V#BEDV5Y4"Y[G3 +M5U4!&R=+(9:$=IH;@-M-D1.@!>7.VBN:XA4RU\RL94*RKNM6>R=A0%4$2$,? +M(TEN>$R7''@"[JXOZ7LMVW5V-N8E$7XZ^V7BV#!=-4#6Z@S=@%]I1'LF';?' +M#$^>@R.O5G!\J>OP9@6IH\G+7U&6(A$/]%)T@T1V+QL^=ZJ0;`G>-;"Y>T]Y +ME06A,#^3(D3Z;$G__E\I*6)XORMZ2]_2:2&YW3?-@P_UKWZ_+;HJ"CS_("MX +M#+F6!A-RL'P:>'J:EGRX>XV%E*=:?OA(;63"6Z2]6IJ[/6HKFU'4CI'.Y`S3 +M&,"1+W6G[ARXK$ZEY&`!O((:H`SNLW?@T.63YR?,EWOY9)H#*C^]Y4I],$F' +MI9&;6[V\,@K,(?R7?*,]IAZ/4]QQ'RL*>D`#%4@G!51+JGZ"OU9SY]="K+MD +MY,4%==L>L)?3`$AK.YET@R&7&M'-O?:!-C'N$+M4#'P'^R%HZYP^B1;"UO<W +M*-]7!UVMF(!QSM5!2UY79V/7=4"3/WU6,R.34F`5&F)F$.>`U;V(EZ1ZZO-^ +MI-H=52DX,*U33EAW0(X<P9[<T'N8&A]:#B$.)9BS6YGF_*)'DT',=G'Z:2`X +MM2S([?UL.RIQ0A'P,E0)IE[@6M<<@'GK@2"84;3DEU.4DOGO942Y.8ES=`.& +MY3J)';OPV#/IH\]EE?7'FK>3T9=37;S=%]M-F3L,BVHERNX/2^V@[*:.4D&` +M"NR#]GE@%4SJ>G/LD3.C*$2UD)]?M<9$R,,::&WZ21?>P0QMI%V.YV>%R]*D +M3E#Q#79ZAA!IZA)'10GC&UZ)OL<,44[?++'&R3H_^>!3;[E"4I^4C%!\KP7* +MB!4"Q;ZZ5#9'0MOOWLWYK$AXG9:Y-3Y99<36RW&J37;;-Q".FI/::#+1RUO2 +MC8W;!TO"KY\8R&WAR?*!6R24_:!OU5;C9.]M'/DUTJ2DTB-BY$*(:,T)_7%+ +MR5`31^%-6#&T"[-Y*<2-;'I-T3Z285T+$Q'^XZO+_%E+`SK[4`T@#'A(L6Q9 +M!9L4P_#^E!K[9[44#+(<Q=:6]7V`$_BD&DS-@@N":)^!;)**['5QT_8J^LMB +M?3N'[\2-Y+^;I8C%N7M+9K+F2.4QU/JC*I!64T%H>BHP]T5$^F69,^F"WJT7 +MGR(/JEEC#.41B[P'<MS-S'-)6>R#7=>;:9J7$4?DHXBPMHS4;`-O\,@LOQCE +M^@<);\-3E^1(JT])C'#!\GL8:K3R):D4%O^`AF:X%ONE^T%R.TLH1#0I%6>! +M[.S<-^!]P_292-[#[J$\%TVZ(+OX27^ZC`B4E$*#U5^E'./0OYI]`/F>]-F$ +MX>4!8\']FZ<OC\+L]YFBH3#7MQV!S9?W'TKQ)^XM$X$V-#*T,'T7I@%GKT70 +M!AT)ON0'&Z'@+U2]E_';75M77.;<V#6[R,)"':P:38D?];M1ZC)>+,--6X&S +MVM)7/;II\9ANT?*#S@;"4((^:[+(_8@_SX-J)Z:TAF`*.-*EG3:!4B2-Y0', +MF(R$PLFMF@JEZWQU?NLLQ)O$TR?MH="_9<B@NK&UM1+D*US1S%O+G7GY_1"E +M'I\K_;R.G_M+;RL&[N7,RG)^9)J$QK?V"X';Y'6*Z!P;>)'-XAEJ47O-%@0Q +M>HI(T>__2E']_7ZC+FS)SHNG-A0G41R)K)0N,:%L2$8P_8F"603C#_V_FQU' +M/7DRC/1J\"2^7VC\:>93=`/5$T2#`AW(AT`^MY.E3@M02HS/B%0<G-/_[_;Z +M+(*HO7J7$FGTA5STV3`@;+>W&_JQ]E5Q1SP^03;.GH!%NR"/026]8U]ZS9Z9 +M:/<B$!YC/Y+W+(C)'JJT7X7L2LOX9$Y67VJ8(;XQB,;C'SR[!4>\;K7V6!Z+ +MUU(`Y;;7.=;YY;=M6"AE0R6OE#_G#!_7>^K[C(T59SGV_NH'I9M\8Q12#VA? +M82"/V&B!1H#!LZ78AU!N(HN&E[F"C4VQ#BQ#M82N%P6SL'F_0_(^9'4,2P^T +MZ3[H6#?H6@').+D.ZG8Y8KT::O:1._$">Z\\O?__Y]V:@=:[8L1FEY%3`EG2 +M)R\QO232?WWCKL!,PW1XKTI'$FNA478/I'.>.H(&/ZG[F4#5S_DDX?3DTAF+ +M'UFE)**"=VR*@:"_OTK^*K@0$VLR+U8]&?DBL9?V<B(->"#)&&V[PH>'J)QB +MZN$Y!$HMD(XY"B7J)-]-OJZH*/T-U#[5>@'/H_]A6C`12@H30>\]@X5`;G^D +MVK$!0YU,>)L[][2J"1.<FU]LDKA#G\F!EU\[VTDI;9+_K4ZLM7VD_3%/."FX +M/Y!MA7P"J-$;YK,T4AU2L)VU1JFC5LQO=ADAD]]X&:3A'M&V^8;Z/`E0(>], +M&]';__Y_RG1"2=_EQH"(9)+3SPTE,)QVE:XC7THRT6=M4QH$7Z-H!H#&T[*O +M1.[6Z"7`)V-)"I97>E+&W7"&)@UQG8-KJH/1X0->(1J[?B"H\(<:Z:LF=^)= +MT+^W#4I9PO.[#1L2T/ZTUQ".QQ_2*F%GO-__%QX1,7-[.GS/+K/*&=H3'P63 +M2#I>-2J#18:-7GQM.=]Y+108B2"R7M[K$3\IH;]@V#>O83[%EQY1UC$QDE2M +MB3'>5'*&'$+KE;G954JM(._(M41GP$:KB)*'Z`#REP)PNOZ5%^>IP[*8+=SV +M0$<!X#:<1CMKE+[B.FWHD78QP8K&PXCO3"3-+*=BN]Z*9@[SA3C:+:=[@KI& +MP#2W8E4Z`XX-,3A:6]-O^5J[!?^+R36NQKG0[UK8,!+L_B4LLE*BD)2=-N2+ +M<69:1F1$_]JWOM#KE5RQTLL_^,'_M:S!^+^L2#[%W)$0^THM5T$-C2"F#SX, +ML"01^,>T:@WN%,GI:/D_?[)N!ALK%YJ';]&Q9**5G]7Y2`2(RVC6.F#CQTA/ +M*5&_@8/[@$=V;VS_/OM-MY-U<@QX(D/X0=[+&HCX(6!&'+E42+2NV:;I96*4 +M[Q^]P.'*%#3"4XW=PS8*'<=:EHF$[DT4]!ZE]Y^?[8N`!OD;)??T^L6D6R+) +M+,Y+$]*[ACY["+=25[ZNP@_>:G"J>XHTVI5^[RZV6(Z:2&^6%:^!0,8X5S+1 +MR5]?&J?HIYV=L0[RBC0WGJ"54??80PA],/N<]B%&QW,8W(,E/]4/*%/0:D:B +MHN\[\T<`L[,LEO&(7$)B<"C6F4J=IY\T1'/:ZAY%H^+TBU_!O>J];T'#>@1: +M9Y\3,Y:\U49JC#I3UI2#AT"4G@>H4>CHMD#67M./YJ9R_E/(*,F]F$D)%-3= +M_R/$(,6_1X7Y=VU^J*,YBK8I=%;UA^"!!U_$>]I$T6B;_N(-POQ_0\O<9O6V +M#YEQ)A8\/?MNT*12WYX@]B^_Y-;/$Y[`3DOC3?(L][F$N^H"=\9.C*,$9.LO +MM;."#<%KMIC`<#Q2)(_HXM",;](W\GU@G.]@O[[Y)G'6;6`PZ_'S<2,T",3A +M&)+?PT@9".F\V_AAMMBH.0]8D,5I[YM2JL/(0K.C1&E;WQKMO]((3,8P,3A9 +M\!U[<?_C'P,/*$W/\4_7]4PT.S'P\=@;C3&&*`BXWN(DR.92S!AM,]$N.G\" +M@/@0HHS^@C.+A.2P.S!,#*.A3\^/['`,,S+[BA:Q0)]MWSYN^-',#A))*U09 +M:UL<*CFD5I=\)`<5XQI`X4F6:M<J/US0KUX_NW.TDN<IO%H?_;D3"/?ZVI,U +M>&03L;B#M_D(\&LQ0W\))X.,(I"=\XPB,,+O>``WB1:$)(9>N1:G(9IV)[FI +MZH@[H3Y)B%FF;X4]DO#<@POVL)PFGMVD6-.&&Y*2X!+>/(^TZ:XZKW8R?R1= +MVS2KPO?!\G"/+$3,D^P3P>:S),G,9Y0'\6(H,0.;LQGV+)PV4$M.@M>C7!;0 +M8T@P[]LXW/"R:)':)SZL%2RI:,J5=OSST=CTQ2'3*K_J#JBY)^CSN__WW^(+ +M++"]\?O[NY[P[*4MW+]$XOYS[.\):#Q4V(KY7B1L(M`#`:Z7)*,49QE`K!@Q +MLQO7ZC"W_=2RVP8\>^ZL>R&^LH#_S[X?O%L=/=0YO&:;!>>J*?4IHA2X)S93 +M_G!6E&Y6)3MIJ@B89)3H/U<VH".EN+NI$$A3*D2\+:SM@L7SU8<37,A$-,X' +M:!9;/VJ,RW,U%VU*I3T[[+,;1Y7R2L;]$=X:3ZHGGQ_XU+JUOLW:F<_K,S-V +MZL2]QE20G!*,(6&]DI:;HJPB,CI85Z>`=7U&L_0!R%&7EIJRK]2B_-4*^+_F +MS-X+(?OHGV7X\N>H5!8`W7-L])+2_>%>PB>Y,RA`CR($I>1^E![`$FUCP<W= +M,I051'2?5=N\Z2+#TDJP\QU13LA?^PO^CR9XO+?\Z=UJ0H2(<#>/:^B&G-59 +M^5!HK?Y6E9IE5T*A$QQ>=F'1F(2EO.LG7KU="C(P]&)"_?L_E==G2Y1F;:S# +M>ZB$Z_W;X$KIZ@7U/_F!N`8G[Y3=T.T3!>[I51((P')5R&%=1F5O4CR"Y,+Z +MI+%T@'-ZY<\[I$[:$W1$1)+@><.\:`R+VLEV.6D*!.+X-!X57YFX=Y._[I'- +M<MB.HA1RE%P^.5[A$:-[_9:S$P?$WKD+K)*KG>KC_,>5"F+27&;-]G+_&K]F +MQD1BE(-8C29'6PJJ(E98PP_&Q.E&.R$(,+ZR<._K0M2^;'ZP7Z0Q)"!K=A#[ +M9*O<I!WRA[V<M*(?VM<Z;2S@;W`T;*0X0,10&8==PU&P+#[G<K>!9\34$8QW +MWNZE+)$C?Z3@L=E@"1Y=O$NC`NPF?CWB$`MR(X<!&T&_ARJD<`'+X11VE^[M +M^J7D?'!:+JTC9'PY':Z]+O.%I*1C+YHU/*9)7+3\\6"5<40'>5R09'T*9OGQ +M1F27K`TK@GH?"#$`/I'Z$#'E/[%]P9@]<%ZOYW<`"W[^H#N%=W>:2-@K$?:9 +M9FOI+WQ"%=$C)2$.H+_,#FP77M7RU-?,U;^NQT;.FM:Q';C;<KH,#$0$8\CF +MH#%H#CV)!\TSJX\T!')RWM>X9N5\L-#9@5>S3\L\,==V]5$1,\MEW?H.K/^T +M/]'0"$BIP]S"8MA5T48?]XU,UYZV`_]1\PV$+FX-:BI&$A<Q`I9B-R!<P6I> +M8:`@KN\JW@BTGI:"D]00+$)X^+=1C+&7!6BNQA1:AY#&9KQDG=%*1IH3J*'! +MX"+>LW`M';WEITQT/Z;"U9+S)9DB0PZR8R#$D>DVN['GN\__C)0?S%&PV=(( +MU2CB4W8QY((TLC;42HXS\0?16.D;X,1%0E6Y',SY8/8V7W'%PV*O(S\W\P*E +M0@1$@;2@(TIS+$)*OJ2B&.6>'BR`_JX,<R[;"+5Y<<=B5,?-%W..$-9NCEK. +M)37I)$$[Q]N+!^@'0._+-_^(W-=FI0"2W);;DC.UG:%\-@`]\=Z5\-FN!JHP +MW60OLW8HT.8V&>^+^*_=]X%-=$6[=21ZW?"]N$Y4$'091D(H[#L'&X<7A-M8 +M->;VWV;X5)0'AH8$N7HE^5S4[?#1[V]1]D`OHN&LNR[&P5S]<9_SK]*"2$%# +M>7HKBC79N/?-\^-7Z;:KBNMS<+2303MF)"6OJZ]5UKI!"P=?QZ'F6;K36;3E +M9U+OO9AT2*2\;R8.Q*%(#EA-56LP_"%NU$$2V_^TJ[KL5;!Q/STOJSC`>FWW +M9XE^I,)(=8!82.GC3JFD8`NSZ)\@,V&0@M.X.\RX_G-RZ8_!(2<GI\SHA&+R +M;4&LW5PMO1E6HNC>7#(D657U69*3.5"XKPBBO`G[][TU;AR@1);O=$SQNV], +MQFH@*M.<K;J/^IVHE,NE^P&NP65XXM3DJR8`G[96'F<?M'4,0K+OEI\ZZ<AR +M80+ABQ1&9GD7P)7O6V>V4GX9FIKA/30II(D+3Z5J@`$3+$@\^V\2EBI6I*;( +MZU:[#;>O,1:Y[8*$Y7ZQV2*;N[#U=U%**4ZOVV$/.O")__".N4VLUVTO&+?; +M7L=\@OMK;9XTU%.E-<%GY7)R!9?_FXMMJ<[9+I.I=D(70;>QBH)93`G6>9:/ +M'A5_7Z-OHP]!1/28#"=+Q=4;+I<&V2S"\>.)GY_H"%4_?#-%`#_H]Q/XY\CR +M;[+:5;A`"UL,M`Q%`+#PW8W$JL6+"-&U9:>7!NG[_@?^9!M-!?C3!*']V5/V +MIE[GQ;KT#<3F*KY>Z$GDGX7&(:AX6%V_$[AQ?!OZ.K9WC$H";DA1.?U3N.8_ +M.)V[@`H$X8S%N0/)7"-HCFD7!*?5OLF`.2Q203]U"["JS8U5`_YU,0H9^@=M +M`DLKRS%+WV4Z<ZFI7V`Z-/.8B.C1)#O@NPQ(_-/D6V5.BE!%JFJM&PPH\`TE +M;ZVV0A'W9,(_\BNO!H.&DILSY/<ZG*8CWL+!^<+Q[D_8B^I1'NH[T7^>[PP[ +MWR[L+RD<L\]<\\!&<045JBB]--=R61=;V>`+,1"W*BR"H<)2Y&P]4/4B$JN! +M!(]Y&JTDI@+L:$*<42[C$F?JD&E,["Y'V+`3']_<[?/Y^YV\V:I.5MW&TZ$I +M?^1&PF3\F2$*VC6I>LOPI!":S@ND'7*``IA@B3N(H$')MP91N?#)`,2.YI11 +MBK71.V70W@O>O/:GPB0P0?@Y]?L3IBA:=0M83P)C8:)WG="YB<M;7=?+Q*,* +M`_%.UX_Q9\D,;9)$E*4Y#U1YLG?PH?Z#^=2AXQ/@8Y_^$)NP]7C676,C%RMJ +MG\.0"\,-*)K^)(!"!W+M?SRCOGF8VM/$<%A6^KL)4BT.(.^CG10(F[O=*8ES +M\[;,U:]%J^,EJ`M"AA+5U))!\!3_%X(/&,IN'P:Z(Q'"EM$(<U`@Z<`-UG+M +MW?.:,5`,[FZ"OQ)%.&<TY:\0=4'!-TO.NS#N34TFP+9"`O9DO?+<E#`91:?K +M4+LL":=Y+DL9@WV"*I"KD#PS6S];061`0*J-<[C8)Q8/X7PHPH4!Z0/52PCE +MFWMP>52(KZC;6%!<@!"LZ`9R8*%#7-]4#">P/#JK^YHI"%F)5V8[,438_JO\ +MR[8AV!Z!=3X4$<OL[ZCSPVU\=B[Q0TE"4;/-+%>'(Z#ED>YH72@RWDD:N[[^ +M,[B:&\=@X;(36OF>R1MU52.$%14ZBJ/A5W@4CY\(->"N@)A6N;3X@;6_]P4" +M)Y0Z4:`MI./N]^=?A#[Z#YCX=I>ML'`PLG"P;H\MI!55W]E"21C0'A/E'L5% +MTSX?U]WN/R*#F>3L>L_D.+*;(`Y.3+D#Q1[ZX&4MXO#]Z`F3W,\G;#"GT)QP +MB.!H,8SWH"!YH/'5<L,\LH(H@M-L!?=20:*FL8WZNY\&`;2K'P`81>KX4J=. +MKKAM[*IM"B/8VF>N'J??%?-W!Z?FL7<(Z>F04HO/+;_5QZZA)+H6?-'^Q1=J +MZY,T?G$?RI#Y]B^V-9S,&KROS-"W29-E1=F-JXVL"\'O([S<E`(VEC<@*53% +M=SEH6A(,5Y%>1)>J@9G"X_!61,$IR0S8C9GR8WIWN27H=[2I5_Y*:=B\P`J8 +MAT>)[!2C73L(TIBN%I[)D#&_'IUUVSAB_\56()JC3,WL@M<W<E=3R._TB)A$ +M2OZ7E0"<_F2"CP[1UA89J*\.R^6`7V4*/W)`O.V"SR:-.3G<7@5@T26DJLB@ +M#MQQ$F'&D0R7QY8%')/7M.A$F@]]S^-F1]:J<7`"7&\$>@T58OA8+WG!(_4[ +MDAO(!77+`^W!::$+:`3PFT-QD^H+W[UD%G-%'2(=P57#K+F#G1@6>^Q6).*M +MH4(07-U),=^"484/#-?JM@:3!9N"O>_0#NFVF/%^L!J5$#]Y$`,J,W\<21^9 +M)BOLTT!]K)+'_]2=2X?"\8M9C:$-)L!?0F8_<-EYZ:6?L6S,0T*6?L8@W9I^ +MY7+:``+HE6A,?P*'5&/K6L$/)$MH*=817-,O'5B42R/V4Y!X:>'"_R95MQ#, +M]H`%J:OMJ205G83Y.Y1%2]P2&=_0!+5@,$F982EJX%W3HW!@3JU7!^@QH_E, +MV%I3AD]#`AFST@3@)ZPX-%*3C4$=P4VC8$$STV^`;](:W^3EKG"L7[)XVV1: +MRWB"#0[2:A\^8F0V^I3587%Q@N@-MUX\A6%W`:4B)D=K:\&:W<-$5S+KQIC! +M'.N,2<A_^(MQ@QOJVQX.L@8IAX5#"&[U&BJOK)SM=KPY9ZAC9%H4C/KLNI(> +MECA[Z]HI%0AW;5CZ2NAZGN,&;S"^C#IW\FH9)&!]<`K^.7I\UM[2$MCV=^)Z +M&4O/\5?T"22`FBR@2NJRN68>CTS2MD:B_F<Q#6Z9M@/ZXU(^BQ2*0%=:HC=1 +MN*6%[_>)Y8?(37T52<7G:RV$61]<D8`(QM?0L$O/X*DPMP'&`;/?<L':;7)A +M0O*R_6KNL_D5B;X>_:R#[O6[OD4`UYCR*7FR6$VR?15TGX]TP?1,U+Y*O5`6 +M,":D62B>O.KV=].YAPCA5-'"JBBF.ZWN;HHVY/?/?Z836&Z)]H19+IRNO'O% +M$8IK,C<`OF.N7,D".?(Y%6U_-F0F^NC_/1\)?QNG%OG])@ZZ"M`.*=\MC>D% +M?:T+(VS`-`EP%!J<3D9IOQ8K<)'1X\3:-/S#Z)`H<JK"U6>0HI0ABE8!>PX8 +MH`!Y87-$[*3^3=R%AKB,X99PH^7*QZ,,N/?9NVBTNCMC/::8<I<-66!'3U"9 +MMKL1LLK(3+_Y+MKV>R.G9Q%V#88R^\/FN1(DN[?F,C]P-OG76YYXX;`4'+\H +M_8WZ2<<8HS#WL*IM(LB(R:.#B.B*PWAW%M;N'.7J[[_-:.#B5!%`\]523[V6 +M0%9F6KT&@*FY@%\Y%AMU7S03K<D.%24L1Z\>TOX\E.80YZD.1HU6(V`OW/8( +ML3W]K%_D[US/:>I?Y?ZUY&"UUU&=`N!SLQ8C\&*HESXO;AR9>OS+%=VBG96@ +M/!&'T+0NS$.RVX"-HY,I=E'-H>%&#*X_WGW_+K?$>X1/:.YK1B^9<4@(\T;$ +M0TM)K57%%Z5]KN*;<3E<,9F7P3D16TH/Q-*Q9(:Q@1@/$<DK:\[T`]S_\'<1 +MZGI"ZP4P!)-0L?SN:4ET:@C5^P8!;4.T?_G0=&B]'^B7Q'37<8'+MNSQO\#K +MPB)*JJ;)TVU+5$#;9'/2FC.QS^)1H)M\-EBO@6P)XQD4,2S[=\;F%>-8KS+! +M^*5M%L8*_(M3*<':?6UCZYY-5\3(1G5P,-5C'A?]"B3HX,_\^GCKE2$6%-Z. +MC$YJ?X'^EU/6&G;%"4C2M"`.LKTGO]/!&>*(([@VOS\NK>2QUNTZBSFNS<,- +M&9YQ#+J=<&'(_N[1'+6*.8`;SK!2L[&"_?.Q1D=>N(6U$Z1Q\1LC:-7=JL"K +MXKAR*\W[9H.AR-`_;1Y.A50QB@&%.S,]SE7N<QF0GR`SX[90;K]8ER3[VH'W +MQB'\@@OZ[^B#R4L`03$U:YG6QU(-=_T'*&003"MK)_4*J3(5W3&RJ$IY2M1\ +M_K*6MQ<TCV'D+2!V^?]*CT@4="&`R2PSM+?]/99S2C5!^3"M7+HN%&<V0OL] +MD`GV)M\+S7IZW*Y!A_E,..(ODFE+!)A1WM$LQGW_Q_$:*LMY)JY"2V'GHUT= +M!0&J7PLMKKXMOHQ@&AOD\0'FVED/A=+#L]<&J/3N\K6HLGT:;-4:/7HM4%;R +M7B?Y=ALD?N<E./P4;&@B(^O4I$4R0+UN[-]7>S0@AQXWJ;]PJK?@\;55*%J% +M9-3+HC/\7IX4'[((V=5*[?$),6*V+UR9E^DJ',*05:)98C-[1%KQQB%I34TR +M**\A)-*K$7_7-W58S4&34&W@TS=?C:[N*S@\F)9[XZK7(6MD_8"6ZYAK#<`< +MWVRW('O=>7RNJ.U0D"%>`^_.DP-5"_=7E&V_-RS[:C5676G0/@B"<_T3L25O +M73=RX-F\V$.%7<A#L"4#N?G+"N!6GJMMM$=($P=PPV@&7JC=1`:-!M^V+1:= +M4X1%$JU,=(<1^&?;YSW!<G3JW2,`B.3Z`]?IEHY594^C,/<.RCTEM1@_H!L+ +MD-O])W_:97S;CAM2W-,"5V"DYHL*XA^=M6_/@PZ!7<%6&,6")]7J;%)TFARA +M+#[N'S:=NCZ*3$4?M7Z@M,B6\PTK'?M43%ADQWNK5@&P^=^0CW3@O^DAQIRK +MF<;#8X6[:8U$1/@*,T/Q$'^6T<%!UDNLF`_G*9[T)H<WL;3(FP71=51!`*"< +M;AU"HOBE4MF^,X3()PSF]^_[V"A<\D9H-:HH,^<C1ZYICZA..1D?!I1>+_YG +M?)DB+-+++J$L.7UN72Q9`!$T@IGX.N#IJV8$P?/"<-!5V6FG;FN-.OWAY9>4 +M`WX1D-D=*VB`DC@\*-U<IJD?G_$0LAK6*/',O5Y@;@GLFR:FR'H5NK><;_D7 +M:S?73QXNW(A/VC$8WL`-Z5%-437!2;[AIG#>(`MBY+DD^)&D8Q6)*]>L9W;D +MC/N^8U&9TV45MIDUB@PS6+<HW&\6?46^.\=Q*A<5B:3\]?4%A`,DRCGU9G5D +M%V6:"'EA&S6_VIM;@:SVASX49D*IKS($N%F#-IHE`_I]C]]V'/*0VN.3:@IO +MW`I4VXL0S975:P/VVN/>&X1T<6X?Q`(AX/"L:Q3BEKOPO*4;YVFHF5;Z,W\$ +M4;2).2>@8J$*E.:0'[UA!BDZ2*[.&X@J)/\D_H-X;+(LN97"S/,M?B'[PK,; +M[7]=RUU)3W_Z8J*0GO1"(@3^ZP\XIQ='UZ_?G8U9RQ:<'YFFTO7RD$J^JN<8 +M//&(UIKSN#NX5_^U;B#0*PU.?N[-V7T(T>N_O'0RARY06)1=-MV]!QSV/_LE +M@J,#"Y8BF/(YPD13ESA$7<1QCA/1M?ZYBZE[$'WG4Q-VC8]1LL0O(,^65HMZ +M@5R94.@6">H`(@SW,W)1NJFD/C!K]9._3!Z$$%FF.D:=!FVBJSUMHJX9X34^ +M(:/H85FIU-X8230SIF/\QJ=MI-:ZXY]%`!.Y_`"]B##A9^KY)82+@W:Q1UG+ +M[-@2C8\<RH$QL4D_:7.413QVCICL4(!<MO)Q=+Z!OS#?D9=!?1M04T+.6H\` +M-[6EOBNMSXMM@LML>)R:K,\38\Y+4<(=(%RDS%+EHB8_@OJ<($JIP_06W]9[ +MX/K9'C*G!M/&[;Z10+&V[9R:HH`J5VI\^8N';P/(QI4%>]>\@GC@AY82?1>L +M($-MC@Y'OKV45/VSDD^E-><,I<G$V&1**1<D"4-(G7]S2K9S1-IAK.M-[3U< +M0>5AI1M;IF[W_I0B<?GPM<ZGH[JUVH_BQ!-$(MMSI5_@2-OH[R,;W=,?O('^ +MZ*,BU2GEI-ZCZA50=AV1OO('6+S=+%\!''X]!V>ZOPS'MI?ME\#Q1RXZKS^U +M@"Z-9(^2V'=]BEPF=H#HS\\C62F8I6#M3`B6<YX#EI$_0X]:XS;?]$M$A-6Z +MLKS[:>/'X]4,HZ6`*C[;4B_/#%YQ3NTE432R2&#)OXBP7"FWNY[9^N`W,)\1 +M]$S5FTKL5QAT[]A&O<VH\F3L(+=$2;HHDYDT:O1NH?``!M$.6Q]Y#)/N<,@! +M^H%I_%>R]P],B^(^.[_2POL04T,P"_]'<5-ZX].DWG?V$3[BA\\7=G5R?X8_ +MVT<8#_$.18[C1J:U."O"'7GT"4HV-DLKS<MS7>X1%[1=]"XND*%AO==KU+[/ +M_][Q#,P;*^2>W4%04?"8FQWIMXKG[5!_H(K=1`D0!]C9K/-++(QHQV.H&-@0 +M0!R.'`A85^Y_UT<-+5S-$F2Y8P9@N)/)A9_-E8AV;;+1!71]8'U;;<9A51GL +MH*.@T5ZE:6OH,U@P711<WF'\.6ISY=QBYM((<G;=CTF4+A:\]T5=H:.H\T.B +MOKZ?G%_CO3<U_['J`HX>JD?89%:L<0V:*0.4?GO`P5T&,B<J=EK^S;,5*ML+ +M3^\"3YORFOA1RHE;F^FTCGYI$L0#<2@;0DSJ8"B+<ND:P21?6DHOR:,Q5YI2 +MOT6(4P@'+`1Z1%?_<'BBJ]WM#_<'A3'O[:FX;3[O;YOV30?(IJCSEK[C]E!C +MWA@ZSHH!L8,N"[MU:&7N<>W8#')^%Z)(*%VCI5':S[L66W$#N^M:PXNR!>!4 +ME[C/CJH[9!XXP\)4EL(6*_`40&0.JQ]LNDV((V;"AQ'9UE'!9PBS>=?8F#0$ +MJA3-Y5DK)=IK'O9;,^+PR(V+\=['ETC?#'\67J+10NBTXWS[*/5#;9K>5]"# +M/>[TVLEC'22`/F7NPC#>9[U1X]/1GFO0`E9V%!(N!83<.:\6TIY/1NJH5H$+ +MPP=M)P*G/MW3W%WH`O%-&!OWD#Q)</?]V](#N4I!7O0_-9V&$FD9#]$IX+`/ +M:2>TO$:@^/A#*W";5F$?N+,L53LO-]>+U1"0<2;5H>T+7!;1D?@<DTPM?`K/ +MKL#?_@.X^5FM)1W!--O9$:F,BUO]CU@O=IP^,1J-)4O=I?[W]4O5VTM-)NDB +M>021VR&'UE8EI.TQ7"B4A?T_KE;K.S[74=J1L3J1C<*W19I0?1&TP;^-^)M, +M=;#Q0(7=^OA>4=6;Z_'?-ZHN#U!?Y,CP;OF*!BLDQN=<5.\&0E/>R1]WWI]V +MFF8QOHJQ.,0A23O"Q=*O6^*T=*3]:K%'B_I6JD*Y2]L2.8U]6JPU^N6;!XJX +M@[*51R;NLW4[B2S90D0Q.WX0KAE7%HVQK4;YNRYQ%5Y02ZSY%9!X?!6+I)+8 +M-@+AV"8F-ME#2YQ`]I]F;,(G?6@WJ]03BI<1JT'--JRZ03%MM31')MP.+[N- +MO`@3'3LW;/7BI0&)3)?Y/M]N&+^5=Z*(F+:_>]-7T&7FO:4QS'L+??R8HX;V +MSMF>&VGYO)+SOKMXB5H-,R41;/?,1U5$]%T7;>$RF<@FT.PG]0;Z^8FG5*^; +M`H58=OQSI>Z1>Y"C9H'EZ_]_&8;5QG6.RU,N"3>EZG96'K+1WV1X-7P<^[<D +M4,U15]MX>^^9Z;:U=:NBK1K<)$:]=(1'T538;"&A;L3_OKY>602`0YIYA@:; +M:YJPI$S1<>]$+F+YZ'_REY3"RY%WO/<,2N7E,6*"FUR,0'Z\PDVB8E6!9Q+F +MG^!1M8$T-*>,AY:#($R=A"SM0<!1P/(G8Y.WJ'8>1"-&(U:R<R8OCIV5+VG[ +M<%J9E95UA/B#AZBZ.EPKM\YR*;@4M2_7AX%MRY;^614_X[V9D'$H%LB;VX*3 +M`1K+R,232"I*FMTCZ^OAQDW57*3R&HJXDF$:*;\LH'7T9#.6P*0`<+"%4J6Z +M".%B/)!EGE7DM8];_,7R,B+_M`B;&*'YV$1Z^=#0]_3//EKR@!Q4WD6BD8=) +M&HDWP`WU&VD!H,*MQ78*3ZQ&`/%;?4Y]XNR@O=HY@4P\.$AQ%;LLAX=@A#C_ +MLYDHPZGMRI3H]\\7#)$^)M%V[X'>&Q"&6*1Y8WJ<NJ<XIN=0EY(8=>B(D2^C +M*.>S)3H"6/[VRZ//N,342S8.-,BNO))_"8Y-D`W,J!YQ$"8"1#:;P/OUT!*! +MX9:3PC9/C2O>U?:<M;`*%(9[]GL`D73/MQW;U;_<;$3O?XRO!#*LA(E7C$#A +MN:<2?(1W@CIH:IB@(%DQ"]!RQIFZ+^73IBD^K8ZH\_"C<G\%,&]V$#OYKFI> +M$3LHP3O[^FH(]J/!7%MUN%RN.R]"LT:K$C]$PR!#D..#FOQ@(@%P"DKK2].@ +MRU0IX?T[*J+B'B%DV$F_MZ-5\#/H.$F+C+D3J)@C:9_[PP>BP@DWQ:0RFC&? +M?RP>?5%\4=&`"C0W3[!5:%KQE<V*W'BS/+4*C^B8A9%%N4#NH$*LIX!LT%^^ +M/!F5\)I0/4[E?1_TF_&`,2G1W6Y0)UV#U#__)5^P$:0[NM34H!]DQ@"+D,P2 +M.VFG*;7_X>CP%@N=US";*4WIJ\BK$=2H:9[JUW71J_IWDQ^A;21'U"57<_/, +M5]/E@%`7Q`U$=$FT;-Z,OG/*T=YJ)R^Q2<;FMB`4V<"#EC6$(G%Y<&7R`PL, +M3$SEW[?D<[)`AKP>IP3=<$NRO3=4AJE`P@"#R/BAZNW--"_HCUA`>0`DE@(R +MX3=\A/FWD9A`#*T^C+JS:=[*G&]:`&7[)_!+Z'&:Q\;^H[]^M0OW":R$9CXV +M&DP+@?M\#X>R^X[5&0\H2&-KSSROYA295NT1D3E)I_WR6]+87Y^R?"SH3W?7 +MG0P8\N6'NS-YQCGKVSEG:L,BM)#%#@&R[5`-JT8O"TE=NF)<C=%\YE"!]`;^ +MD%3U`G,.P+Q>=JS*J5/9()4_`L?_28MRWGMSFT\N).&F=6/+I=(UGLF%"L`M +M[99N!<Y\/S"%#IK'S[>0S3=/,B"R`HXR,@0-P;^/O@"*!J2L5;<Q$L0-6@F[ +M9=Z5TXP+Y:%^2+:C,>V3>I81RRNQ$/@'W+ER!>DQJV/O[./MOW77J9;,4NR+ +MK2.J+&P7SZO](C[!Q7<=IW&VO6?I55_(ZJ(^%CB6T?1@`>SAWJL;\/S;S\87 +MTN7:CFW/)U21?,:E(E:6U%KH#/<V."G*/`)F'-$91FO/EG'8);,XANQDT3UR +MK^-"!?Z5I1QN>E;"\-#U!#;WA9:'W*QA'C75][ED*"/;4!O6EOOZXKW;*0]` +MT5+YJ$9<2`ZN'XYPUN5(`_@$7W2/48DN('1R83-S$@]3QSY),OS1;!@,,&O' +MT7=L!7/Q2I0TJI6KT,.3T'1,!/"V^]JYZ6/<C5&='P$^\9?C"4NMP>$NR8PG +M(^*AKQIBSQ`UQ\^%$5$?!(Q2:OP7C&[BB09#0%Q(C>&R)3&J9N'>!A0%JP!\ +MUBV<&Z\A82@L?LJ2]!I@O*N$3T`PS,:[JY@XXJS"408>C6O[;T;C&W"E+A0U +M,@@L.D,`YA\G$Y<3=U0HVJV!L\MF(6V^?&ZRUF5G?Q(B6P9!;[;7:,:`&%*3 +MAR9>%;!FD@C>Z"J&.C>7,?3JO7F,45-I)A5M<'HG!2D8BJ?Y"F'@$J^$WH*G +M;M,/%@64;9H2+B:G"Z%UP)1S#8&0P57``%SWPU&@>>[_S,3")H>C,$X1;B#' +M!DG97&K?B6&028)T[8>Y;SB:=@Z6HU-^<O9%+6LR_Z%5,%QX%@Q^V:=YW8MT +M%67,*B.W]AA5N_@8%>AU'#LRNB^2M&U'\A+N:37YFCL0[)@(T[BSN)XH[T.3 +MB]//$/JBB2/E]&4G_TB6D&3)Y[UIG5G)<@OI5(?S"Q'5.N>8V6(6L%UM.CVQ +MW`E(_G2+M*B:Y*)_A*[,)WJN+'<%.[+T_/Q71+"J6E(9&Y(?]#*B>N.1!EY1 +MMR$QZM+OO,/B3?9"I>R;X&YK"$',HOG6P$+CLGQ\Z-:!B^V;,NV;JTPNW'$5 +M'(XC'6`0*59@XP8N*_OREOC<AV&!M]OLX\Y2K8P>I])0:B9:'9(#)?PC/2!U +MK&:%849=*--5/@:#N*NY,K7JDG4HF>Z@D^%I:6!8O_:U>+2!A$ZU@_R#"\5! +M'+RM`_W[+X].6YGVEJ%DW'C>SKS#7N&A.+'VMF@Y*GA69A,ZO(&7O;EA9_3I +MS9+)AA%&'(#?0\8$7#1Y@I9&A_L6XVK=PJ'/Y&$MA;V;2<!]K%[(!0WV:N?G +MJ'&<F.5N)M/H.2)]*Q@?1//!NQ+L:A?&C!3)HPU?>JP!,PB:$9/"<0*E\9=C +MU!=>YM(;[*XBEQ]<%+4\A+M/>DO[G@^?NP)D7R[I\NOH8,M=19Z5-5+@PG[W +M\P9VN@[#-`P&=!QV/3LZ`RJ=,!2`/OZQLA&^0=_K?H>2CUA+0U<I"_=I]KU: +MZF6/V$4:+1KF$"]GXT*!Y8(%!EK^G'_+K8<9TD_RMQ6#"=(49/RRKG!-[\X9 +MGLL]-<-84D&^CD!_@340MRXP]N]NFK^N_UL@.ZN.DZK%LG+1N+_7:[+.<=3$ +M/%5WF:C!6XVT'#=94^0%:N,"A"VN;4=IO<=`*CH/VV.7F`X>'_/\_AA3TN6& +M;_M<,88UQX#0*E=#9<DNR4RK6[JJ!2<Q[[^W73,G10HK03ZLQ+@XGPTU37"A +M4J1,),W%`D6L5R1M0_D/`OZ.?I'>0CW/G.!E*)M[=/8?=`UVMQ2@TT0Q&](X +M[^?5U/9BF5..P+'C22DM,13-'G>P.53>&69RB#S^^V(ZP+V<,I>SV(-YPHF` +M/;OS[F=JROFU07+NL`#%/+R0!73?:E6M8TF':7J&ANYS[ERV\#%V?'(.#?K0 +MREY&]79N#DJ&NK]MOK^&.8I<U@D_Z#(XE5;9\1<`/Y)8*&;H##K!FX&<^^$% +M);T^^H3@-=9>X/Y5V;]<#5@OP+35GQA2@@N?*M?5_+73-DKY?RD]]*AQVI[_ +MKM-I`\O]%X-2I.-THG^_8\G*3H"@*>(41+(N4.YWK;#44@'O:=BS\)I39?5' +M;4")HF40K?R#$8E5%])Y[]2IB67O]SHP,.)P0(79^%IJ!4MO,C<Z;P\PB3)! +M<O/11%I;CG#7#8PHA79L+@X+!IJD#_-+;]X13M/)8KX=,*EQA3W,"^#BI/28 +MXP979!6$29T\(8D_TS=WOL.><)E%OM`.-L/2GXX=)MUJG-L#3,FY(/GZ57O" +MB(@6[X`A!8;]9#M+8TZR.4F%XG`!O^@;UE@D'7S@'Q,!E35=30)2LTE-H:GS +MK^N`ML%D:N)!'<P1VA0)9]<EX+B-@[BKHQY/R6HK@3!-M0(5\2M/MQ(/>!F_ +ME28*.*.EC?X=C<NL@'ZC%PMZRJSG%YU]E/J^LG\ZI$A"FXJFR$K/P?[T9&#P +MM?G[T7QU$[ON[7:+6,H\O3GI_$9%_UP-_NHY?4<L>'X82B,UXQ+H]0WPA07. +MF!>`15;B1G6W<PBF1=;Z+E:LH8/O>F_<)"_-KW^L0<[(2:Z%'Y:R[S>%.:M2 +MKD15U^\BUMH'WQPY:BVXB_=X=H@"VB`_PH]O/3[OSBPDQE0&1L_3P@H?Q1P' +M0UQL/L,72;QC(O%,RI:[>XM]35-^DBK:-]"N([=&8^1L)OL:"XUC/,T\D&%" +M"MXD6-=7UI9!,0TT24NF!REOK=$1BO4@[".V7N&-.:U\F48L8JP:;66QX\S* +MVF+T7T)]>LK5:/\A,@CL&O5):3T<G=G:6OCA:;D@7ZE9K9/<;=(@$:[.)FLZ +M2;$IW\]S2Q&?#/[:)W+4<WI`:,VG<[B7VN['$9[CLHKZ:H<`+>`!Z8[Y-QF$ +ME`TOTG=YG"DOXV=\KV(*R)Z3H@G7M9[[JO?_4=C-X)@G*!SZ.NU\M>"-F"CF +MZ@O!?PE>FXD+L5;8O*887A^=91RF)#T=_+VQ$:!TUT+`I>F\BN.FPVEC&PD^ +M`J?RJ38U#,K$(UW)F4(W)T3!&[/,PW!+TPI-!JJ-<E&&6@,F##)';&%1KOPT +M%/J@$>F0(XEP"+D3$H#F"G.=V)-WFJDQQ<4XW$]H#%;4,0^?6./O53598<P, +MS.E$7/".^JBSW"8BO`Q%BCHED[2MM.[V)]6L=Z#UV7_NIM=JI6BAC^0'V46A +M3+8DYYN#KXB'%O-RH3Z>76`+IL?P"]X!K.A5+_K`;:^LG7.ZFKM=[5/FR7S\ +M[,JA^XD^R8U#7%@Z'F`2E1;K6*MA'FX<MI*4L)^?*6+Z*UIV6NF$JU]#I`;P +M<TD.@#:T4"4>,J]`$P=I6/R4.RGPU91!DL)3L%R.UI8/,2XE@`#>H:P4E""< +M./D#"4X5N)5(\'=?!^2^-T[9G+'Y*H<4@FFR&?-\,7,%;JDFB:M)0>4!1(IK +MK)$_GH3K4NS)'UG_K6B13L<*`>"E7)'C/=4<2P<`41`>L.BZ3P*`*LO#--L' +M4YJ()M?-T8UM``T91IL^ZSX`3""D']4KM>*R);46?J),GAT<3<)8!1GWUORD +M5S>XQ(;]`^5;53,'`5`2.9L`G%X25)?N?'`(85!KX/)&QJ[EL"5`]5$;!,IM +MKP!'7[ZWR!R/U%F/@PP2UI@PS,0#5SIBBP^6.B_;^:0=JR7..5C\BY5/!57< +MGQ^%B[`JH%-#H3%+F[2A`&D6-(**GJKSVS#8R3JT`3B?G51/V*7BSU97NLC# +MV`2.;`OO3P99?WJT[$H6$QWML^"JJCZ[J84C9+Z)'X^]S3/26EXV#=PA2BJY +M6:F_1)CSZ>EI$)2QEKB%U]D^S=Y)`0*:X(,O1="[)([SE[T&(&:>B/90YYP) +MWWJE[QE&D!!BAWA-7%\'IG??*.9G%:V,Y/`0E!>Y;ZB1SYP>[;WP2=9A&46$ +M<LD0'%N;)7JDN4*"DR#_HMX]UGXN?6/^V?<V<CD1OK95'6_J&&U,?QLG6OP7 +M7;[]1).?5`$E)2'?[2KFVHIT@G,O>QFKR-"?!W'#V;O$!C++7LC-&"1J"ER. +M`$1P5H0GZ?_X*'@<"?(%SOACC'5:L>*"'4P<:J/-TX=A=\814L=[9AG:_2%S +M9=,UMCMU3B1@P_7AF;;_%['/_H7?OD(RA/'O9LE#-B0GF7\A+!C67AGP&ZZH +MKD37=&AB5B>X":10$_/CX5?D1'#DQ7**S3%FI!L/79$3L+DO>ZSP<VO7CT%C +MR&:9-P'Y74`U$CKA`/N&'Y[]Z[!=?OAG;R9/\W?Y'OK;7PV@Y%&>*3UKN(W- +M\A,L\50V.^JX>@)X%)UKL6GF,5MN:H/7RBNWNO#7O4OY7!%.K;)^'"W$2Y_* +MF$AY>Q;T5U@5^#"Q8Z.R>ZEGC?CHHQ:#QJ-=HJG<J!7?0HQ[R9H1@2JQWQB? +M#:?@PX.["DA<*U72%V='^[M+\Q6/B5F%0,XODETK"1<X.C>_F+V.35(?_+;J +M'2%*WV'B.[@71=N3;6MT.UB7HL<,\%`(P?^^25:\R78/)B)QASF.@#$8P.1V +M)BO)Q3"NW=E1QV:OQ"'<!7,!DM!<83T$8E@2T<G?3UUMA5C=Z(45BU.S^]U^ +MM6[3_79I)'/W_5N-#`/;V5YF_.XC$Y%[%`[1?(\L!8<G)K3^,,9!^:39.W;> +M!TPVU<K`D%_FZB)R7Z66,B-8,GAK:C><.RWJYH-!0OUO[XY\Z3+X-$F<2/\^ +MEN=N%[<_&B@%O@-C@U*&0W_B'W86C%`9YA0-;U#X.JD/9<Y1QT]E%:Q1&O_1 +M>'8.QX[<*V#*#(&,=N_Z`CR[/][DCO)XG,O2[FP;/FE!_!KNW8R9"?)%@:*? +M_&`FA@.(D_2&(U`LU@S7U6P;N[>D)-/9#N!3>.<)U$>&E^DU<W*;>K<19%^@ +MU[ND"A)"Q'`:7]%3_3Q2*B'5'_TT2NT"-@DTTT+WVIV0`Z)U'L5`+G=B/7G1 +MA8!!N3N'63QY#4^+3EN4+F[<;!-=0CWK"_W:H3\BH.866OOE]G`H?92.^8UA +MHE:^K326`-E"N.R$MF2(N3.*:Z*<%J!7?U+^0R2RW'9*8V%VUD^Y/DHR56Y5 +M%%X44;G+1-8[?J,A*`>(%2U1=5N:K`-*C@5-GI!+X1:@,VO)I@>R!`!'SN0* +MZ$A7\^.Z(&X:X'[552:@T?9$1\C3T%Q\^"U(U?QNJ;EPA;U;X6]A;3QLV4?D +M#MATUC^R"01.MP9YO<A[<M%@I3R74>^D;Q#(54=O0.4+@TG:Y^,YWT\U?79S +M785J\'G:F%Y.&$7`-/_.DR_[D8T.[Q5[H&R*"M/>=MSWH^C6<\1"VC6*\L&B +M*8X"MOG`</USA;#_=E_^TNS5"?PNF5"[QWN<`V*SB:KG[S*.I74LJ"C:*!CI +M3ID@[0"`L+JYA8<R/FS3#2_-4B0CJCX24[YV(S1D/#[E[`Z8T:=F^E`YB;C! +M33_):(Z)AU3*+NP%'TH%M3L^*T(9$6^<P);DM-H,?(3.YX@MP#^F8AU1;6PM +M_]'VVHRZPCVB?OV4%G95D/E'W?%X>`8B`D[UJC.=JTF;"EV'@G>1`CG!5E`. +M,O.,CU#(\`3_3SLP^'4@9U1?PVPV6&F\U=#[1![U`4^)SA&Y(I(+41:V64\U +MD*=BY[Z?UWI(5=!E$V0NP,0R2/LX!RAHBW]E`4_I@'PH7V!70(%<2E$#)T9S +M[VC$=N#)6K=#?2"I0J>O;'P$A#YTD:-+UH;O-'RLTZGD2!CJ$486$S=/T>%_ +MXK1F;ZAFVN>*SZ"9DO1J4/1%GUS/TAXEN?XLC9-'0CET63Q[]=]&^$,8)U8D +MT829M!"E98QP&7*S!``3>]&3!9-E&QZ6+$;#EQ8=9LI5"[OO.:)5AU";_3DA +MJ.8G,-5Z+.A-`9=8.P0;>URZF`#H?]YCXDB!9K#$;7]J3N,T%GP2H/>JW)": +ML.9@'#`6,^J3)WT>4\;:^RI>308H=!Q425PIVZVT4/U[\/PZ=GFM1AOO@3&F +M"K$;V&F1S\*^TD!B=V@#6_4\]]JJ/W8;/ZA+`##_&=_;NG!A;0JW5/".`GQ1 +M'ZJ49=28Y`WZDM.*GZQKRC^B9'4.Y`HB;%9%1=%2UUO/M<SX$`8QWQZM+*VM +M,17#*&S^?=ER!BUV_/-I;FBCS(<9:-#O<D/U$O;XV$;PP*'9/<7'?,&]/G`B +MX0KXQD"X&K_Y](5I8K]L46EO5I;L\01M9>P?0HU&4T(2O`LMBD7`2Z>J]CF> +MJSV=>PA^@J/N#JSEF6]O!G0M$Q=7%%>!52>%@<=EG@%8;KZW(BGJNFO#A><G +M\OVR!QB?E:S,@)7+L:%+<-B`4ZP4]N)<H04OWF*4FTQ/*M2P5O*O"JP\4<%, +MG"&^*1^(DG0<P;IAU!4!/(V`3Q&(*Q7HEI>D@KKFOXJV0R+T$2MF?6T@'FE, +M=VK-,])8<@,`_`:Y;^@]*%TMMN:^D\-K(M+24J>\Q^H/-]2&$H(:EDQ%FETI +M"I??%AUZZ'-V6P+N@=0[S2BZ#[^&0:>/BDVT*L6Q;GU;F>S>OY8X3`WW9RD& +M"^T'PJVYOUD\-.#)G;C.EW9/#4]&\)XA)%!0RZNL(RAIPB]/?3U0>/P)I[13 +M&>AL:+)1KU)`5DT0O2YU?8$M4%P^:S;]]B+>1!!CX^NO,CPV,M;;GUO1Z@,R +M(F`X"6/.%<EX29"W^XGW52)&#]II25)&UR>#X@+L?P](_V$^]LG.X](AQ;#G +M)HT=AJ9%M/04IQ4T?="*OK=3BC0&1.&!;VSDYO;S=3>0$,-)-M?U>->Y[N&- +M)RY9<G@@@:U>(F76>!P+Q+K-"0_%H#_Z;G:A_+U%?.KP0HA_G6O'N(T47^9? +M)&_:*1U)3(D&!VF*N@6WD/UL(\RS2]NO0\DE6\DJ!16-5141"`IN7A;E0?." +M;R9N<B(^5+2<B\<T.VQIAF_5!Q)-0:@<6;.,FA]8CQ&<ZA?[1%L]P7>7JD/1 +M(BG-D31*^/#UG?B&R_ZAVS[3NF!PH1929H<2]"K[)3L7JB\I7!$BJ<QUR1T% +M1])B.NL1U2>[W%WWC$F!3OR&[Z:\'V\G9$OQHJTBJ0@Y8.L4%0QW(!X3TC9I +M8T%5JRQK4(R17!PL_W7-DMU3$WS!5OW>J+72=%0EM:,*&F"J7!^2+F[G"!;; +M_"5\NZ"80*R^A6V:#GES1F<7B0(9K\-#7REML0U,&?QM$%\.OK6%QD4=3,!2 +M/L.\&Q\?+SQK`]++6S"RMW>%,!@(,`7ZBZAVDD?Q-5FC:[F7DIH!JB5W[C,R +MG4F'QUF>;@"?&OR836%`@4%$MGH-2O6D?:XK/#8_X+M6I!Z9>=V3;$](2T]! +M.FJ04M3W&W$R%-M`US*8:!:[0.[.I2RB0TT*JY@L3\BR1EGJD!<8H4M%?TPS +MPM?\O#=`]HQ(PT?@Y2_%%@>P9DU1\A3@4S!SCW(QSK93+XO7R82EF4>^)WP- +M\&HJ(!)"BR/J=S-*SE(:NS,#6=ZG\YKZX5]_3C%3^=_N0$`5"V&(QE?Q8!%J +M;_`_'J?>T?VMGW4`O(%&/D,?[?GF[;XK8([<V;E-^5.V&[RC`"8P!M]5LM%_ +M[L$_N=YI8.`9N$P#JA7!5IGPEN%'6\WPD-\3<X:.<\,K6^F&$JMENRK]9_1! +M0E[6OSVR56/A"P&C"76FZ]$&[C$+Y31>EKQ$.)_L*&X0"[[^B6Z&FP!0\@F` +M5[N-XJ-)*_Q+,3JJNS]7ZEKR@XF!':VK>2$L<QZ$:U4&UV1-<>C&JS9*M8L= +M,A;\=Q!]73>33B&L)#JLP\Y&#S]3(![^\J6TY:%P1\44;9;;0@XF-27%G0KQ +MB!S2?WLB$!,#%%&/&`["Q,!<561&U0GSJ?``\9%OYRG-(6R'2V/O>6\F/'4P +MF)EL+[Y5*@9!`JHMWJ5^J6^X3#S/Y2?,_57MM54J!\Q+::6W5X-^-,5Q$K_# +M<Y8CTET)W2A9N6T.D^I52GO-YT$=\,$<]7F%G8RP^&_;]/=JE:@`P,2(%_6B +M]H'4`0N'<I=&+U?T8&DG.`*9->3U]9;`TRN\AA1G0@J$ZR:JCV)/&5/)TGMP +MP./NMC%>;X]63BQ!OT*6-`-Q!2`=C`UV3GP?%X]E+'H(#7<#0CL-T&6+R67' +M=/M2+^*1=HO#MH!X<X_;?#FHE&1KUV?_)(V>NNX,^[)HTU,,?X+/9`>A%N"S +MK=@)$-*IGHF'\+6GRX>]4=/#@UFRE>[^399=&1ZN6RSH)8<[TLMD3#4CG<W7 +MV<-<VLG^PY[821I&"E"U:$@XFQR:UYXBH0=+[NY*^>"])[9AW#B*QO*B7$L5 +MQ_0S<TTLIXK<K-"%VN!3$^L:2CT1&"1&GPV0"1QS;9E(3=+_VW,SBF.@SS/X +M2JYA.=A9OQ=M@FUJ&/E]5S>U5A`PO8Z@X$$]^&_/"B<&1(+YF82?<LFG54D` +MC)([M!P@][DW"E!IA'\CS?5LZ7)'I,S;^JN9*W"L$FGU;%C<C'XI2#3:L-%[ +M;-__YB/WL#N=;2CU>.A<9CM#0J2T2_<PO9>Y!C`>E@4?&2GI<0R'47;_V\XW +M1NE4'+J]W-%*;J`4-PU[55VE!/T'W'SP&1ZL>I]B?RB)L/[(7LS_$\LKP:J: +MR%+`3[YGMDY['0Z%N$"?F_1I6B8EAT[ADC%C/@(WO`[\P'ZIP<(^'D+K_WXF +M@&AY_D(FLW1+\=Q/Y<Z6O>1IK!8S&-F&12<#RO;B\&KR/=3L3'.<>9H6U%@< +MQ,]]HXSHM(.>#<9$,-QNX1(-F1!PB<>#?6SEH9\5RU:F[<2U@^JA.$?*08XH +MKJB$[D.+.?;*`HXSCJ1>[,^"0BQH+_R8#`LQW?<=``8G(/D?E;'?Y]T)`_>U +MMK6B!O;'H'EI]#"GZ$9W4"R*>.W66F;,?I"YC!5BH5%[PG]'3P%]]B:$:=1> +MEK@T4QPH*V*"'QR0C).[6QR#(&4._+FU1G!;0^1CNLDKPS!^H-'5HE9<I:"S +MHI$;*?ON87I]`B-K]TT)CJBWZ,(69K[^D,RL$4/*[:E&I0(Q)5A>>*'GMLQ3 +MI38QD7-#%2*LE6<KVFYSO,Z0!;@UBW^K0WAVCJ.7)IJ@!('5)^J7[`IV=>G3 +M?91@#K=_HKN,,9QK^M]#"];(-C"^DW2>L@Z4M3D(#%:)IS>4`^;`I'5<5%,/ +MO6IPT/NSX^A.C$1!_L0=TI)^QJ<_G#X7)5,.7+^E+UAYF*X2M!+#>PU=`T$> +M`I$'8\(2CU6TD:Y[S$`OE!4X9SX6]<;:]RACEGG+=GK*$QOX*E@3]6#"E<,+ +M_RQE5:W^\>T6::\8\L/%'4"M:K?).Z=+[K:1;O2:_4VAFG7?=489G:'80)V^ +M#/.70"2GFZ$Y'=]"8OT_[/%[]_*PY5U-8Z*.CP?IPN(ZV@#84MFBB7QS.QR1 +M:U^%P]$%E*8?O*I$JSTITOYBX<)X,\6%MQ-3T(U%1YY8L#D$#(IU`&WTLQ6] +M4P?Z?P_?^:.O][O+0N6]ZOL_W-^"/MMFZT%>W)MJ#56/#\S`2Q5^AIZW:^L1 +M-1YW_:_M+L)$G7!FC87KZ\DQA0_0"^U.P<XFHA.;LVW$D$-U[$]#4BJ1K@U7 +MJ+[AI"&%'=6=OD=P1N@[*U_W=]+3PT($_)D7RNS=:F0$J]2UC>5,8UDAOTCF +M`;0_^Y,YTW*?:\%9C$$D.W"$H56K$S42O7*;KX]+YZ8FX#UWC?8O(C^#Q90# +M,UGP.[A8FM"#UFF_031B.0A0/KX+LM2O#U7ZKW[()@=&ZF<[,VAQN;@KOWW" +M5E420UF=GC.77!9I:9&"CIWAKQA2E-ON#*$./0(1I>S(<Z0@<T4MM;F4N4D@ +M(RR(J50F=^*!X:SH43I4L,YMFC\G99!I%]`6\^%"P9U5<?&*!A_QL4G\.*L, +MB(U*T\Z^6I90+GAOKZ;C'IO+%9S,S6MKQCDS2UYUV8T0YK\^G2/*@=$F&ME) +MZY[Z,(.EJX!VAGT'CMR">FH7'/`!6LAE51J>IG=@5O[36U8^4K`4)SRF(E^H +MAZW<S5>=$7RMKBY[9M$A@/8@&%XWQMMZJB/HP,!#\*N`T]S</(DN`3Z&'UPW +M*+0&)$@LBX@@FUHBHV;%*U]VL^L+#RA=55`+(^]]8HFGCW!\TC'^2EFM?33/ +M<==X4$F.1\<CUV?\ZPX#.7Y95LQO3AJA&30XA3M48(ZRF/4?WW@.=T]''M+# +M4I49;;7DYVYE[Q2GL+5.`S$):C/&_H5$LI(4/.`Q%DT<>F#%_L&+URREJUP) +M*OUW7<17[3N[?_T^'VK8K/(FO@4NWJ&(?,8JNR.$BQPGI1(%0S;Z_6^O#D:; +MD_]H(/JDE%"S/D(?905DZ1O#\UHWUBH;V8MFLPPI6&)G"0E!>GBYBX;)FLYR +M5$G0()5&>&6BE&B51!3C'$I<M5;Y?R'JU,0T(S[R$:\#7T?[;6WVT/$Z?+%2 +M!#T`$E228.W?'JRL=UV%46,RPU_\O2:V4I+1'DDQR#;Q,!HWVW[BIB(RV>H$ +MQO)I]EK[QNBH><^A\:@5/=80\<U1OIGL\2;2?<MU/ALGOY>/-L+X@O3)GCR< +M&"E\5U*=?Y8$%BGAGIH-=6@^^-#38<S;1]&A]QOWOQE=)7HM[@7'A)JWT-;N +MA:#,;CVTU&[C`=MXWC4$4A^:>^N:$=D,9@-5B_FN5--4EL3"DT$X+LI%&PU; +M-@0E43R)MBOC,8/W9L>)K(\(:\]VI2\A>$@#3\\=:CP^YL])?BSH;OJUJXZ` +M@0:6J5)&E-K`43S8F4D(.!G*,<3'3PB!M+L9/[?9Q>^HB<PW=YA7$:ONN$JV +M[(0&Y%[7)Q1<K"`\)+,ZVK?TZ>*K$>,).A@NB_/@]M%<C;1I7H-HL_6R%K3/ +M[)3O2+FGQ7TP1-;)]Y88':31.HR8]PE$5KK>A+1YE8`Q!T4PO3Y'DLZW]ERU +ME-=K&TS@0(D7S0"FDIZ=NTF(Q_5H<X]:W^`>:F>?D!T>O0:@C$#2E)_S8I3< +M.ZHC-ZBE%(=?/(#>SZQGS`%@]?&M3T53>S9`4E6VV#5#!J6,GW'"6KL^5G&' +M_8WZ5E2*(:RLXZ#EA)>W%E539W55E!MSJO4SC8#8('VM-@7H\Q-:_]DM2M3& +M>6D:GS`]_(3*.M8!@D>""8:-Y?#%*-+OAK6MJ-O7'DC[4.WY0CH.?T8ICL>= +M;$$Y%46,X=KH*JI/G*2:\%4`N#=N5;^8E6</E9H\=;Z",E.7HS@.U!A;(E"2 +MP3Q<1R8)&!EY"D`L&!U9R1AE9>'.%<KO2L#9NNG?TN<DC`2)MA%^OLQ)\ZT3 +M(@LR:X,S578X(S84%4&_7"PVV"I][F-:DC).M@E;"9;],/]-,,6*S#O'@<S# +M=2HH=5\032-\5I<W=X('>(2*?[!DD^#S%6Y80%H7?&.A8F^C/ZS.ULI^J;`. +M#._J0&)--&L`.',<70%YH9R0S1Z(Q\%YZODCEY\>)[>Y[C6,*UUD2!X0=BJ; +M?18#*"ML'SBA2VIH,%R9.]1LR^@$;.I_#<JP&:Y:6YZD9380^!2#T$P#W?H# +M`$(B=3Q"O>(1YI*_+<L>@+'`1GF'VG#5^;$;S$RMP=6#O4"_3V'X<K7YI>FI +MUA'Y-'!6ZDB4!C3.NJ'\'X#NS@U5T,)T[NAY`%.WNN92Z`W@8ER?XN44LTB< +M8;WF%J'&*4C[)AWLAZJK=`[[RHH5-CV,P\NW)@V5;J$0(S\4R^1#FVOI4OP1 +M-T^I>T%59#"N+A%C@/B,K%+K)M3<^S6R%?$VC5N0VA60Z9-I`K:`SJ2I7K#$ +M1K_:GJV/;0`&QOE$-5YA'$.O*$W6^DPIM2D`)D?[?<B#GN<KQWW;<]\38(WV +M_?W7`R'">S=LVZ31)4.`_J/9_/'M--WBW8``M'0+]6#`^<"C$7B?0*E+G#VT +M@*_ZS2QDMZHN/D\G)WVS]AV5IN?,"-DS[0(X@Z"(-[_+V-Q/<K(#&L0%P,^^ +M7LIM/Z_2HCMF4#94&I7M[>S51]"]\.4GL<3ZZ#];F2D)N?5PN#`R432<$7'D +MY0"S[PP34\LLB,<M\V9A+8CP23SCC@>&P%=]UA&GHZ1&C85#+-0;A%$!<X]S +MB+Z%W:+JD;7_39K``^&K%1JZE*XD:'6$>.LV\.L3A79E)T_HX#$+A5H?!2B0 +M_)+;*JY4(1>JZ1N2?#ZI@2(KWJ[/`$N7!)Q:PE^RF3LR-X<@7@%D-<Y5:4SU +MR;"W1ZI'D+8?B:/ZN3`_0*T68*M>BZ$0U+$XDI1JB2"&L_@WNR1FMTL)X_E6 +M!;B\XOX/0875F"MTBX^9\:5YIL[S:&/+]**TV#-O8R\`J2,&;G"RL8P,@>VR +M7*)Y!O]UI%ZZ)WT.0!(HO62_P=-.V1[A&$$V*7R';UTY!Y&"WIR`5L2R^`JL +MVO(-.=\Q#,Y5BG)L[D<Q]DX#3(!)?3O>TB.U,!G-&V=CPW</YHA(7IL]9(@1 +M"3.-/*@.#N'`#&UWBLTF:&*C:Q_7/I?F]+PG/!QVEI+U\0:#"I0B=FIC%#X4 +MI1MXI9O?*:AM:V["OD/+B&"H=]Y6.`Z&X/19073^S4^L3NB[5=,S)-UEN>]. +M+R&&Z(YZ=EE?I_'\^H2^6Q8CKKZ?-*[OF8ZF]+-'Q4DPM`,O6KXW:RY1QXI\ +M85E;,J"*5QWO&V!>AYC662&K,<1HEE+];=_$*?F>\!4#MM9+F%[(P#5\\*N( +M[]#7>:XDY.*),1S4/?D2YO%L'K2.YCX(#U'<"0Z%Y(]B:X*K##[P2=2'I1NT +M[JKJ;&2N4$)<`&'-C@ZF<0E;GMB\-"L7)@,#C41`01:D,H""OYWNA\)>B)OA +MB:J^M4.PQ?]3&QPQS+X_!`VJZZ4@PT:\C^Q>H@K1EX[^V_JR$%E_%#[0[K>[ +M@SGH=(+Y*\9OVT_X4LX5+K)(@#^SB0<W&FG1[YX?XNEBV<=]7O'<3V'0V]=D +M^O?(.>]^\-)M(!:;N,@C1RP@^<'`H2,Y"F@69:%VD/)Z\DVK7*E;_J+%@W.0 +M>AT1I_%:@&37G=$+X$CTW$E>/'LSO8P/1*/$_6%_"V7X]IH\X5B+0FT_E76Y +M>UN?)KB'V5]!C!CS<`2T&Y?'5[3CMJD,2,11_L1(<?2J,A7A=0M:N%C5%UP$ +M2G95G:>3<>B1U<.M5>02O+H!-F,?@^YR[@XU`2#[S83?)#1`@F6^(6\*<"_Z +MRI8RK_II;26M[S(8+>2+WB"58#3W,Z_F#_TR3E=#[%!7W]986316QSGC^8O5 +MGK&@%S!MI19*^]CAD[<IB1(2).<[`!!%`"2^KN@$[)@<A#/:-7&F>DY%[7:6 +M[L/I3!WU(;C+8+"J]B;1C!_D=+J*&K6HP3;I"3^Q&!`H0`@V$VVKRM%>.`E[ +M=GYN?2D=V*N14OTVZ#.9+IX2&[/*ZPV]^;S`T5'@%^%:,L>]-7:BV@3*"G:; +MZ%05&]GR]-D!XXGARB[A'+S`Y?;CXP'!94:VL:J=]E6O1F?I&0KC8(=ZS9FY +MJK'JS%EWUNHN>9&.K_-4;2'&D/8@R@Q^Z:+FR7TWUC5(76RSKX)<.W(9J/)1 +MEYMO=FG^9,R<,+X"'<S95PX3Q4@:,@]"SP48VE?TY7F:G]`9]4LY+RE+Y%39 +M_KQU%`J)Q9N@9<"_@&Q7O4+YM84@[G03SGU$&"4JO`$2">\J?"FK=BJX34<@ +M[P0CSJ_1RG\W"3>_G!J1G0ZU.$I+.:W]*KZS_\KGRXD4E^=)?XO3ZF2YEP/Q +M/81_[M[,2%4GA&_[UCII2F%D1ZRV$Z3XK"/.5ER.%F(]ZF$S'@JOG`"($K'@ +MC%?P&;*E9#L@;Y6+WMSU3[?+-NAM@/E`F"-<13BN2)(B1S65X9J!J:\)]"CB +M8?8T%+R=C_?+M^)W!B2V,7]CL8/W.<A/<#W'?L3UV%XXYS<Q0T%"S'*YP'_! +ME,TUQM_@`5,IL@*R3SAK3*4%E\;+<2.4P)^2W<7$Z!FV%X)>EA6C?NQ4I0IO +MDL?GISC;/W:`=D`A-(I;N4[#\RU\=1QN*Z-`J-&5XHP>KZ<QK/H-S?#0IH"P +M+]+22Z3W(!_WK``CY#=D5OD+(."%NSJW+90Y(DE]%CZ"*42B/,954!#L@[P" +M7`("76%ZH/Y=H5QRYW1_8+QN)JGULOLOG-`?\!#>WPC&*FOB5.1DY>0T(&Q_ +M#S5#?.<#ABIIQ0@%J?"IG&+=H>Y<QX>,O2W(QN1%.L.#,MXIAJRO$^Y8KZRD +MNJM+MN@?_64["K<>Q\MXLDJW:[V,I8@I098WB;9=:'@!C]*#NL8%PS;\N0NU +MAEETR$6<HG-DX8?*)/X9F_#`F8:BB-JC>HD847[1?9[PTJ6&7PP5GZYN;383 +MY5;9^:G(/V>/`+QBU'L\OM^47<20)'.)9TK)</59RGY\RX/T#`H&[:;0I8?E +MGF'`.K!=PF>@M)@N#90@ZH^!]RW81W!SSK*IH%Z`><4F@PZW8&K2&=U</!MR +MORNDI6>5#<LD983N^K393S51\2O\B&?24EB''H<511-D#`C`\LT2M*12+#"J +M$'$("O+<0G#P.X@YW)%7$6)+#:(7/!(O>NMT-L`[#'8L?*,E_Y,`KNP',T1Q +MTEA\'U-*%;+(1ZAU`QA/7=ZWOQU7%AH/#DMD^"U(X:_73G;'&UH;5F'ZCX0= +MH_#AK/&:6&,?8\HI41^J!=:_(W?[&C&LU3<]I.;<%'@0;P;D4I)QD!62\Y&^ +MA%!MP10()X*:RD=H:S%;1TVQIYNTR]NHYQ*B+FQS;C2=$T_G$?<;'ZX4818N +MRE/B/:[^\P#<I0G::JUG7--+F%*TEJ=8COB_*WJ435@10"ZA!Q"OIN^84`-3 +MK(.UPG?07]`"&%&4(*G&)U:+$TQ1BE8[04:$B^HJH*]UDQ[MF2D)Y##9D;*J +M!=4MQ^V2(PO7]!'56(\]I>.,7/-,F=O+Y#ZU?ZM#9W6X43YFRKA^03#N,XJB +M8B<'KX952U8MU5CF>B.](?W>P!Y/_6:&D<6ZWO$/#B(B(F'7#\/X(:JGQ$IV +MNOM&;NG!-]J.ZP$7]2\0$99)QX;Y)PNMN1\SE(.C_0!IF&H/+LDGJ=<LI?V2 +M!G1\3ME<4K\C4L)]8_A)>K,22SN'O^++@0N@1^YGHI%6\[>:KRW4#5P6/[[8 +M&F*(K/(/P0B_'[-_H@3+`J2/$`^/@UP#L)\AN%]G[2WW%K"DQ[<H18?#]B6; +M>*+XAGS!,C6#"4'+M)H6%876\"E!)VW:J!#U`8EMP.T[\I=@V#;+^HXQH6:1 +M\N/C"O_41HZL"!3DBJ1R(^)EKL247A%6('YG[L?W[+'I)5$YC9UY;N=#V5@P +MWY`X67RJ,<=NDP%@`\)T]Y-&E(RKNR:9E*'<L<(!"(-+3N=84$L#!#,``0!C +M`(RP#D4``````"D``*UR```$``L`3D574P&9!P`"`$%%`U\`S-K"1>3?Y$0D +MH0./)\<61DA+L68B`S28_,=GB0X@*W[,X$Z-(.T7#,37`$X[[$E`0`U^*`JD +MGT<4TOI3(55.N/?DQ]%O891@<2*T]@(K(%?T"9GKL'S'1#H8`S-KIU-7C.?A +M.^M;_PNO^_SF%Z54^.G(M__W4[P],ZZ@6]8XN'J$P/-B?V6N)L:84"K"UO]= +M%VMH$L\-]E^4E/08SJ@%Y/(EE]!#OX4F`5O]PRIC0T]D,0']PK<M:1DO)]N8 +M6$&PUL_&>1M_<'LY=E*-2D4D[&1]%P0?($=&.!$+PS[8B`YDP_*:FG\;6\.- +M:W`X2L-+G8V0[74]F?EL;R6]X.QC/2Y,81<&M<&TH^_7@K:02^D8.[RB_2;! +MC)V.3S"M"PJ#R\(])5XISX&/?Y.PL06C#&LIF[JR.&L1.CX0T#\NJ-*8&"=' +MI-)<IGS\0OL]UQ`V/(-;HK2J8H1.BH@&4,D5*.S.+A"D5]KRF)7(PWN9<!-> +M7^YG)NG+@H?ZE8_28D3<I9'M2"#5F7RY_&+P-+*9TZ?F8<<76%H>#/!I%2`9 +M$_&.H<I"XPIT`&/'+)&LKW28T.3/0$HLYA"2P2,7N7SSH[&1H@L3IB$J=N9D +M=*0X#DKE/]_0_6<88/8;[#;!L#1UF(F:)D;\./UR:<T0Y\2F3XU5Q$I+QY:3 +M^8+I$H,AV[,)7HPJ:I*T>;8DB7]S$YX\U<,D2+$M6QV:U]LKBP-(*(*(\Z)6 +M"YV599&QUC-H!.235FXB.CP[/`[]"P&'N\B[9W5<\=]TIE^L&PHK!&L`502L +M6K3=+H?,2BXA"BSX4`"3##E&GS'D/\7\S\\SN9P=VMAEC]Z<@C7I+33H\:"/ +MK4LH.9R?$Q8IS86\)@9Q2.YWS)F;F.E6ZD(*SPW%CEXQ)A>_-\?+.>]GD-S` +M)`C>`O@7'1*"10H\_9O>[A+S2,O#MM;#I.:9I1G<9O_(_#A7L9?--181X^_$ +M4N=K+#4*$88-Y_7/CDYT0ZYS2<<K/\6/"!HMK8!O;!QI-=@Y?3KMC<>A2:[K +MFN%UPGPMM6)[#C[/^J+T%*&HAAG^MQ6Y4.!4EC!*FAS?OB6JW,=FXRHH/99; +MVQX#T))6I/+5SQV1DI)QRC:R#\BW,HQ$7%0$<</$6]T63S4*>V.L=>1^#4)" +MZ>@#F;E^9M`S=)Y=4L3>I7F7RY7P5LKP^2X$^2\TWK"7N21/OR(YQY,>;;5[ +MX4ZDC\&+DB_]*Q]1!SOWL!`W<?)G.8F3X+6D7K4<N"+6H_*]]'4Q?T[I$%.E +MW%5CU1Q6.#JV!Z_B5]9O/LP`K7W^I%&IM\/9W4R@%I%WS#6:`@[>N&DB^%7% +MYBCDB#@P;>GP9R9@3E:;LCCJZ'7S@7;23]+\.LOM\8Z")Y/(@O(Z$47&99Y) +M"74CIO1STHS'O=9*#*(W.D\XTZ,<#MYLHQ_>;*+(B*2+7T-,O[ZPM"F2R$#@ +MIM;K[F6VR^YA#\^/FF:WO"G:WIKJJA'08>^U[$KE#5]QBZ32=9_C30FF+*!L +MV:0))%7N8#%I`P^=DYL)PD0=*MC!EW6=QD?9^BX%5TT)S3S:8H+;XW]5Q^H^ +MY_-!WVU2FJRAMS.C*LD8`]RWH8#M'EMH0&_\A\BJ?!EG!A9<M!S(G(@W=-^7 +M/L97I45/7+5VS#R28IV^-.&`+!1W1A'*>=PY]">3>:T#,QT5`3N`)[K.B9G3 +MYUZ%%\P-RX\#GI=`D.0A]$K*-A&LM`\LH1(2.8`K^T3&-K?4SADUD>&)S<Z! +M'?33/,GNZ7<D&U1^78+<-XTCMJ65AH?@B&<@%]`-IW-%6Z[^LN9!"*B.20MJ +M'D\5PCXVVHFUEL\/P-5\RY$#F*KIM>**-S;_LED>R(=KJA8U(4?"ZLY!C4D1 +M8&IZHWR;,OHT?NY>N,P/58JB0`18"O&ZY@$U(72$_M7.WMSP<C@'O&1EVS@* +M%#%X+V*SVESJ]2.F`28/ZX,ZLX2HVN33%.&*UB/>:+VR<4<BI59?#O\L\!`: +M>(L6!\?/T1G'%GDRSFF8:T12DSJMFU001[_",XW5BPK-29>#_1('-R\`1BG? +MF!.7C$==SJUY`*[1S#I\W'1N];HBRJPR5;EJI32E1,[)A!6^)+1^Z%.(2:MR +M"\6X8SKVV)!RI=6Y6:Z1$P[/_[HA^>GI@]%<"1`U%$LI[[#S+H%P+U"+X0GJ +M=Y(:Z>`<9FE?Y^DL`Q(TS?%*_J#+<U7U065\(J2Z&W$]"PO#)D!K()W;0U#Y +MGA>_T%;IIHQ#I.JCLY5)*LZ+A_$EDCD%PM*HC2U5D><!+&3U05W`^6B^(3/U +M7Z&/.^N\#7']W<`KNK@D1@\E+.Z`8%_%,$]XEF;^M`M&U_O(TF/<.4Y#_'+_ +M2IBP"T])%)IS?Y\=>XZ!T!/74?#@L)UQ%TW3KV[43)E6`W&QO^-F6]%4<39@ +M<S6`GZBHSAX<U=$/F'=U[L"RN^XH[$!#H*F1R69G;:7//.NF1O1ZZT(9&8#* +M#"DQ]SH?F85I@;\,"-)H/9;<=>4D"]9GY$0!SN4$\4E1_DECDG"B[9'][\BK +M:*BFQ5Q?.9P)\UZ&_S%(BA@>)?L'+[5@]T^5B`/%:ZJ%$Z2%C5A]*<%K`DTH +M!8CZ]HVZR[B!`=8FKELS"64N#_TD-CR$X>]2F%.Z2)O.*S%#D/.(`P"+.!F, +M)L&>K'U<DRL%-(VYZL/^&([0^/98/#;PU?3<PR8E0%WG(/P5T\72O7:'2!O< +M*4T(3%4!UN*4?IB*5R20ML`1"TH,K0>FTP1%IQ'P5BGK10/NF=?LGM51T*R1 +M)I(/L-';T@/EW6WU[E]M`*'E[+P_`MM749-O-/4>J$,4NMC=2',I!@_XB`EL +M4SPV@4_25`?LQO[8TVD@O\5J(;IBBU3J9I!@>S8Z\86Z%M#G'!OLV:E<]R,A +M&ZBTHTU>0>NXVZ1+N67S+8X`_\,Q14!M?"J`>\KB590J<":](0Z<4*2.S,S5 +M,S]B,%:JS'^YB$6!]`K4CG:CFAC+@9K'CJ'+5H>D7[[/[R(/H]]Q0<=6>C)H +M_)B,R5])>K7C59O/`J$TN7D-S"O&O/<*[L$(.!%KY!V$(?'TT8%)OOJDR_I7 +M5GE&<R.TG5U%9_EBG4$6W8(8]1L0V<+HY_-M_:9$30J>2^4UQ$E6*S:O\*@= +MT@V15"D);=([TEH^U_D=;4^@4#1WHLN3D*>1N!LH+^,&6B+W%F_UTJ?'TX*5 +M'ZC[-]O!CA_>=PRLV9DV:2&(.DG%2=\[8DU;:W6$/N<=,/SF2,+!S&:P9CZ/ +MUNL&D4G=&Q\%9D\/9]K\6QHPF;FKHQ,`J:QEPCXCCPXDH$OMZ,]A-H_9KTQ( +M.TW;OJ1.)%@+R43@,<W]P+SCAV2V0;L,-!S;K7=,:KNHHYAY\534]I>3NMF\ +MQO68DZ&U'4'N!:4?<XK5C,)07V/WZT["V2*>#0V<I5$*T!&YR;3Y&=W@*O0, +MF'9-7>0!;G$$+W$=6&_G/(JIE\II`G$E<$>H)C`Z6T)]5N`IF6^;-I\=C%'6 +ML\VUD&F51.=JR&Y>3SD9D_XDFOE]BQ?\U.?6W\C@?!V-?$*-!7*5%9?R0^[! +M`MCB1.%8@#T'LU,IKQJ.Z?0V#9&4RR9U[M+XX]7Q]THVDE?4Y;U#V4D'FNF` +MWDX;623FI-B%*9(\:,JEH(R?)7C53@N@;%)FU]\R&?&@(ECF&FKO](4SNW3; +MWFZ[FV&M'YBC?)Q(V:B-TTCX2)\<.)G\^R"(PW`$4Z5+;&BX3^OZ?3&/-+#M +M)38%:G?'RJ2(^!\4D[BV@[9<=%'8HSHS#)6U@XVYD'=KT`=(/MV)E0K6"7-K +MHD5?$LPAB]R@CA_82;)$I&3--B/R7=8JBBE;/69YM^"#/<<I[(XXD_\U@Y6M +MS-!BXG^94Z)F'`\D,,"`<(/=8`%0-OS,YX1U2_,%H2#3%L#]-0%CC..VD1!9 +M95NT;CJW`Q3Y$4^%M`+501+XD'J9">_NT@U[.WA8]W8!_0+G6_A=\PPIK=^: +M$LHV,9EP>:?0\C*XGG72*,G4$>HI2Q!O/YC\.?[Q5MMTFFLL..)].XR."%C) +M=@&0@S.\H8=SPH3Y+7%L0>QFQ^$N]CCP1H2<^&-Y6^ST[)Y]86HF"8^`8O?@ +M&W%2&W!U6Z9%1#BXM>+N]SKN>'%MNO22^DQT08]'%>_>(=+75B_,.06S$7>9 +MA_W2TR[C;<("X(6;W0%U%;&-'9#^__NB-,7#,!P\1%<+89E'VVH@).@[](EU +MI3YKB^&?O&\AGWT<)+\$QUS.\4%XG2"2?4.#VT.`WU@QI2"EK%=,4YV>V9M3 +M[NC0@`ST;G*=</^1V"M:70!80;)F>N#*,-G$"A0D8[3/[_<0ASW@L!#KVI%Z +M1@9Y"80S""X^P]LI*\R>P&IU@1%;ZNE1O\W\J^S1BDE[I(V=>LA0_[4]&QT6 +MQBRP$"&J8!3+Z8R\N>\B8'-G;F]FS#(6%,)O<]!H+AM85T;_$2K<0L]Z'<9S +M,W;.!6RSIG?<0CN5Z.:=@V[([CBO":6?1D;$UO6M[@-WGM_%FEPZOPAY]'D9 +M]L"/BZ&["I1AC5M2]'-;#,#>D?EE$(V&PJT9)B+Y*X+-$2W9E`E;I=`)K]H8 +M.L\F'X;V"D!V=SN33M\8$J@&3"*=8["(!;CF#O.<_'&C\]&(#IB<@S?Y=!W' +M)>W\\#@>@O76@#1'\`V',VV<!%\W/`-IV`/Y<B&X],7GLMF[23@N5\!$;VDT +M%AO,C]&52&@)I^MB+,'+Q.F,6N\E<:`5\VM%)\),7&4P$9X_+@-W?:>6.4]) +MXY/3GK[F4_70%)Z9#PT`PM!@ZKC^HE]W$(GB%_.ZW#LH)I:AR85_-UT:*T1V +M@PV3IE+C!]'5<E(9"8=Q%']-#/>]ZY`-6YX:>_?ZZU"8:(3\`)8\AJ'?(.=K +M0_D;'QA"<\@_W5E"YSVH`:^AW)Q'JDB+PY@.%R7_E%L`[KUA^O4'EKL32OM@ +M33:P'4L>;GH@'AXNU[A+.%E*,GE7[+="ZGOM2=$@3@+5(53G%2DBVLVO2D*0 +MZ-.,>%S?5X=RLM%LB#QB?GZ'AA]2S5>J2Z*E&W0HZLL?=CX/H9\C7O#O2I>W +M*EAD+I$?8V9%9>.%Z0.%3<)?CF<&I(%90F)<2<%GYU`?@ZYA*0*7'5DHPSTZ +MS:7#I#3KBELR\25R^XA\6R1$$@Y6Y-@:0ZB7&;A*,FS7A/V+8&DOV5_OG:B* +M,-!#%ZG"]V\ET@*ILFX9D]`KP7\'.ZGL"T?G:^UBZ'^MF%^70VPSW+K%`GF5 +MM4"':&U"%4!W$"/O8_SJC_AVO2:GDF2W^Y>707F]3V\O4YPI-&!J8,)_UNL` +MDQE2L(<S'W55M6AF9>JU0?&2KGSS5H8B;-K<^FIY2Z4T>UR4LLA0:UT^=!PF +MU8S[E!AT1S^CNB:\@5WN;0GL(]VM6!R2^"Q$HJB[;01));XFM8V@XW'[Z;57 +MO7@ZZRB6^9!$9`73Y-:'OTDE_J1#9;=F6/1R5A.YXXOLRE_A%6-]-OY-_F@R +M(^&93JEMYHI?-W#DA9`YS)-75VGZ4*^K>_*XO>R:V"4,4S`TJILO\EL38!;F +M/AX5@:N9?\SVT/8=6"!9&`[9M;;*SU;FX.;0AG[C@;CD>1G251/WK4"=)8?S +MN'%8"D+*S""$_XSG5J?#T.1O7QE>$^+2HB.=+%!YXSMIX9M6@P%(HHOY.A;3 +MDXV28LG(=;69"7@HX+27.NOP/)$<+?O975R']/QAR\=V9XLX\H1D"#K&]0!> +M77,C$QKKY\\]]J1`$SX%VPMW%^1(SVP;<AUU$^?4\8D!DK\[#+!,WVWLKV]7 +M$89P'18;Z$Z.%Z>@,6,1E?7:%"2,+$U)&@P$.*G9#:!-I5>X(;8DN9^^W,F1 +MP[90.1XN2DTCF9$H$A*-,5S>Q;$7GV(3J^&9%RFLRUY[W@TL9-[KX<?3N(`L +M;E;P6*ZN"839%R^#!R)[@LK<ODC=*UE:K^%-@M-OK:(.`#1&P-'E`^:I_U\U +M0?"=F.K=W%?53PLEAD1+Y_I9O$=]]*8U3<N+KO<9!&4AW9`BA;VO[8:7-V`, +M9"7U#EBM&RDA?!J/"',G.P^E[LOZ/O^3S+;$=AF--.XFW9!MY3N@S^PS_T1W +M&7_:X]D[0,)*`=6FMWC?K\4+ANC)(^X<%I$<@RI<7CN*`J<!55@$Y'E-M77, +M*^5FG@OF!)M&BK=U5!XDBTJX:C9"#K]Q(#9-I,`I3IE@;%0AZ\ETA02<PI43 +ME.F,YLS7JP.P#L27/I4)PUEKHBD[L2-@_`)SB5Q1`&OWT1):7)RPV<;U+W0R +M`6V"HT1E>YY1:JN$]NQ[`,]759>.?;D2PJ>5]+2C=/EN%?(%N7^68ZS'_'1P +MRZ:>[)^T`.B;=(D'Y]?IP'\^N[T#]PL2]6HML?'".A#WH"+@<QX%S#3<08T[ +MA6P$19#!'R>;I3D0\A#HP?-7Q?+YQ\#:A2[0JQ@N:)*4&*;4?.RS0G@Y25!< +M*0V>1^4QL/D01L<4DW=VN%<L'..V(98CI;!47X26LEB;6X`BBWRWP77<N!>( +M#$/4GIBR0T5OOH*GE6"M-*3FD[JJ-Q^84V;2;W.GQAN11[7%7[H>+$G&MED` +MXG15'S1/*_IN#40E!XEK#%`7>J\1Z^TQG*1AS.5;F*V''NX0.6^D*]A8'=OZ +M3T<I9VT.W]SA7L6R>K:SN?'^@%4C"?TQ;,]H5,,Y0'4(#2=U"P](EVYQIM:N +MS!SU[.NR>=(=9(0'\=N-X%(/VB+#RVW]U3M,RE=C\M1O\KM')[=R((YY/PY] +MK^NH7UR/[">2#(._P/7-X`%YB4KB4;=_>TGNU";K,<BA+<5YUTXG@U1THNE3 +MG0`>#VNC_-MCQKZ!!$WJ]6(:+O?1CD@.T`\CQ#^^"@3SD19Z>X#I*E]YN4&_ +MRMY@J$:B$.IT>R)CZ=>ZLM&_&VGG4"LF3C"HK-22V>3[_@N)KL[-+^8-RPG' +M5)_-!RCHYW1/85C!@>]']52T'U%J`IUY@5"G%1NA$],[P-IZ0J1NUZ'7QJ%M +M&Q=07G!O)._LX+&>F2<+ET8=5N<AJ3(QAV:N1RV0$.]`)0$/HM7Z/YBPLZ=A +M9<2$HISNV/R),$7Y&4@BT"U/'!+B[:1!@G@(4UU[BC[&E936M^MMP[D86J`W +MX_0+`PAA1T[P!RIQX;UIT#A+$4O37N\F$]*#Z$8,[I8MMWG*X*"_PFOF?&X? +M.D2F_(4P^(79AF2)4K4>DQ^*P-WEDH/.J"\X=:H\U(:OGR9>,PJO^\%H'!CA +M*(;3`L>/82=?C0R&=8.TXMYDN$LIDR!N%=^H+!RK(8,/(:D"T0[)\(14&I*J +MWK+&@'_!U+NC?'S;UON9\&%M]:):T\G-^E1EC7XC'=9IM8GR_6@KUV'.MWEJ +M%^-5-3\,BN1^ZC<8PXG=V8_<3N[U\1M7<7L()-PR8Z2.8:CM\ZQ-O,((HZN* +MS*:&Z2-/E*<F;]C!Y(U-+FTEZ-/^`M=8$[A'`SPE@<`ZRO_\I90<25?>5;C# +MP.#7VZ)XOTQ+/];"854.X=@Z@Y$G#",/(R\5]4O@-<]\:7,V$?X>42QE2:R- +M:)+5[9M)D*2IE4RWU_0;![DF/IO1]V9%ZX*NM[UKS6-N&2T&=O`/VFLFVX). +M.!?:_C7Z'#MYL$L]'J&<C(=%[Q]Y4M1Q:#!4(HGM,]\$479LYF[PG.5#%6OQ +M@)&V5Q9]XI//(9`TARW*50>5E;B*O,&=S1+9:D>B+I'D-&3;+8/1OPDQ!HNK +M><M:+7:XOLF%K=FP`.\912%C4Y?3%JH@Z!:?>+OXZ3F_QH.V(:@86,U2-9QZ +MH"VO=&L*Q-6<CG:S.'PNGJ(N0P#2$<%\-^_X7T/*06J?A;EQSX:8.YNH[G11 +M`:.\%+YJC7F2MR?^4K$/CI2LQ#+]]=]_R?EQ/YN6WXR+$-,S"!U]4^XLLPZJ +M9XPVU;+]%VAPL,)6?5M1I;2AKC&"'-5N,LKG56G#)ZP,D^R'0%YY&,K2U]TY +MRUHP&DD/-2\S7)%(^#6J/;5/`G+$.MW6%?0=%+>2$]M:DY0QAU71:R?L:G_! +MGDS'DFPW"7&^FX@$6D3GO3FS!B`*MRV(L$^A#IS1&7-=Z.+DY4Y'!,5C.78R +MBORS./4RT=H*`+85-#GT3V'72&04.(DEI_+6YIQ>'*R57"T2C?DS=PZ$*-@T +M_!)4[Q#Y7;2$QULP.:/XA4<D"#OS33.9A$)00(N4DZ+Z-S9?ZW+@?U.7%\5_ +M(@Z"$ACGPZM:HB72,L5%$'#+?`T7?='KK'9-[[\C,7_^[FEQ?9<0\ZK<LZ)3 +M)3I"J\^9?>>GG]TJ-L^&7VJS?V[<E]\JYL4Z[S@5?E&4>.>M2QAM%7D^^SY_ +M7LVU4VDU'@PD,)'HT\QV&C)]\Y*T1K.1:C2X?)Y50AQ^^=^<TB\_+N%YD_(V +M_>W2V7.U\Q=Y6F[_6(5[WV/7\-V^/1'=;1GZD`"VT0#2'WO><VV^<GL;I2F* +MOMJ'??B'WT-2TGW0Q?3NU;6#V&!Q;MH)4*_)J59A/J__W`Q@<71G?!5@:>/$ +M-#Y/IS)W;I?5$<EQ&7UWON(TOZ%'ONNH+6FS?7^VY:4I"9+<?OK4'ZPDGJ4D +MD(/-IWZFI*0P+1:Q!K66H\=-O>?O08;(Y=1#E['7Y(7Q'WL2/"X:R\'C`ND[ +M]R=AV0[!<.:P5X#LFGI3D&7"5D7R<)_QD!@IQ.#"@=&9N:;X%&'/R6!I]S9; +MHGM!%<6Q2O685D"%A/TE6-0+`J*N6I"&)99*P`FXB\"KH*3#/C9=MR.*<@@$ +M.D`0!E0/;M(B-`Z"BNA/I;=@G$7,O;+F.?MIN9Z&2XK5JTC*6LCPR(86;N?N +M+,6O5X$*3J3$_(K4L=C,(DU%UUF_H0/T\D,E0F/!TJ+,-S"A#;)<6C,AOE_1 +M\D+U?=/LN;*_XM]6/N(!\=AT..]@D_JWWT':L@+,@GG>7&-BADI$:XP9:$-/ +MH7N]7^.`$_`V6BY+8_#X<3>#GL#4_I[K4F9<"IG0]*T'/D(*=7J1"A0V!+\Y +MJ$*013'P_$D/55TR)ETH`TD<.<&+XK7E]^_1D.MU8>E!Q);P.G^$8M0^880A +MOBU^_7&O,>/P%2=>TA7Z$]$DM%JYKM+KL@7YG&F-?O/NE-;DM*IYCL@<[\5, +ML=V+"BCX0E:.@-LV,KL;!]GMK#;X:DKOH7_)00M"'H>JR9+/O&"3<O'K/4)T +M$J/RGK;]5+P9TR,G7$D%#%9>"_DO>M`[B?-_`I_.0IZY'#)/<>CN9N>"'!X# +MG5-+28G"'G%AH9\\M[7,?C[>Y0=XT^VHJ5OSQG&-R0OK7#83P:'BD01V0^2A +M&)^.W11>NU.;^>C;90G\'R).4^S2.EM(\.]84[OM<QA7.&OW?3(Z`'%D0+FK +M/([TYK6'TE;XF`==Z1B`EAJF9NA_E5DXA'0*19&2>@"P/+BI/.UST/;-YHZT +MFHM0A]2'K([6#V6OF/!C';:Z8OBR.9,7`3VYM&`A\3_VL$_<>PCYU5($!BXF +MJ-]=6P>>R_2K#/9FE8#\("8U+,!?8U/_&G*+3=.TI!O^L27>O46+;[7(&39& +M;R([::$!Q_I]UJEPX6_>Y1O"8EB1`=3[<&"<I_0M>6=KW,Z]2#&T(:^G0F6$ +MU!XY^9P2-O)XD!GXV#_F05J=B?O]B"T!$4F!3^KSXU;$+V(W-%<R%BWEPK8N +M3/^?C:B*\(72-<&E9[$J"6#"V];TM>:S(B,$S[*'V\19NO%8):@D4^FB--6/ +M+?0MJP=U",K:/,3[79&JJ5AOK;E/@"IW_&;V.Q+[=4;!V7X9>4(W<A,F"W4B +M4CR.E=R\'0%!H&*_>Y%;$-;,YDTJ#B64C,"7J6LU-Q1E/DE.CFG2+@6.^P_$ +MF01[;2H[G.[SE]W1@OV$R8:JP^1B0^3O<7G*9J-*.&?UIX4@U4IFHJ($L8%> +MY(!'$L.G)[_@1\Q:E1'R.CS7[/0AW\>6-@R_JTY2)]-B!"YT!,L=R5^+<^^Y +MW=?S-+Z#^"/6S`^:>?#29X:H]S8&QCCE9D<5:&40Z#RCU$#-@LO_1`\IYC$H +M3V>-^8DM2*_6C3.TXUH!F3D>1"M2-KE4M&>)PQM$@8BYD%GA6`#8>>Y65\)W +MG2!(N/:1XU.0P<)Y@,4:"^M``2>+Z2_(PTXW*1;=2]E=A^$^'MBQXC*%+1#O +M=MJ6SC@!HK4P`!4A8D)\BQ7XK'%JZ,V2_(1%[%8E(.ME11&(<H`0A,WW([LR +M>JALZY;6&G*]IV,V^<PP66MFN,F$XKY0NZC9O"V$6K`R2N$6JR%-J*#3$X"6 +M((]\'H@S?#^[.`F9:,9<#8:NPB%+L%;`]CO1;'7P#_QZN$5(^T=6,*_-M+L/ +M-^E?Q-F90J+)"2/SV90,ED?,RL:V_/X![8E0A)#&_A43<^7:E:VK\+`6!OY6 +M9UHR;P''=24Q!EQ/\!IE99<#(+63!K&!7D-EG@1QQW=`WA"KHN$25R$%F`KJ +MC(SP6)FQ:FPP<#B%_<NFBJ8+(_98I@8X$UA`8MT8B7>M,9>0Y/'#'S.`YUYB +M)!W?^<NBO3:A*/IOJ*BSJ[L(B97)[V2YX7:O;;*="FZ-1(QLR:C7]#J!5F\) +M2)*)S.'`7QBFKYA];=-1!+U9K82K"PSI-G'7D6U;T%SJ>B>MCQG`8ZQ2_53+ +M17:L*226!IIU7&'RTR0VOZKAM6@+<!);6,^?W83\3$:_>X2J!JJ**3DYRISL +MU)<P"ZN(_QZN5\;0Q+R?A?!-81GDA\#(A@<F13PM&7MT8[)*)/;*]#&U>%`. +M0*B1D[027B1,""NFB>NR^HKPQ-Q*,JUZ3B'?[&XE2A2BT5]!!L(I@*2SOKB) +M,].)V5`DCZ9OE4P2:#`%%+7@M5E'3#*=)A?3;=7LR9`&S;%1#`Y,\YJZWQ2Z +ME0B'QE$;BZ\/.EO-&VVN0(',DG/;6:U#\4U(]DT\=81*%2:,/#,^V^D0D-.+ +M-#&O/$WHH0ZOES$8/Z;P#+3\1R&+V#%Y.<\];!;U<8P+,13>94@*;&D[Y`%U +M:4<_&WL7>B^:D3R*E^M<(HIWVX=`7)@/`@4O56%F0NU36E32/!]ND6<LRJ9I +MDY"9,I/$LWQ7VJ860_QO///&-!K@F*DG]DU76B^34,<_<UOI\R.DFL0AGD`E +MQ_,K&*>_$Q8W`-MQ-BG0`?@[W1F2(4`_=6?FH5A3Q[)A#T2`/#E^@>$MUHK, +M2J[7:"6:U-S\M..QVLJ=*I92B`+G#OC61<9Y`D];@Z0^O21Q@DA3$ACAI`YO +M"$GA<;\!V+*MX)=U2^U`3`3YB_VE;2=\HA_)6T_<>"67=/$]"`EO:+SRECHL +MJW)[(GWLK1*C]7+3B4UH15N.R_[:\Q^>.6D,ER"A[K^<FDG2)?SY7M8ZS49' +M"8_7#N/X#J'3,HUS8\#(;[OIM'0,#J`]D'6/=SUSO1YI`"Y4=G;N]TJ\]D1Y +M.='E@B-_W9?-XRFN(Q\<D(<H'N[]>Y?0_N_,CG0"_RQ-9)MA9O/+W4`8_8_C +MW/.<R!1JG8&GB(,QX_1(+J/2XFS6@<NU!3'>I+>>S`B1UIQ*3,`B(K=H&**B +M]:.I[!VJ77N2N7P!ZJ,3FU^C".M0'L57R4OK;3A/Z_`\ASF#N>L!DYX0BE<B +M(/**_*6N>:;?V#D/82)!MVEUP[-TAHY%OW\*1`E0[MO5/<AWTD$?FDI=<-&= +M6'T@@L?NH`F[#B6V0V(U+$;1FH7&LN-X24^72\IMHGIH'1T`Z.J(P9>3@6B2 +M&BH'F;)/%RY'GOV*>[)K=]O)QXIRHM6`#0/Q5'3HW/=>M9L+)S[\"5RTW(#* +MD53,H[C:J4`&F@N%DY>NF&C&U!M'Z*A&0W7$FS(V/@.W8[U6+EVQK;LXLPOT +MN>:-MWV82J`BN?[2$K(<;@AYWZYQ1<JZIEH$A-8'LH@,N!3$)H,@1`C7,<^+ +M549NL2]-XT\^3Z_4(X?=LS>UZIHM96D$\'Z1643EXL*@$MV[,-F-*!B*H9,Y +M7FF**+-1:Z\PB^DBPH)?BNRX'AJG?@Q-"_D_^8@.NVW4;%0;Z-S6@Y*;]\3W +M"9/(`%F'I+H\24(:_[0G4M8/.V;9:Z`#S2*?;776DS/JSDKDN`K?1`.4K"/W +M8H.ED6-KG=$@<)9(,4]>/!<E[:,;S]2U36?0"@PEJE.7R+*#;\:I('$^*-&K +M&8@$CQL?YLO4A[^P;O[WW"9ZA;1$SVT7E09"OW_^KJ(@!28:L.B)^QR8;.UB +M*YH8;8('$RED@-<HK7`]]6ME76@?D,+M/R.N)(G<XW'SE>W[1629U[U)<"B% +M@*[QJW4BAF,L9!K$67I@R'^8Z",((:+$60]=C-W?0@ZB?M1:D1-%07TZ2WRF +MAOU2:B[S,4-Y8XK;Q29(0\8'ZRR0DWJADHN`.Z+=$J'P`XI/)_I.EL*E@O`, +MV^D>M&R/P0175T3(7>9![6Q@,7*)HZ.;;X#54L)6-K3YD!RVS=.H7+U[>4;5 +M&]8N\!B[3A:54)T@A)?;5PO&I-.+U)IW=B^.6XVZ$(CHW>;L.F6.>9*+A8AJ +MQ%)2%^5)VYLKE7N=U0<$W4@$Q%;4TB9V"][L/-@`/J=[38W0DV^U]L?'C!:` +MCTQTS[+!(2\:+(6*F[RYL7OZHZK:>W6`ML]#_P0K^T30G^<I&;22:.PNWQ+M +M8F,`K+Y$/G@L4+,3GL_A]HQ3I=999_=![HF31KL2?=*I_%9W+XK4P[`4X3+Y +MDO1N8:#N"\%;I,WCT!,R'3+PZ5NPCF]0_$XCOO?_3?WP<FYC@&M^7MY'L[+8 +M.BNMOPYU78.ZB\;'YSE.D[P?I<,-?R&F[W[B:V%5\;"V]B-J!/YQ*FB]1<P^ +M`A\6Y'GTXXTEI)7AHAP*H(_)*!.CU,44]!Z]5OZ?Z_EVP/!\PI,N[:?>(B,= +M*?<_BNDDI<$5BWGHYLA\C?U*\".[-TN$.8[(GF^@C87^G@)':&*?"&@SR&6T +M$M+]LTT:%<])W*3'FY\47K@03B;S!ZD2I)LE/RTG-C"4MBI4P$A8ZER;)UE+ +M5B-Z%9Z28A(4JJ5LTMF:IJQP)AW2$\]@BEE."#:<SVZA#_.GY4U<PJ-GH\R* +M4,`!AE1X=S4S"9<DB0!F!H35^CR@4G/^]?XN!9W1J9I3K':"MG5,#9O\]G+0 +MT%&&OV\BW5["6;'D27IM_=2H0CP>P$_+["F(27\)+-"5P@3A)5[R<9;=1*X7 +MLEN8TH5Q(9`/]=7_F/96:"=M=HW:0M$T_83O'@+`@CS\'>%$&?HK"3.MVC-6 +M:4[Y;NK@GBNZN]SLW(G\)C+UJ]E,LQ!<K^-Y.YG*'X9L<KKM-4"#RCLC[&'J +M2L:38F6=]CE*:%"$\TAL.`C0_/RY/C5@!A*7*=(IN8$V,*$HAD0C_B<I[U7: +M&']2%2DEDVL44B=;*DX]SA^AH?Z4];BTGT.%17RR.40[OP0/.26(?B\1P:!S +M<$GI[]H;=#V*1W',`+WIZYW0`!8DF%%<HDA3=/$+5J:FK.Q979TF7$CEU\,Y +MH_"N6:C=3/G8'446%J]9E!`9".*>#LPY/YHLM,UK5\[1RD<^9\C\=Z$?O:0X +MHLA-NC3.^$B+X<T,OJE@;FQ-+K_T*F:CN3;A52H0!23A8V6\H+/X4K<4BD8O +ME/;@?/0@1-Z,NB?B1'FR#(`[P+^0N(5OCE4R9?SCF;Y`:X=W^)"]TYR\V<B- +M%CHX&N;+3QO_X8LL:)S-L==>NODSNL3?CMM[,&;JOR/V3)/4:O^17JH8]__Q +ML'%$[,5PW*Z5=KX7@:8I>_"JUF]%KH?+H#HN254G?A=B+-W=PO%QI*#>_WPL +M\@,55Y%O](^9P56^*V[M"8@GW3LEX8A6-1)OLS5/J8@+15'HT#.&-3J$;V39 +ME^$1(A6>[]@WXU12GY)N07^N!_O$(RT97=N.QN<"TOU%L``.$ZOUAK2M6?F_ +M+UO*&SS?OUC0V-6+6?Y]R[%YBHF]\1G3TM]*=HKW$EEV97NO*_(7C&M68<]5 +M31HZ9RT$L:2&?N34G"JA+2QNSYD(LY-?6'K_=%`>R_GE<G>\2%KA*V$M",S3 +MX5W!#:P0QBK1X.^NN3#76#S]`1<,E,(1W'C$.9;]_M;>52S<-/JMRQS3?*A= +M'DA02P,$,P`!`&,`C+`.10````#P"@``HAH```8`"P!214%$344!F0<``@!! +M10-?`#28^</_GZ@E(H:A,X7\G%A3]0#MK#KJ#)\J.)^/5N`1VR%-8!%`,N+5 +MN%[?E7HG#P,QM6?1J]RGU.HJYWQZC8U&L5\Q,63$HMXJK$;!>HI%'0`#5=<H +M$P:TCEY@].6)R%BJN_RG1<ZE&(/8):`6LQ4\=70Y0+@^GVW(QFO'HR,5L#Y6 +MP(P0..A.D:57%CY=&=P!G?"JX3_!YW(-Z"ENP1K`OUCU+#7D8VPB_]]G:L5: +MHVM.N*\L*WI]B:W^65?B1CIQ/'G8B*9LA$UY<(50+'(75:9)C'5T<%<).X:P +MTDQ,*5"\=!]Z'?Z[A*&=V)8X:\^*AZNUNO&SO;+N001R\&*+SLDG9\RD(W]\ +MBN=AUO5Q85;5A_213?SOV\W)C)_@7<16J+.K,6)=XW@Q#OF&X01)_LCSM+1A +M8D\8&E".URF-""16P-QOH&_X!>9G6#6"0,3X@]5T*/V4,LB;4>::\@#`J-R+ +MU7J"$$GH'*_\6*/*JS%\RD*^0`09`Y>%7T39<AFF4KV#9P@K9@D'Q#5WVRH@ +MA:U<D7OB>&]JDIFXA%<Q4Y5R<GB%OWOF&AV&?&FTJ";08EXNY:U'B[?3IVB= +MDS#-<8C!6GU88$&]'O/C%)F"0U).:;OU#[O]D6@(-G2%@<@0:YFC`#DN8+)_ +M6&Q]66QD_UE:()G7A*#SDS_ZOW!:Q>/Q-H9V.Y#["DX2`>%S?CNA+_%QWXEX +M.7_?L,3F(^K#])#!IL3Y=AJM;2F.!^+]`5N^:8BE`$S\9HA2"1-*TH#0N?&J +MVDH]!Z?NC1`FNHGW[\X?>:8G;5I1-"JVVO+?-!/_][K/(L6-XRYG`DDQS741 +MHD^G&T0;.9/3N*CE#V.'=LZQ7,!E=->E+_I6LIA]$E*3?M>-T=Y_NF4'D0:\ +M,9ZAO]J>'<\@%]RM"!%<29/YQ_,6%7E=7L<./!FU[[BE0BKH7VYG7TPUN6Q2 +M?'^CX`X+A'G4IE*.Z?2:I-O)6;Y,#WV6*#+Q^UU-1_A-WV7?6_&>9@#@1UU1 +M'(X5%?4_QO"KB`6.]8'6ZMZN.Y%(/27(L:&Z@@1?7&DNO5DT92EP;24/_%+? +M#=@1O4_1Y,X>1J>_P<4Z<IS].7-/._S?-X8:#&(<F)]]/;^F',S83Q-/A\;; +M>,V3/E:@T7PM%HQ>-/M%@(OEB^;U1V;/\A=N)VR):BN6$0/D`<G`%W4\^&Y^ +M4V$!\D!7P/,C_;3]D#2#M[`_8DVW7E8Q,"^LBP3-+'N/V<0V5BMQ'W9U<(;V +MM(\N=?;%S_*7\DF^1;)Q?-FE8F^NA*`3D?ZGJHB&52_]<J4Z`7>U$N59Y5$] +M'=!GJ2@OC;Z3\88IS7IG5&$2-0`Y$R.>1\N!]&#>H_9,ZE]83WG\GC#\%J:Q +MHG;$4\%K,NK"WP>!1^]]HN!Q\!JF<LZYU10B6FLK.2[L?4^B>!9L7WW)?:5& +M7CW<%/TT)&:3ROA!=#`6Z%X%C8CM8J-4W[?P[Q'K=-=/7T"Y3@F[#!L`EP1I +M\BN.0)&>P"J4J-6)F=$L^:L9/1T9-2SF'SU:E9@%$B!%P)#>2?M_8D^!9AZ4 +M,Q]/)/(U@@+KMWARBHZY7+\4)0\?=TRF0X=3.#*K<FVZ,1.CVN,L07T3WFXU +M58!!5@+I->103_&X7O)]4GSIKQ&T5C:+__!5Q[N+B$C._J4P'4$NJ^;R<`+G +M6>H,/6P^.ZX3DF-DBZJB"M414&<0:/3#4;TD(.?1XY_%6T.[.S+OX8\1QV?" +M)GH/'#C?R'+-:K\M;O00D?WA1MJK<QE[ET:&=/CW:,RJZ0GN0G]4YU&]1.%. +M<G"R!1]IPV]$%;2%65!IY+/?J3*C;J]/4.HPRI6:30.JL(QI/4)'$J;.":%! +M!BI<,_9:5>6,DC4!;^%M`+-#V]?"\QM$,Q19CJL^K!OLMZT%<I@A,BZ\T.V^ +M1#%FI`M7B^7]W3C`"%;(5*A,:"]$HPK"TQ@A`I4:-T>69.X/^)`".NYM")U5 +MG_;<KJGEB@ZZ9Y)!,RKJ^+[?D>/!O<>*P;[^5GF&3-N@P"5"`T5%9Z&4B"&U +M)-T'F.6L,B\-U>;J*TNC?,((EOOEQN3<]>$K^4%%;,S.3A#KF*[@(UX$4*\E +M\Y"F2F2T(7%L0G#.>4CO%$J_/L"5_H29?Z&V"W](S([!U]::1L3Z:[-`/Z=+ +MR&.VE$%X`#X@T`82<-E(<;U#T%;<_G`XL@B?$F+]"J<C)N\^Y)8T3$Z@/U'' +M\B71!XJ2\6P&_^KS9`1<S`*<>HSO&YL@G-L!?]WJ`"[+^$Y^6=]&BPO&HE]? +M0F8N*H0JCM74G]<YJEG)7BU)F&7MD>L3?FM+X#Z@>$M10"'J<?-Y(O)VHIIS +M2U,34472>M_2!P1:C:]N;V!+%NT1:M^)J-W;U'J64CJ"RQ7&;H0GW!:OLU`7 +M[.9B@K17NIW+3!3&)N\)VO<N0&)X9]\@J8"(#DD?;:$^L<95Q6#A/>P&R0A@ +M57LF'U&[/*KR(%S5>0<N5!^JWZ?9+/GMI(+/KR=R%%%IPF5A^[OX+D03B3+D +M"OS*%=-Z(Z/;M)`!(BNHU)D8#L?!>2-S$VP_O9D\(GI6H\LO_C)\4GI]YC#) +M3E)%V:,#SXLVG=-?&"E.Y#`NGDO/UA(?X6H(Q;YQ8/9\%O[4I5'EI26$'R(< +MT0R1*F0CDQ@9ASM8;QM\2D=IP\^H&[[8QS.(X;A&_5`?.TXFF_'+(=NWP6!3 +M_M\??DM8[,LOJ@8\DJYS'K=%?='W'P'3"8H%<TS']A%R%O35T+6B.0.TP\'Q +MO_>LXBD6V`/S2"$<_H,4RR@LX:XOX?;MO-@S`"Z6I150=]IN=^B2$2`<6M;F +MS>WB]5CL_6)R,WD<R^7%+.DS2.R[8UX2+^AZBS-Q<,3"7+@\)!6G4?UAX,K6 +M?IH)[0;GOFWKPD')LUDU[0PLP+VC[CZ[B,AYP<TE#F$SE<6]-!SIZ7(B$##M +M82I$M@/`9NPKL3QP7FB#5@G]1B7T\&TB)E(A.F`9OV?U?KDC(Z4J*/+"8O=? +MDQ%(_R?=NL\2*3@W)Y6`J?$]_(C"PJWW[V"Y*Y`E04)?E'U9(X`3A8-[GK:H +M5O6\0G*>@^X\\87WJAX'[A>PMX"ZD;9:C^Q(5-*7BLB.5)]Q]%MM+:JNTQ7< +M+3^]83`-P%]Z.V7_TIO-(_^$:5J(IK>7)=,87/]-YS4CZN-QUD9'3.-KG:6\ +M,Z*O<R]FGHWNY$1>))Z#C:K2;@Q,WB)`KU,?97S-^8ZC6[`D2Y8BJ\DD^U9* +M6VQG4Q=S6B>(9%=$T[:OG*U<TZH&0Q?^L?*G73D(.7Z/Q#?1"A%2+0W[LHE8 +M=Q[K;XIXJ@(P!]!"O#$Q+@LJ2<1E+*4XIW`Y^,"@?&)F3:3A%5-QI02C"JJO +MRD3.RF!F4;BA2=6-XF(LT'SW/U#F5XE,O]+`U0E<77\T4Z%RC^="<AQR@ZZ_ +M+2\87E`I.G%<5=`!ATMF*\;.N+9-Q2+\!CU?`.1B?\H>U'^`/W@GE0\/G/_& +MQK(G^=N6:NIT)\!F#+A02TY*I#4*@9[W4MQD5^U,[]9=?XJKK2@*/PZLM:&J +MV$<CY<NU):5Z+9I#P8.6+___()!R+]2>9V@]UUHZ.:':A_K:I]8=E"4*Q3Z, +M_V'G#!3NB'JK1.0X*(98=*?LH')M+,&Z[HW_/HJDST8HF'TK3$-_T:=$-2!= +MZP$N24U$5\:&JINR_^,QX4*._^>E)R`'%COT:NORL7A=4+L7>)M.4@I"4;8O +MW$M(I)X2;H^0$4F?[CE02P,$,P`!`&,`IXL.10````#($P``FW\```@`"P!C +M;VYF:6<N:`&9!P`"`$%%`U\`*1A$9UH6Z;,YMN:K,R29HE:!&BX)G&^$95?T +MU=B+5;B#I#J'MV`(A)/<ULF\^.^OYPL*78U]Z9ZJ\EK3C])$XL\=TDZ<=*); +M8)1.WNZ`+;CNN7UF1'8O='F#JGM=,F*L'$#F.]AZ#,:%3[<?8@&(XK_3HBWZ +MOQYJP3L%K&]T<2@H3M%CQMC!`@$WS,7FN!3X_TBU#-G!(UZ1Z0DQA\&K+;^4 +MR`DOHE2MCZZ7V`B1X88YW&7P`9I=](QD97;T,`(DHK8*`[^Q)Q^1BCB(7B27 +M["3WD*-\X/!99=%!9L%\5I.U]>&9K-#`?1A;!(O=BR:MH4HP(A3+W`U`V:J7 +M4+U8&T`EX]!=<>[A.QG!FKSBD69;D)=JRW6R@-:_CO3(OE*Y;BF7!!A?B`N_ +MXX;MA?%;%==EXOD.4W($'&':$F5M-"^D@I?Z]7M)MTN$##;LJ"H%H\4/9=T5 +M6HM<,!7[`.IQ&F.EJQES`>_FE+:D<^IY)^7^WL=M-O2KZL@Q_DEN?X\D]]E= +M43HT%*]"$/P\+!5=3,A26WWUVG6WC:',>$'\/5R,(_BZ(8GYGEXZVN^6UN,/ +MG=;.]*UYR#O?![Z(_X\2HX):6Z7@0;>LE$U=H;=2LT-+6*<JW9WU\/]:\5R< +M#P2#1<-[0HAXL,G5G-XM,/'41,5GL4858TE^R\/?/9:DE)*>]&^L%CEUNRV1 +M&I,W3)V/DL*6HD;/2WQD#&I\BI(/HE9MR&!*;=O!F>S&OIO(-H?V960(_^[L +M1H#'R6B4`LLH@6/A%"%]RTFKPS2%J)+(1$\6+7?4_-A9&G-%4Q%_'$F]T6`` +M*('P9SEF'IA43@UZK")#5U)$H0E/E`[?9)39]#\L94TYL-J@2:Q&0;#EXQ*4 +M8S$F;.C.&;Y:7@C7^7&\,AX$%*UUC#GZR6$0Y+]=ZOFWH_8X26M4ED,Q4?Q< +MH_OR=F[0T_*CFIA?.-R`S*A"ETNK)10(`;3Z"9B&&.`4<!.P>3TI_ZG7E;7\ +M=9S:`?.$(D6\9HEAQBE=V>T/\@9],@+GG'&W;Y/<7<,^-"F>`@=UFT:2V>KC +MO+-[FA'W8Q4]"HAD_CL_0[EN#;H=^"%#EPI0)VLOW-`><Z?7>Q:;(YN?JVX- +M"XD!41@JV,I40%*F:#1H*KB[&5PJH$U=^-UD8G1V<9W72#`7U89(#:("%1_< +MB55:!DUCY2;%X0JYIOX'N:^#F)4%29D%V7/=<QR50\\=41'5F%*^<^18?"L% +MY!E7UZ><4@M=6,?,3U;@-D!:!4P!*I^=>/&VO@@8<ML?@<6[1`H.+UFA3)2] +M1930B-X3S&[5M;%K89F85IS!8-*S69E=2(_T2350JXA<6.(#F)\BE`6_5KE2 +M2$@#(,$<LC0,7*`+>SK4007@8$*10T@9N$8<TFWN_``.*Q3JP!S6TO)$R-^] +MZ&QIT`';4#RZ+D'&_J8AR.;0AB^*PHZ<MKL+O'UK^M-X.%:9\7J4Y3JHHS+H +MIV=D%EV([9<59)$IK0_AQU+68^9>!2>=%^=PO?5FEIA.(]##AJ^=P>68^9XK +MX8#&6QP/*F!%NG%C\-6U:IIFB*X]8-+T?-U8IY4Y(?F8B!/3_-T8DBV.*"\M +MVPD3O\3M410#?RFM]3S<O\SI6P6SO&HH3CWW9N#.JL6>=8NYWWB,9&%7@G[W +M<^'`,M"^1-@1[:MOJ2\G>&QW^APCP8QL$RWBRC9LYL(1E"01N9K,&[/4`8-2 +M"0@!1*'($`J`F3[,#MY280`3'.UO8U+NB>LQ\SG:I#$*#XM,W4\<F\-[;RL@ +ML8HJL==BT`VC*;]YE$%E5=H`U([ZY3"`"/D-UUV$V<6+HSRCJ66`+@94$XZ' +MQ7I+X1)?P"U=BQ5%UL#(]7G8@"G/67Q-X+[]4QQ_%/33!7./]P3TJ7G38)OV +MLDOZ[?LT<<NF7HM0P#UKNG]Q\%UYSM`HF$P3E?%365#!2],+OHG3^\'8I2"E +MLN?3#+ZA.="G\(O23&V6DY,LE3(O-LMB,F6GHG/'[W'S3A,I!$F-@L+0KCUP +MO>$(<(82\1(;NCE^[O0"?_SXLV,/$,@=,7);VU@H\J:<[]2K_&Z(L21D;M,- +M&$I]4)`45EE\0(_[]<:Q@WBPO3-2WFK;5\65KD5-,0B%`$\]"%`(1!?<K+E5 +M%URW69=Y03Y;:F3>&1C\]Z:6RB1A<+8K1(\*]TD>ZU492AO3*H4OX0RUVQPJ +MB4A7IL!)S=^1T:BM3QUA1T%E2LGY(+!D!6QWKB]_,G0YD7HB`V+\1\K=)ILK +MF:HW1$HH38YIRG/$-R>])"QT6>JNUT/X/"J-!MR)3#XS7JXZ#JOJ>DU?'<B= +MX(OJU^(EA)9):2ZT5_5^B0-]@91(OOO#X?L`^`F8HFOV'9\"=?UK`7S@)ZPQ +MC/(?>:*>SMFI'<1+Y_QQH`DN[2A;ZS.\",Y$"E")Y63"0@G.A8XT]QR9>)0Y +M,J=E9?GO786XW"5A)2Q#AIX"UQ^^P8W_.)56#+TMEAM;V8_2JH5'':6Z-_\Y +M_NOQ/)X0;<76P>?4190)<JN3H8]TEK!`X$92&BXL=E9_3`KY0;2Q$"KA><>4 +MVY)<`3%"IS#"Y!E5':?W_8:.*JF'^CTIF4TS)<WUUC6?+`G,;&3YQ5'DQ#&O +MZ*!+I:TU0.^5:OD&%U'WXYM$]*TQ!PR^D-OMX<NY=0B,JVR&.@0K?#MPP(UZ +MHHF]J>)#*S_5UY[I4@8%OOO^SX_9(XMZ,@TAN>Y\X9'7'P+'R!P$A/4)RV'J +M?:2?76"A*1`"3^TZ-,!J4_N20(Z@I.:J1HC*4`_:1>1#));)9:\5T0T;J1K- +MAT%7'XDR0%01:CP<G*RZNGP32SN,,2^\\5MTU5'K6=RCQB#CJTOS932.,?96 +MHT'675<W8*K^(-;L7M9;R,IZ)8?`3S@+=>"KYJR%Y@&\YQC_;S?Z($LIE*R" +ML5[W-3#LD<,%=^PY:[IND%PE!3)PH5R;IS!F/TZ$#7``"D,M)2R`M8S=Y%IN +MY%#78<HD1D"2+!4TSG@@]!/N]*5Q9%(`>66'H\`&*!HC_7MIO/+]HJ@ZY`,6 +M<5/;&+*$PS3&"%<&?9RSTTLS8I,J6JI=?\7?JS^">],J3>1N+NSL_\]$PX\] +MI23;B?UE/$9%Z?JS1:8+EP3T'&&%>/S71!BHWC"2(7K?B?83!IY]H:2PL@Z= +MS3C\W*NH<"W5-"0&3-*[("4NQ7ZU?'&?K;T4>`X'7R%[*'-W#C"9<E(`O(>A +M-DHGTY;>2W*T&+FB5L*^PQI-<S.7>4#YH6.P3TY%G+4H#]Q8>-[N:8.M=K$? +M;P"(9Q)F"HR;;+\.FV3[0&I\]BT@$:#TR;UH6._T!,Y;2JS>TV5W-X7+F\#[ +M\+T%0.]DZ0Z:UC)K.*!5DIIWTUG$\^\AKBMU.+L!5BW[`RVGSK1*)XM%.)*K +M?5VV8<V7%]Y2[^I!Z5^J)E5KZ,4,`,&J43&OL["G`$`/K,*>FE0Y@VOH%ZH= +MPSH=>P+A*$G0CKTH=X<L,1*LT*7I"5MU0*[`;]R\4LTKK+KW-?9K<'22@E!J +MR_BL)J`(9P`9DYK[3TC^CAI#_>D,WAAN2:`&PS)B+J2*9W]O?1*1Q.06+`W$ +MA;Q]HZ4YX?G/8L?09IE-PFIO)3M"C%$>2E<E<)*51%U;I(+^V6^HH&]:S%+* +M%(Q;HU2<G_OBVO=?/!DXR>.&BK#46/NC4ZTPO$\]^,1*NK']/7(N7!70A`E> +MX*=I"GX0P@@`TR[8?/DW'V'ED^5+LZN^=!-])*X146.N%Y8*#OHC`"WW:_NE +M/E.:'1DL>"\?(;B<@W>[=$#8:(0`/4><@3]9!_9>2)2\5$R^\'<U'+:Q(0(B +MG=.Q*,6?2]<?_>7+4UB0`,2QC*])@#GC2)$$2Z&(8(0Z%<.(2O^,3-SV-QK$ +MV]5!$,%`:\JY;RNU$(F&C(KARTX0RV?K`KYC`<NZX?A53!X]#2T^-%Z8*U`^ +M&>`+SV?PW$3<231WM]-Y=\7-:#;FUE2E*)H="(4^;Z&>E@G0J9*<BZ-*EW'( +MXM_)8YIF^;7UP2'-'2O719NSV$L'-[I93[*`A4LMZH2O=`D+'^^=FDI+WY+$ +M'"8+1#!R;]8(AD!IB(/Q;PB>P#A&02V:;?Q&T].&%?$..G<]H/(#/D?8N@`J +M"$]'TCF^:&&TZ/H6[`LL!2;/#?Q`F!^S)><L,5DQO?*/6%K3)L/:_Y57LX<9 +M;1B;#8/*-Y&0F$+RP*A[GR!U#L%I=WE5\R60>LD7XNE@";L""#,#%]U^J@?S +M>%QLE]JJUBH0Y'CF1BPQI)M,U*R+S][6W8["VE5ZKQ4'#376..,(#2L)]BRU +M^P<U$#2FOC44+=!;DU3,S,WOKIY5X*+$PZBGQG>"P6*+AA)W>9[L8S[>J,G> +M<1HH"T5"ZE/E)[U=F^&987+5O);>YT'_V@+([//T5RO=@*.C>_>$`GORJNLN +MEH3X(G><J:?FI,'G7K)>]6G'KD,$OF4'1)HCE42R960M"_UU2O$#['R49&"; +M'9JM`CTFRY8%M2B^<6POD<:C]KJ%?@!'\/W0O!0^H_W@>^_[(N;LG.]'GDD. +MK5+?%/%CQ]'-DO%?%RNC]K5^\6]RYD<M"]*$R70`8;)6`_BAF-$!.W6YXIGO +MD?3@ON;<UQQBUE["^E,AI!W:DK]FQPO1`;UYLXM)\T5_0CKR#2X0'F@5T84B +M(%;O.>$RDRNBW#%ZD)E)*K838\%2RU5`(A.MG&B:VG)<I)>YVH-HK7KDV2)+ +M#'E,4U+91^%3OD5G\1:UL"(%JF3HA8(!-Y(9BW9Y^9K^!_/7^!^/WJZO?*DL +M"P`N/%N?XD.TIG6$`KEO8@5HHO;@#$99]>D#)E;><_89("CBSHW?DCY2)3;< +M9!X#V#FG^;'XQF1JNX<3D"3RX&;3GU8A=T]UZ@4^;]TKQO"Z/XSQ.V?,HRK2 +M4@$L3534!&DCT[Q1`BW%SO^<^-+KE/->Z`5]K1@/4I&CL\22\\8"=#C#U>?1 +MS#*&;F0%>C9@7W">,FF!M=BM_=0T^WH*Y_&]*J&.[YRSK"+004&^G6*"!S%= +M[[I0Y2-[$`S<ZZT3YUN5,B$E6%]&P/GSE3,XF-2O53O(Y;HC>HML)!"5V>LV +M(CI+*,QHF9UY@M:Z"@@FVU]ONFD+I_+6BL<P!$^-S=M?9AESXP='*<UP>83K +M2!8ZPOCI*S4%4H*LDD&K>=?8KK[>^U0>"KD`'V(GO3,LGIK=$6F'C?,.R`0^ +M%Z#P3NLV0=4Q/(<W3@R*4;"G-QJ(19_L]=MW\DT'U)^H:J8AXA0,!2T`)4(- +M-_?91W*TBA8`?8\?UE5968F#%M@$;D2[8D-PP#%>]Y'H]9_(SJ8H-QW935HX +MEDPNU;CS7:<(>6!VO_>,$\\)08P2Y6U7K$=%OJKV3FL@8H"Y'7B=4-[3Q``X +M<[;Z3F>-/UQPT'&31`[I1K@ER,0S<-DBQ-BHB_"N@LNYX:9M?8X32QY?W`-+ +MI#J(H+$'%[46(AV1:%X_FVTBZDNL9.K._DG`J$AU`.MR_[;Q*<O?^9DLPDO% +MZ9O_[34-$L.FY9N[]9:!,^_+9_]SR#E?93!7QBR8"V[?SK\<_V%J4QVH1'H+ +M18P43E=-K+__7>TD_.6K^;M]`@];0K0ECTX;O2;5KLGJH=J`U?^G1W/9Y/?Z +M].]^QFX%NYSCMK++TT#04X.(3CO;M^#0QL5MOGN/?WTS5?N/%>_)P7*[EQ6[ +M;<8>R:IZ5ZHG2/L,@0OST#DZB2%B>5H:+DBUZ!9WE\GN]I7D6'1+C?BX8I$: +MU-A'D"$*ZSNAUS5A991Q7P]4?EI*GIC=-"4E[H@\DWC._(BO6WFK`9XX<Z.) +MF5C<'H]H9!D(9W"!$#.%@@7@S9_UZ;\U_JE]XP5W8BPA7B4EI?2#)D-!8F#! +MK:U2N#+O_&)W23H>"M9ZETLH4")#9D)0<4OH>$X]Z0>JYLT2U]C\/ME#Q^U3 +M9[!:/@L-NLDL-AFC;]V:A5,#M5FL5J"'[];.GHMT+1B>5N]"^VT$)<,?P4PY +MIZYFW0WZWG`;\-2F*P(]XEB<6K<!CJ:YV6KF9LP#-/3O'#!K^BR+:,.<\32" +MR(=\#WA("H&\W-"U28*UORI$#CN^%,Z]V__/`0!K5VG#/9!O-A"#%A<?:Z+1 +M-(EH3X,.;M(MX457D0%NSM0".#-.=P#RJ[8"&<G73R#<(S\^K>6]:<>+"JRT +M_1D]0FW<T'[QRQ3M&/ZD&K>>?-()+\R*BQ@Y;Y!6#N(+@%D+^KG<4'!W\51, +M6WP5OBY(^9*8')\V,$;5IL^^Z'`61JK,9T^F#US[+`5&L7\@NC;;]%SIPACT +MIR`BHT=P6[._V6%B6')MT33S6SU<&@#KPSQXY3'0-LX(B^?RT^F<VF8C5\0P +M['Q&*CQPJU2IZ2`V##)6#,F_67:K)=M&GQDC(K,Z`6R8V@#1N'C<%`$-1>&, +MNKAI\'0##X-\H084$PP=%;S[J@?[9"&D:L/BPGP@DS_=T(5YTH/'E6#(Q'MI +MNRM_(XLN7>@OU>F@##[B.BE`^THQWMQ/,\W1MISF<,N&+4QILSK%7T8[8/@? +MV:I_-C/$VD)H41C_32VT?P`+=J9A-90HIRQ<"AUG_A/`K4T*(7//[KK1T"<. +MMK<:EYYG7SQ0Q@<--L.FQ^GVA:F$DLXJ_"GV(;VS2LBX'DM1<1IP<:IHZFKC +MXB56-M6V><M[H/E.!`-"BM5CUO%FKQ!>"0F@7E##E>!DJ/]Z$64B<F*I_9PN +M+QZ''.FD@+4N?WM`K8:&12_^BGPF^"?I-/ZB\4,R9>M-L\H#5"]/=G%O4$L! +M`C\#,P`!`&,`^*XC10````#@`@$`:SH6``@`+P`````````@@*2!`````$UA +M:V5F:6QE"@`@```````!`!@``.(/<+G'SP$1AE7G"I[<`8D\5N<*GMP!`9D' +M``(`044#7P!02P$"/P,S``$`8P",L`Y%```````I``"M<@``!``O```````` +M`""`I($1`P$`3D574PH`(````````0`8```\7%,#N,\!B3Q6YPJ>W`$Z55;G +M"I[<`0&9!P`"`$%%`U\`4$L!`C\#,P`!`&,`C+`.10````#P"@``HAH```8` +M+P`````````@@*2!/BP!`%)%041-10H`(````````0`8```\7%,#N,\!.E56 +MYPJ>W`%&:U;G"I[<`0&9!P`"`$%%`U\`4$L!`C\#,P`!`&,`IXL.10````#( +M$P``FW\```@`+P`````````@@*2!73<!`&-O;F9I9RYH"@`@```````!`!@` +M`"FBXMRWSP%&:U;G"I[<`7)P5N<*GMP!`9D'``(`044#7P!02P4&``````0` +,!`".`0``5DL!```` +` +end diff --git a/libarchive/test/test_read_format_zip_winzip_aes256_large_zstd.zip.uu b/libarchive/test/test_read_format_zip_winzip_aes256_large_zstd.zip.uu new file mode 100644 index 000000000000..4961dbe041c6 --- /dev/null +++ b/libarchive/test/test_read_format_zip_winzip_aes256_large_zstd.zip.uu @@ -0,0 +1,2053 @@ +begin 777 test_read_format_zip_winzip_aes256_large_zstd.zip +M4$L#!!0``0!C`*>+#D5-F]+T`A4``)M_```(``L`8V]N9FEG+F@!F0<``0!! +M10-=`("FO[LUN]5/O%Y/\T*]5><A6=#)TTD.OF)<:2AS[W[+>ZFRG[\#9J^` +MF:ZW6FK0<?^OE"N?X;_GZ;$PP5%L_]A0LJ6/RYU"^0YR=<::D2O,Y&LACUL% +M*=IE#5YBC"/\$T=^Z?%7I(%3>6M\B9M.9\@8NU&"NYPG+`G]S!QG:J='SS0( +MZJDX6N]?-JP\02/WMJF:I<9++GMX6D0?(\K$3R++0*L4==_\:N4-ATO4>0@Z +MGT::>U4Z^XDDF\((-V-.A(<H\*7GC&U9@6V6D36-R!9N6@A'\N]ETUC`#ALN +MWIL7)A!MHV&88JF"X=B:(/G.','_;<G_%#>-"H\V33\?F7`_O9JMG48`C1'& +MEBD,VS,T*$*I)930?M+66YR)Z.Z*.-,HP:BGBB)R"J(PM"`:,MS0D8^+J2X# +MQ*<U:&3DS(J67_&^#DL>]Y^C;%=#4E#U)Z\`$/J]/?=U2G%HX#%N[3H4STQ8 +MD84#<.^I]8L]EHMD$>TKSE/D9!]OY8W%<Z6(X*C8RXNN8I70OG@BA#;YIE:K +M&\41D2Q'2#$&F'_5HHX:QKQPM%!15OI<U@:7UJ\2NS\V?>$8O/N@1OR1^24$ +M;REM$[5WB&)80'QK_A1;C97>2`]^-AZ(=UEY?!5?:5'4`<-\=]A3F6Z0%PY$ +M6USVD?()9WD.+&_45@=M51S(<9`/U(<]MT<?'W$)7.3@$O+6AFMP*J(7#"D7 +M,6A\NLI@(7R8X8?@Z]UFC>8@+M/X!O+T2-E?X>#3T"2Z8]/+:UB0AV/2(ZFJ +M_+B5+&&$&T-HD,(?"3^'Z+8[`<8*Q*-[Y8$OS6W@FOAY./[]<'-UYKZDQZ1; +MGU+P!:^U\DMT1>U_29'VMB9QK%^J2DO`W"K!GJD)4SFQY-#@^]0`EP<'6.?S +M;$**![%"D@87R\'&P@\!WIBNX&TIX1!F+@2=)D&<&E0Y=0H/QW:5UA#Z<-]B +MHN;J&[(IE#1KR(2MB1!RM2PM#L&KP+V*"@SH(^8R2JS>]Z<5RP5CO?;I$OZT +M+>/*3A8$OKG:3)SZ1W4NXT5;QT-D_4'<4N?(Y>G86KZ,-P9XROY+F?L'3^Q; +MM<HG'NB$D=&1[>*,P.G#8O\9O?7`V(C6,(`T!OZ9]?`@F^.*8=Q"TH`+7Q$' +M2F\W,T8^U5)."F=R8B-Q-Q3<H`2=#=C]Q29T$W=!'U5G.&/<R:=DI4MH(7PR +MOB@XVZ8,:F%'3*V/&(YQ2/U2&/)IRHD!/`D!TWHKC8IW>4Z[47321[0NPLBW +M,H,`!A&?"=DO,^5]VY."\LJ^Q*OJ\=L-`="^XA,3M\1_04+3DQ-FZ<8)KW4I +M/6')W.3T\`O@7Y-7*?(VI%-I4A?#U/;,3?9@(1ZV*L20K=984+\W:\.(H^YC +M$3#`.N\Z9['%&@[GW)Q!JR`D+?4.BD?*M!A>8.*'_$1G.H/P.^SV8E8X)J:K +M--I+,W):%.EIFW'$J[O\)2%*,5;,VFBR_@FI2@B-ZS8QSCK%$YT!N3?@47(U +M2GS_,NT-CU2+QR?JE.,F'5?ZBEE=KO@D1(GS;IS,M!<L=F(@]'&S:TF&,[95 +M?OQ#^3X5L<O8"C0RK0(V6GDW>CD$F-@&T=7E;OS_-)6(`)4B69F[V[@.PX?A +MZ=I,`:/KQK!ASOPJV14&DW$%BBVN71"O546XH[R5;VTU<>0(W6RL`-9T8GDL +M*8*IXVT#VA"NEW0<69\]85OF\>P;<&WVQ73C9082TLF"W)`:6/HK97(D9"O% +M]E/\=D+4XRFI0-4DN(%+&5"\9@D8WQ%,#-D91X!^+C;<#-%)=Z7P/30T4,Y? +MS=F@(UJ0PO!"+HJB0*+4P3`+K-=1Y7IP0C*55'/\;RP+F(QZ+36C?*E,Q$+. +MX\U]F2$6:SIY)I^2<R3/BM!"@5:8MN,N^E&>-3&A86*=Q)O2\:?^TE7\C1"< +M`-/?T3CEN[E&S+/$E.%Y?$I94,*[H\O*"#?QZ?4WK^9&1XO\)#A_97S/FGNI +MYALKR83X.8O&D8.X]HDUUS`6S5CI@.2(12FK/."A+SD%<A<L@_6$$6OH?:;, +MF7JXN1>_ZP]<9)'C*TQDE&G)N%-1,K95^Z2[7F2-_(VDJXV"0\OATG``2>/, +MF&D)EOQY%M%_I/:Q(5YL23H]7TJ[\@-?D.I,.^Y99UN!Q[/XL''U`P&1@FY) +M\C*XD#`O)4_Q&WTU]$DZ8<M7X&WZ3DX;=**T4UKLY[]1V\#"T&!*QV-9).7_ +M@,VYPV$AE^M>'^W\RUML(.)A(V#D#E`0`>%UX59J^8WV+^K?3<,B47<>L/NV +M&7,L9SS'ZJ,8E5P/2PC^6,PZXX)S#KWH;#"\])STF&6G""_@M?-W-5X8U7[L +MS7+HVI8ER6H]:B[51F$9C"SD7I3N]/(&T]+3U*;/U'GP10RP^W`)`[3K3P0R +M,^B4#OE$;(8I5<[\B"6?N7Z9AD@XJP1,DRVX2`F9_$IOJ&J"6-9-$-"XOSRQ +M(M5SEJ.OO,H[:(@NTKI/'WQ`*MF(X(F)M,6E">92_^R8#V%O]T-"#[:`B:/U +M+C&O*KK:RMV^3HV1H@YI+M\OWES//HW.'UR[!M2"=-@_%OVP?VSS<=U+&J7? +M1ETNPJBUG!8K6!K!Y@L*'RT*R/%64^1;6/!']B%0O#_'Q&2#_EBY5@7O:>5[ +MAFI,_O-$)5>?0&7N<'5.@2MUWO0K2*5O";Q5A(%SAE8Y4&I.(I==%2*77V8^ +M5_<F44%GZ:^JB9H$#(-"Y"2%G[8I'>(SMM$5,`$I:&U)65/[O9CN7%YA!X$6 +M!O??-,36GN+[*B2H-I[>B*.V:5G+':C6^`^!T<=/98LA0-JYW[4#/-"]S'N= +ML=+1N08:@:8GAR96#8[FX]$]&$,*P4=EUA*FJ0'"&@'4)LX!]9ID3)K7FY2> +M,6&^&(6"KRI9CW3=X/5T472EY'`CY6TZ9)B1OEZXHZ*Q<H5='BMU6.!Z=]0" +MB4%WX[\IQM)`8*P&)@:+/C"85X9^;W+'/OA7G3F3/O+D,;&&=I&ZWM?U2VA3 +M1)[RT6`O8>S'%:^$K>XH3LB!Y0GW"G7\7LC[AGU0A&RD%];(P=2.#_C5`&#C +M(18*>O%=QC[?.^2(5$Y*PU:M\(<[AWE3=8N5`%JCB=]5?(Y!3&%,5&(!#,Z= +MH60'*1(.B>0,M^<C:@_G8^_*46#>O(O*_"-1K0LP34`JIZ$D67X.JR0,5Z(I +M5-D7O.*AYEDZ!WOV2VT?8U%%[;HM?P@/IGWVJ$Z"(HU8A&4U`=I92K1]MM/3 +M,E"V;AT=D6`+]-PJ]X-OE*FX2/8MY""8"7>-B,S_#D2%<1[LKQ6\;X^SY8J\ +M:"?'=I+_WEQ=E'^8G!MDEXLSW]7,A!G52;>WYBJEVG7G*CB4,O0>F0+M2U&[ +M$I./,K6"Z@)FR%AL+*[,@>@K_.RGK:*3BWP1M_OY,5B`B,XBFVM`=EQ"A]U\ +M`+\V5Y/*DP+0I8P28+=B\[8<P"W9[[O]`C2*.0U>4X0'=I:DNK9NS=&)CU7R +M_S9:9W,84&OP?^&B1$9!#I`Y7M]]'2U-@X+=%)>:IVCPMG`5<:>%!N;+I#;, +MC4S^:BCP*I1M#RA]L%.!N+(NA%9*%EY&I[()2YS7K%<^\\BP-)=5%@&+I\!( +M.]-O"DL+VL9\6SL#1XB<X,6@OC-@C7RJF3"[1AZRZS"&NLU2R7KIS2F4<^!- +MV/A1O&DD5J\6HG%YG!N=R8B?`,@"/9-^^1R9@354CPE?Z<SV7=>K4FPPE;ZJ +M6Y6VL0$:PO9:6N:`T$^D84%/A<Y(TV41^K&0QGV*7DQ`9I1]>3^7ESZ-IV!4 +MC>I%:A;&/AY_$K&K$@,HH#)1L&E7!3\G['M:#)W6^WRY`<18>,^;,%`<^C!& +M3>QYN_+6_"[0^=Q6H[VWV7*RKBG]'&RY*><"Y:8*ESCK9(7'@,B/A(5NY`-- +M^;(0IU"'NX.MC5C_A:&A9<2<^"W::C-&+3&+`[S1MJI"[KMS^/)#]VDO`4<Y +M`M`_)MD7_4;P#!K%_+L2*BZPKP0GC?5X'STN!/Z-1Q``7LLV%+4*H_"=1\Y_ +MCY=U]OQP1`:O1A(&!63TC6CW^+"78--.6/F(##!0%*DLNO+X4XBKX#;ZB4#! +MA\'HI_\]H"NHD7K-W=[+/EV@*OM)\D@O:WV>+-U,/YO9SV_)VPA5$8+7&<CK +MUFFL'^[X,NNZ;&VCRE+]^3[TU5#+@_`;99"W:CGG.-BRO1;@Q"_SPXF00ZZY +MG=FU:YB-^;3&$WM)H"9N+94X[S2^Z96M]<Q8YM._'/$3+X^'TI="X(<^:?ZJ +MO7/SGTCH.XB0=C^038-42Y?G+&">NB]HQX9V2NK]:8Z50UT>/Y\0>3W>4@T= +MI??&6-X]='7KGF-&VBQO)&)->W_W]6,IS[FTKCDKTQUC!7DK-+'2=']DMUOF +M+M"6)6%;K/)EKCO*6BV"AD)#]8#"*JN\"6N6R04'W!%OZ7X3$Z;*D\:-?CHL +MVN;32V@5,*!I1Z$L1U>?\JO0/H_$A`O:$^;W;0*I74@FRE4M!/QWZW+?">[! +M?ZB_<#&_`,'1T4S(ZNLL6@,2R6_?TQ'VAMG[PC!YO:+A(XCXO:DJ&2[)5E#M +M32\388P^R#4A284K0HD+QH+-.'_%NJE#M^>!QOT(#&54QRQN&0UGU)M@S387 +M0C8T?'XMXNUX?"#,UBS@^VM`M1$RK7UG/!;ARW[%I^2UKM`(R]_A@#E//P!@ +M85<RO9GFXV@PJFWS#D29S>?M"O!"L,+1D54C'B/*W/D!J)..W.>"%3(`XLT8 +MD8%D.@4`.`DU:KG4JB`#LJ]/C/AJXL<O=A08&+]2(`#WMT\2429DN(.^$;%U +M4S%&F$RM1G?>WEPWS$LP2_?COYJ<4,MPSF#87391CM-[@+J$'^<3W()F)GO; +MTT6KDJCDU+!&34'6>QP7T;Y>)Y@]I\IW-/?ED$!]QU)N+:(A0OYC5]0L^=%, +ME'XYNA=,^'8.W.5VH^X;6HN;39V*G4@#/L"V=?D[.6X"/\_P4JN1^+E5FL': +MU,,29JN\T.1\NA+T%3.%\5:^NK;"!*V9ED&^KO52%];M[<+6?X7Q#V;L%>RJ +ML4"<,I<UJF.6!>(L5SAO]K:/Z<#NI=L^;/41;3ES7&CL#*1%JV6HUDU[D;;$ +M"RJ'I55R,R)^!0.V>LIN]`'(FR8"L3H'UI?DIO]J:_SYS?LO[4#3+.S[*!++ +M1?9`_0&663YQXO@]:]\Y85%S+^93>)]6\"RIF"J5=L9EFS,#"=[E$Z+T7<CW +M#VA]-^V>ZWK$0EP8L398/SQWU]CB.J)3)>^_+-#1'ZQ6$Q\$;X;U>*'3$/L] +MFO0?O4\?_%BJ(SJ;,U3\^'WRHA1ES1UP;`E$,'FDCSO2>X0XO)5MNPT!#R>L +M;[XHLV<YM-"&3'24K9AJ,\#T9L1FZ\\!TUH+M:ZW41*67!>`MXXQ4:]FO^:B +MO)$$&\1H([P[D^,6S()J%2%A5XC?^7BS(`I=N4"@IO"3GS`ZHM\J@WCE[!F[ +M0XTC2:DRY!OGW\+ZS!51F+4!;Y<VZ?!^!-A\F>`@4-38P9@^"]U"E4^YRNE< +M9>[\\WOKA[7RY;W229('#<0F!\(G0[&P3P(WJP06IPEA/-J=O1=X)SPPD#Z_ +MJ()3JL18)))U#K\'P,ED#]7TP,^HMAP2N?!?R,GO@I;TUCHDO3=RDK0^(68X +MC?FZAD5^[[!'JAIK_.5I]IV0('7,?JM0'^+5&7KS@2Y*9,"2EZY=S(PM264F +M76GT-2C`M+_'YD3=A&L.@PTH=!8WY`X3J]AJVFLU<#NZYR:MY2TNC9`_U)E\ +M(HWW&\3!UX.ALJ;O#=FXPY+'U0>?*?^'"UN+W`+C,0531S.`#=X<;%Y@-/G^ +MH,864EYRE^HIE)X((;BN$DKGZC=D,5*(FX)#Q_00G9:SE4ZHJY!L]CKM*?D_ +M2)C8W"W7KIUNHL&RY-50^<%KS%M!HYX=_'9VZ)NE!_6B3E)/'Y/0"9KH\M?F +M,;,-6X*T,G#C_E`_K.EM"QXH;!`.#UMM<85`.STHA*1;7+@2(59)@XJ1JH,[ +MF&?H@?#0DB,\S]RZYC4ZX_%=V6QZUO0*LUZW(;X=H>Y4@/M$.4X>4;G4V'-( +M4]=1`+V]R=XS'6]`4?;5JUKMNU7]):`TX#$:]B*[RQ.*I@/P-)>NTF[5O`LA +MT[2&/`>Z-6#U,36L(OU9EL@F4/9A5RCC:#6!5H?RW9M^:MX'U>0<!P3M=IK& +M/9^=/<2E>L/*`-K\K=(G(<5G&TJ=J/.S@X&(1WA<2)K05`5LO6WP<EA=R,C[ +MNIPM';=;\2VZ_\3X&G5"E*0A4V\,97;>#BX-"31*SZA7A-R!$/9=7^S-V77! +M8$ZF>2JVWC:[&BB(%3)OFS?W=(4289&2"Z&SY-4LB(F]I%[^$)7&P'/2YK/L +M]#/L</GA(9$+F$MCSQ/'=L=P)FIR-)@,]H36"^8BGX?J;00EJ:Z6^]Z$X*)3 +MS%BE#)7M_.Z:40\V/B\659K,%\3R<$FL;-);I`T3N;F,TU2<]M,*+5O>P9D% +MRP3>U+Q%DRJ^.1\CS2@L^)*/U#946KABQ9+TFD(M"6M=HDWV,71/+4HVF&5& +M.27MR,"MH+9KP_]M76$E?!'G1R##V+&!2YU/^HS".UVYV[E>R'=R^>%4T:\7 +MIQ-1)?;F]E%\72`+.^6);+^+@[MIN$7<B8SX_8<"%36+<K$VU1'B?LB4BT@C +M-@*\%P`@S%3R?5?6]Q:V./?"=]E5P>\`Y+JTK!/Q-.Y:N^H>K[D][E'KW-,* +M*[/%4=XPQ7:S_G(E/)"TF3L6?/`+4%/<!L."SQ+7PAWM!::BR_2L%&&M&5#J +MW/7>O:E6[7W",E41P,\>#6PD-1NH(H,><+E:5KIC.+FN%JA.`\ZRW8A\FFF= +M#PF!X/HMZHR>ZOBY=L'&L4B,BANPD+D`BP12;!;&75KYA7F%W$.*H_L2(J@H +M6-P^CZ906!$QUY0F]B3Z7\UL@R'>Z+2\_&8]",WY1I$ZA.CHD%=[0BM5^W:> +MB`.>5A-Y&_/F_1JABRLP>1DYHA$&[%4F;Y8KS&:B7@GYE22E(Q`EOMGM#TSM +ME>V.9OZ`)E:L.>W;V8@W8.ZA&$?YA;8R4"Q>%K+:-6)*VS8]UWT\06R&JAX. +M5HFX)0'\Z,:$G$V74T4<1?[^KNPM2/?1M181N[T2+63>>?-'@43KN9.,!]<S +MNH[-Z./5`;GL6)"TSY^!P?WU89TBZB*Z#["M4$L#!!0``0!C`/BN(T7#YZ>& +M/QL!`&LZ%@`(``L`36%K969I;&4!F0<``0!!10-=`/E^F`^0B0H#1GUH4:)N +M9HY&.E.\T#SM[=N`_$SANDMJ(>8!R7S@P52^>;KX_^\>0G/G)S5.%@9#C*^^ +MCP^35LL3879FQ$?W4&36H!Y35I.5#]/@K(&E*LF,MU&\[.V?-P,J2$^4.\(8 +MOZEU\R0]EMM95-!@D"K&UE[C5[W[L:N,C'C@!P:O:V5^LT\'JAEE]^':%R[4 +M8G69I3@+@/K1I^+,IL698ROXW,>#!T$!:$]*EC#/LL<VOEN@Z`EV@`2F(P#C +MZ#(RX0>5C0)L`%:X`SL99A>#AF"X`30^$RZ81^(N^W?2&2?L,#B'LM>$1Z3& +MBQD]:;:R1V87_SUR;$M6U!?K+^^P,K54Q0M\G9#+NIBV-`!%\"DH^83=J[N% +M3[ACIIBJYYH@"H'Z^8I8,!=@RM]LI@K(4,;%)-;2Y_XQ9>X^6>7_!.D76`QE +MC5_^`++J)PAY%*F3'+A7!>T7;#//'1)4*,Y3H:.B[/!7(N_#Q[MK56<\]RBM +M0?:[]<GVR)F=G;;;'R.@;Q`ZD?3A#I6GG+X9*8T06L25#=NHU@6$=.-_J3"S +M)X=[]FTO@;E'Q6::_\89!I\*59Y_!P)*8(/EV3!I3[H5GGY8$6Z@(U0B_']X +M)BQMWI7R^<P:+2;PJ:&B$>[9S)OR-SN+Q%2'.(M&9E-M>IWLI+MG2)TG`)0Z +MIR[W/&A:LU=2?Q'93C5B<.ID`C(WT*1"PT>L"O:KGW4QA$2[N;P=1H62GRD` +MJ'O#,%AQQW5?)W3F%2O[;J:-%HY4$@-()7C\=(/0+?X6$/UL=5RJ,0?1V*'8 +M]6;26?IG^B9!TFI/[3"=USM&+TDF'*QDVZLZE)\!(OVAL_<*1D0V7QB/!VSE +M!WS8I-6J9;V`"^'(;'5%T"]P8(A)R[0?78,R@%1R0AI%-_P69&%AC#2#Z<*6 +MJIQ=.=+$)#(?+/R:Z@](G;SYWY0@;F)&`GMR!&7@`N,6G(F`GE:?6-[U*;L) +M5>;QW#+W\N]PA8^5X,I87\"A$-..\FT)?A35YW3,QV?4=2NQ9I+%+$^W:*Y3 +MN8H-"5-N,C>(KTSL,P)^AMRRPZ.D@%H\'WPFU9?7J>+5QJXFT'',@FG8C.)T +MP]F]Y6A58V<!<8-W&^<`[O[Q,`<2J7)OG3VHH45I60IHU;1^8E8TV42A=AV' +M/M?'V`/JFPU;[.`B\$3R";[M][(<:3<-'UI<&6/IM--`P!RK4V(LS?8V^*HX +MXX9MZ"CHQ*8[,N]?T>),Z<K(;=C.#V&C5XSZF%;&/:+C@=@A>L#?\4&UTK6K +M<"6TKG$?Q9=1J$0,DYUOF#5/=QXS5NU;ZU](-GAUEJ8;G),_POO/EJ1Y1()B +M&F\6(E5&O:?ZV9*)X-)`IQB1T2=#@6;2B#?U5PN3D:8GV*'4/_A48(VT[#Y] +MWC29)</0#R[2[N-"V=%,;B']#E5L4T&A=+-]<\%:\=8WL!:R_O9VZ=8;R@GU +M^_2FI_"^;!?&>;,=">)`#ZCQ`/CYZ1\C&S:+=;CTRB`O,CLE[49320:\#)OY +MD@XX8S6%ED&=,Z];)7E.95-2EPZ[.882DNCO!^2GPHCL,U#M)*9@Z"@X@Y5) +MF!MV'MY=CR(>L&RGZ/1??HXI585;!0^5PXN_3'A&TU1(7OI20SG<9%E%TX(- +M.)6JP:233P2>^*<!LJ^;G_5MZ'P8ZK/M<NW/I[<8!#:KWV9&#"25"CH3#?*+ +M3JGCD.BX2%J@6Z'J`>2WHQBVXBV8PO^TEVJ9#COQU!@89-PM+$$0=!.<,]8$ +M0#3NK'`AB<XS`:O,&ET)'!EA/R(\'Q!9"O>5S.YT`[+<"$P(U25B"PN4!I)W +M.Z\D",LB2)1EUZ(]G6FZ?]BT^/1P)$*XL)'=<3_`[;UFWG9@E?*OF1PV7612 +M44E.9C"DQ73"9C"1O1ZQGP@XXFV*M=HF#@D;W8".D^L2#$5='U48]L^Z<?]B +MF_ATPE&J8AR5A)UW3`W'5^7OH?FIKT?%0E7\C2:%8ZRG.G5/@N#YV':P8O/R +M#FP@2DTZ1V[T]L?;-?!I,]8@U@')+4"A:<_#]O51OFL/<PX2Z)LXBPY^7I(D +MC>H"]QP=/OZ9D6^4'13;)I+BI3;=/!60$?MZ8GF$XVGB*%XL*EN/JBS-)XH6 +MQ81HFK<P.N&-GE5?#:W_K169;5>V!$,OE`A(A96HVT*XE3PA-46(B%&+T8QL +MB0RRII@OK9G^S<VQP%ZU[Y:%FRP8:(L0!!SBOWF2]4I(:M?SRPI7`RXHXM%4 +M20`9&]R'GC@PX`9FE_K]ANG23NU^KA68:,T49ML*SD("1[\O`+1]^FWB_]DY +M8ZUQ\-7P%8O36NKWFY*_NB1A7X)[9&8(]VRP_=*NF1Q4LN?C<_"1B@9'G4$$ +MRD+H@5W@0S.H2H^,281R>6/Z8X\:L1^^4Q18Q'/(2;:.5FNA^X+-B+5A$4') +M?3,"G_UKA/HY(;L`SG'ZY/OJ+YD=P'RI[2+4SAG2ZC((;V9^)1Q<DJ0:W!%N +M3>5G9I%=]M9T!E.673;?[;51HC7A_M$29Z;O>_-WIRNK:1WMKFP/[<CIL\BV +M+G=M]23V9.9YX#OIXO(&'';<?MI&WG4W/K9P[B@V3/UC(\*#W*$YF@B=81K0 +MR)[_MVZ)T!/_F'C>2.,YM2)13OJZ]TZ_Z`!GF-FU=-,0'@U.!Q/%57G>$Z]C +M9DF$6M3YI1;3G`/CH25J5-UM=O0713G!O4@03[7D5'KV&VP2U-G%/F(1'V*G +M3GPRP9R`CA571]?)Z&6S,^6S2/Q#"ZP_?RF"V%['`Z%1,^(E+I!2B@`KNX++ +M$BQ017#IPSLPY,')O>N\(/>^5(P,:F$FOV9$J7]&(^)_!K\)D'6<9V/I/P$# +M!.`-)_\(>Z=>U4)/;!"?8.$Q:2/7(AISMLS1D$(J1XW>+=6VIZ3;OT$%SF(+ +M(E&>F,]&Y$+J97CP7B`-^-WDV6U/,H&WPBP/NRQNW](MU3^VH:G^"K1_O8O$ +M$21-<.9'67>.7FQ2K@5+`H%9B(UE\]6F[Y"DF-M%\J2T$]K(`[CWFXB(P?K( +M@17<5>Z(_9:1E\KTR^S6&NB,[EVHMR;,%*WPM'L8&;`ZTU*")X\YYKXW.TL] +M7-PMBXB?+-T:,FHOIN;L7`2@]O]C<ZH3*]J,JXN^WAS?*PNG9*@-+''()Y2^ +M7NE<EMI=1]!%?^,JCB8X`X,$4NGB`H(P^XQQ*XH-PDYS9RC_#\V9SQ]\B3'P +M>U506<$+J_>#'3==NU!^>5/3=\0H08[1P2^?X'!2)C)7<A!<[OP8UM(EEIE& +MX>0S(FI]LRJI+%8N;EX=L+]PG<QG-"`-'FEY3[M_E'5S>G*&EXT5SCZ*X&5D +M3^C)01)6M>L;?TIZ=_5K:$=J-F2.-EGBZ+#:VRE5\<4[D'NJ`D$&BY:"0O3! +MT`U652&XT:$3ODA3G!.@&)>EBLC>=!!J7`!2E1$)%`+>HB:-#^U'JI]3F./2 +MNTL,CM))G*1//2W6AN#R-P7._L)79];4_5R'B`T$\BU\,6JMR/T0"/4SO$'5 +MK'B7/;*,9B46\3U5]>U/N/:H,,;M>U5=WE&:?+:G_*[WI.2SLDIG9#D'"R&> +M0_5&N&/*$ZKU#Q<(?+"&!(@#/_DT9$&P)F3#%D`&HXN5*`NQ1KC'#KR))M#' +M+)]_R<9AZRIZZ;T-@IZ2;E:W1^)$S!$CD]),H^\$*<\E4/%//'(,K@H#W6'+ +M,!GC5(0\;%12\_0=\EG^91"VK@C>S$;-S','ZN=K<,D99,,SQN6#+T%4X[2= +M@CKBR4$STAB_'JJ@\K_%0^@`%CV^WM)#6,_`B^<M_0`$5=0:H-A`"T%LOJS0 +M-/K5K-<2/OWP2BU3*?@H.&KT+IL#F$J.!EB+Z/<JWR7Y%BX6(-N8U:&`7;9/ +MM;3P'M>?V9X=NLE'B?'V'R48XF,.A)B35/>C\T1VHI&EV=XF9R9S+D*%BT1F +MKBBT'AD:Y4%TF.=:,TQO(8YH*&ZWO?.@*/5X,F(B]!3J8E$PI=HML?P*3Z8A +MT40W?;4UJ'GD8(,*;$1E1H:8G@?_K)KXHH&-#<W@T8;*TNYOYQ>FF].N<+M$ +MXI9N$+<=V"-C(L255>;6N3-MQQ/1F-5,;"SI2^T:$RZ(1>WUN;E*_]99YS_6 +M\BK*<$6PII-DMXXR##*5RFA-P$JH0[-*Z?;_?B+1]2#AV`5GERD!1U#G(9GI +MTM]6TV38Q?CB_]NGE*`+';'.A!O@UPYZ@I1H4V]^7':=;CGTS7'MMKU+CL&2 +MHRDQ22I\`C<2<CO$)I`6JUX\]0U"HDIP*[Q7]U.&LB)R0'H8F=?>E-*F`W"I +MNW.KLJ%EEJ+8DU.@G(\Z!V=C=(?-YH@-Q.T$_$F.?D^JXYH*50G"AK7]S8%< +MI_$Y&_D1,M%SM&TX.6\PUZ>PZ#$)MW[Y%P\6+"C,J]\[^VP!MFF@CZOX>'?W +M&`H?5C@RVS!7)$19>..NAV`!A/Q"#JG$;9PLOMG%_O=";*MX5E;U-5<W?(X" +MG.`H;&3<Z[1_Z#55*,A8\7W#"`FG_,DK=HO[G;V]6U^*GE_Y">9^&;:>WRT. +M>H4%]\?U\DT135:4*0H3=8.?`M0UM;27[#J>"_GX70F()5V:B8W45&-_.'8H +M\E8B&\7[K.,_/]Y-HJQ!E":='\7+27PB"73TLXRF&#!5-SQ1/,T$_\@(&.KH +M[]IX=:[#VS80[^O\_&UMD0-MB-C[`<N*`B$LTNA^JICPG+_G1=>D*<=K#UH2 +M?QEF'0NIKM'MJ1/MI;`:(]$94#,:'E02#`H,Y")N7G7)#KSB`+T_3)HI9UC7 +M18NZD=L_TVLJ>"WK%2OD[F4R$%QB\L11:)7I[5.S6$GKGZ02>+HVK'K%W6F< +M7$>2,!/8B,NEDNUV'[LR>DCT2G`:3_]H8SITCDFAN4Q";M+\W`8SA?B:[Y], +M5.^%0]`W1Y;Y294R[:\2W'+AK04KX%*@[8K;^$_@9M7!>I858(HZ.D)3[V!X +M9,?%O88;>^X_FR$]229K?!G[^Q^2#2J3B'U*NG/?0'[3.[_9<N2:CK8+:F53 +M@;X>_SZ6K8H0E'I5O5=Q>S*DJ1TX^EVKO-^&Z9/;QGA:>P7YP5'M;M\0OYZ' +MN(?*3!Z$"LQQ6AFI$5>]\QU,56=#ZM_1M$RS]([BQN4[;EH3L8"<RM%_.C=A +MM;URQ?Q@@"&EGV1A^H6S0LWINC^5-A'Y%K#S#X?2%RWXM>U.1TJ53O$>!0N? +MB;>S!+`-8E?R#]@LBBI/ED=G_T<[@GJ?>/7=0=+QS1#K6MX@=;O$VSG$"_/? +M/@E2#O$5U6L\AHVQWB'$)"NR+W8_N=$CZSQ0(01`+$[0VIT@>.?[=L?%&SE= +MB0IR6E1<,0&:QBBLV?4S%2T<OYB*"II=+@JCVD`<&<2_4&%KGZ%3-6.I@8GA +MJ=59S_-BW</^E1N)?!GB:&I2=YNWFH!,C10&5=5PXF[A@O9`7H*V8>&0PQ`_ +M89E+JS[4%9I*QUZMXDSJP0T3XO1M3MD4PO3BH\Z0ETP0.L;PWF5?OY=-;J@0 +MSXQW4EXI@JLK*M3Y9_\WUBB8'-4)#RBRW>T>-'("<3F\M@PN4I!;JGRL$M;D +M9C59QQ>QL`UOEY(&(M47%A2>`3#&4I'2Y9@X^I1C")=;LZX].G0%P<MO@6%> +M%RW1!:3"]4V&EQ/<UBVEF]!I=X^7O,&_O1)KTSU*BNZ):&&&PKBW-4ZR)$D^ +M#%&\'A:F=:R<#IN`K^XO\$N'R'`N@]3+-B3CCCP'-87RQH5_KNB\V00\E<B> +M)A)^-`+D@UPI<].UW)?7AG^I;RMFNFT$8)<G$O,UY$=!BV]ZGL(U)Y%O(0\' +MJVLX12L`1`AD_H6DLP/VW(_Z*W3G-7&J840PAH*C,<G:?10H;%>*2).BA+AF +M>FNW0A:0U-1F>HJH)$,@3K-`9>-\_F3RS'TSG*0Z]^I:S4;J5CGN8>MW,5^L +MM&XNLZO"PDMY/&[_D_-D>5:T_/FF!>'AJ-8(_+?HM^*"(V$]SPS-7'1=WOPH +M:R>RN[!>YTB#'7SI=\(2C;AGX,2;]REK17'G/G"U,[)?-=$FLB!S?\035AI; +M!48<8FEFU%;3@I(G<;H_]B[C`WVJC'2XGIZ+'YY_U#RU'H7>L#EYB]ZOM26D +M%TC4$U:K7:T\$$[G*,)AZ'#-Z<VUTS:=^28&FF>@APQS.%6EPS4.MYN5TFCU +M$$7FJC=J`P7SZ4]LP/A_/54N>H1AF__00<4R8T5]926OZ00!R1X'_AQZ5KT# +M.]X\%=Q5,"U+&).6@F%:`X!%,:TC;=1N7CRBZFP$W^<'L>#R.L\,E:U'85M^ +M0U#U*D*]\'`9\=$+W7+K>L1)X99=.&K8TQ/X8PN)EY1N=$,N\X3>%_`LC6:C +M[$34HS-I<+\?3E/U,3]*/K[U^[QZ@ZTVB>>/1SD<#-G,JHL<I)6A!)!%7JC4 +M8V$THL]:]6J72%=6FM8JG,#I;?L$\T[D-)%(E\&1;.S96;P.\44!Y>^^$(GX +M[UM6+H]7<I8'<`>B"JN&CA=UFSY4LUG9MC:2"V$)XN+C$(CYJ7V-.-(KOLJV +MZ`.,W?CE)]'$Y)U!VN]H=46V<P7!78\RH>0#7B'N-TGC13Q3PLWI9<JK-\1? +M\(U"-K`1.\TOI49K?B2$22D2PC\I;*V^2*@!7,64G8VEQR";/5]<R1\MW>0] +M?"3>@P!\#%5@[+_D"FLO(VX$\)/Y*CJ:P&0Q\FL.9$^&6QGW@V9]G72M^.94 +M4)@EI.KFFW:TC;1#<+WR;4_("?L%$4W0JN4A;K<1Q7/]B\<G&SB.#8N_[>DE +MSOR"R+6R:JQD_TXKX()\L683$_S6LM45P&X&?;L:.:?\[TJMC3,P%;X`EA6* +M35#GQW\:F`X^'2?^K(QQ&/#?F%SX?FXOI10C'_8?\@\V_0R#A.13YZI$T<J] +M(V0%,E*$[7]W"8C#`/`Z_4<&</`YVY5#88G3MHOU!KBY-66-R%G\=GXBA%T\ +MV@"UQ(NMJ<_\]I*'NGG,ED<`UQK@W7$Q<4=[1L>IP[X!8;1NC%=KKIA<Q[P- +M:>0KO0>$9=6?A<";+J>=5,U:0GXGPK[C!MBKG$SXAV"30JL3'$-[$L2W'A!7 +MO(#)E2%"`F0>FRH9\AWZDYRU8!V$8L5OW'\`8[:\U)W`#,N`IIFZBOF[INUW +M%`%]?`RA@+5,72`46SC`5YWRH645?AB*PPS%!QQ[`=D"D^C"6CZDV'2'A@O! +MA,Q83XMM5GE&:67=#LE.4G0(L(:XSCQG??X5-6AYH0J2Q`4([5/G.P"!.?\9 +M.:_P-O_QA#50IA"M;[(U$EK[U57V(QY+;*0$36`V*<QL9]9?"K5M/>KK\=;. +M\5[=Y:]`VK4D:#T*$R=PB9[)?W0"Z?2']WO\RNK%>082+'*4=BJ[I:LXM:.+ +MM8$U?\E;KI;X7.NK1>/MH,/"6)70H-HAV5@<D@'U.2)WK"9C4>V]]KOM;J94 +M:EJ#M#&]4^+7&78^[&U982`#C(JK=?9_TL'/H:T3GTO=CG@L@>-+T_,.VK4N +MJO?&O/U%)*['XC/L)5F93^/^R%JQIUG"]N!<B![K=L54]D9QD#D7"#YGW.+= +MZ"J(N81WH03Q>(5Q@6SXCCO(T.G\+C-$91F\WD[Z24J0'D_"4J[M&,'DWG=5 +MSL^@!.-93#!]WA#[4F\*$!J!V>(*;NY<6&X*-VR*G\XR?23X0HVN":%W/>EU +M2YY/W71(RG09(G30_0!(*8$\/@1]FW<KJ7LEOQA<EG\'T%$)(+7.32CJ2*^# +M'+.QT`^C0QIW!+$E50^#PL`P/(:,A.A,3TNS`6E/J*Q9A[:*S2"`Z`-*$WO: +M1JYN<L$A;BTQ>WBQW26LE-F$L82(BG&(O1FUQ7IM=JRF;MJJE=;(.PY^)B"; +MSS(4P/.&QX>($$2XEJP0O/X%1/P$J\+G\\>K49)OFK74Q)+E5=`+^VE!(^^G +M<U6NIV_="FV-P]1J:AE<1,^=QV8=G5>M5Z4>`*29'C\II+0L*KUA&.[.DI=- +M-DRD&BJG%)_6EV84?O5]1("[3*4DI5KR%_R5;`[L"[N_X]#-8>8PMZS>''K' +MI-B^*#0"HZ)YC607Y439QSJ70X<BLCM?_`3/3F,/G",ZO&!HVQ=2@>?JM">9 +MJ\_>%B)E:@K0HH%_VWO][.\LH!<.-T%)9`BWR`Q'_[U,J<R6XE:F[D$(F='F +M_)!DR&@IR07+*G4_"Z<XH:0^=R['D6VDN5[&""6%-2;#.,'M$9X].%[O*%+F +ML'0:7ZH1CB@3:-`X!??U'7%*TKO9>1*,#F42@@"?34?&V]S2:<?+1%TT'[]L +MSJ)&$:&G3=6J]67#"MBMSP3!>IRD5?P+%48^7?4$+6CP?Q^>W'53FQHO)OU\ +MBURJ>9V[=7?"5*V0VK?F]E1W5\;:;!VUZQIE-$_U?NTD*;&D/X64Y%NJVB=% +M62.-\Y01?:!\4+$UD[%&.1%$^N>$I`4Q\OZN[""\&&MD6K&Y*D#FHK#T.Y': +M?N1;!KCY@_)<["LXK7@_;\"\@(_@9]?7,1R@_E;_SUKE)D)^'!OHJ(^,=YDY +M;<E6*KN<*1Y"SJV+9#I'D2+B?-T0;S'*N_N"XZ0+2#HU3=,"5K2*VWUR0LB4 +MHQI_*\GJ0[$Y25N[Y)#N.4M(PIMCA`P0F";/.(KELEL#,!T/@_+HI9WA",\U +M3+F>"9ZKN"CLIOWO!]6RXO66OB=6NZ(%5!1-6(FN&V4\U"%C%>81U\\[YC7# +M2_T/#'-6%K8;2.C/R96F3S@4;@:[UVXGB5O<GIN:$C@]XBN_(+CA<8.^..%\ +MU[=/`I6JR@I$<'_+-51%3^=,A@;*QB`@<D8"8\!!II;<#H/U8]%6:2X6^$:J +M'(320Q*K>.HA/'K'.HF=[[*S'AB;NIZ.TW5TK-@/P80)B1.6`;5*9PP\=+J^ +M9!JA*CG!-=;J;ETU%QK*)/<4%<W69$K/WL>%SD<3IZ.C:^R7:R="UTI*%2Y9 +M%.RC$AS3O8>ZH64]LN/8PU[]AAK\F+;A`YN'98.#!W!S'(;^N/0NR>6$.5AI +M)WY2YY:9&>!*2;/LS*<L$9O+9L6K!+S?L(%TRV8P$,I/N2$FR%7K1*`D3L,_ +MS>L/,IW?]A8LQ3B%=@ZP+00%^JBK`:\";0!GH!R?H;$FU#)B3^IXKVNG2]=J +MR1>WSC\;R$!/4/\)1UQ+#4]B&5Z"WV714O>FO?9U9,G`'3CPVNUE]SP/]<-) +MSWLE4\1J?,J5H`FG&PSO^P/YEFP8-12(J,S-X';(?=`WI$['-7",WPJZQRNK +MQ:KY@[\;_[T71!4DS:*+.;6I84>$C&OJO;=E/5&CLZN8LLGY*6/]C6Z-/MM] +M!V'BKVROR4$[,-PK6@QN&%0#=:!V#YX_KGQ_L+"?L6!V;+ADXUT5;*[M,]X6 +M<T.Z7YY+1:OO'QS:K"=DLW%KN\9]`<G!1A#31BB*XX)Q0\4C2R"*+C:794!W +MH23.FBZ(E.MU^_/`#"-[S+7';DG'MYR;JE!_U^?Z8VM`*BF3MH>SDQ"D?A]- +M?1J,*P?O_(20DJ6`0G[^9A;OZ([W]`:K?,VTK7IC6(?Z%1]!J>^EXKMS[=>R +M^P@<2+*N[2MRZGJA(K0ROFELN!Z/--O`08!;`Q<.4^"[)3RAFX?19FC`9=^9 +MO&.`(#H1H41"-VWO^_LSFH^GZ13Q<?;ZB6$4)>%T0%O2TL!+;1WF]5?NCLQ= +MH\C)R70EUPAU9IZX1^*,9$/*9YNM?ZP'"U!%P],C_W&=VA.R>53\'LA:4\8` +MN"F-CSMR2]_*]E.*SR..JZ5/.@E9*TEU&B8K3B9?X<3RQR$JB"E?[YJ^70HV +M!?[G!^4XDBS?5BG=J]"G+F'Q+RE&^NGZ[<!Q\7%\A8$BK]<K7^U:SC,S+F<$ +M1G>U>*2LQTHV-S:!I4=A7D`JJ&`(%<9],/7Z%]]#L86JD!!8&:ETC(5C>Z]6 +M\UOF@1FELP(G6>8O'>`[EU%,5X12JO-C;0BS*\>LF4.*1^\H;0)]0#DE_&JD +M)Z0M[RXJ\%+O;._W<_LV8Y\,0U]4A15#I&4H@K(*JJ+3V>V-N&@A`7%+B%<1 +M^7=@8G`'*>PMY,I/1+;';MYD=S:*4QD^)?=ZK631-RJ51`CC>%^JEV\.5'S0 +M^75Z]`)A(K(Y(K#SZ%[%LT%5_MCA]%E).MQI(UE(/N1E7%T\_2BK2CPZ<'0% +M@@3)S`YK[6T(<<:&6N61RJ^,;OW)D/==W9TP36L@%61L'6EZ1?@(R2HK_QBQ +M06JE374:9`^>+M,`G8?P2*H1IBBO2CAX7&<3'1F?L9!R)@8)9XBOR1C`T$SM +MK!'P&Q1$@`[25:>!<%?^Q*3M1@4AO#KWKSV=;B]N=7[J4G7D7<[J;Q%_T8\% +M.>-L?TOLYQ4@2*K0W1LXWEI+<A4W[H<<%#9_VV)'C8;\U(:,L+V!259I%7;O +M-$9%A?G6UN/]OBP7_V3=R/-`]82EZ!"N505)[")PD1Q=Z:Z7IU+TMGPSD.P[ +M?![Q%,0N`O90=5J<4$'_W&9GT2;P<CS![R5P/!2Q_^EZY2KCWH"7!B;-@52% +M[2:*\N6�+=6N#+_Q#:383#F?)[OGF'N'#9;`^G9UQV.#*O8$#`1)/VQ"3! +MF-$FE?TO_=!FJ/.U4$M^[1;;^1^YJ(TG54":@*><I*%%L`1653]>4](N'7W3 +M"QWA]O\7V*G,E=PU3`4)3FJ$MZ(?@3$)HAPR$.NW:DZ;T6`J9GLW.BG7;2+3 +MBDKV?774&)"[1(7VX=P./:(TY^`+T`8:>NR#L+=8KH<"<BC!43N-X/@`<!'/ +MX+FIKWO]3MFH:,7S:3H.'J`=E+3-<`FA[GR5T'$W:9WFGJ@JZ?![[6.5R\%V +MJ+>CVO,;.,_,CB<(B44AD*U_CAX)J^8(SM0*(0H9Q.KV;#E<8)*4Q?UI">4^ +M_MUOD:1KF@F^!58+S35R(OXXF;0KR=]K<<BM+.+-ZR93]<J#,YT#2O&6APVF +MMO!W%8V;;DD]7!.Q\QW'W5V"1G#6Q<-(5\T$A;9W.#S738G"^!2S"`-G\PPA +M\?Z=*COO&T9`1XMRUA"HM_*BK"-Y/5=S]R>9X('R218KMI,U<J0/O^T)ZA/> +MVXRM2((2*#MI-O@MMOR8W7=(O'<0>V>=-0)!5P,DN^G&EV.4[G+'XFY.5:Y9 +MZ9ZZ_JH<=U6Z-E]OYBI099FIP5,DF`V2OMB>IW8K+22;;IF%;0>I"ON$!4<V +M_60Y/Q='B7/7O@R:K@VAHZ5-]$&3`>`AJA]T0'?I[L17O-,+*^]9LQ`\%VJ: +M/#F2EZ6TJBV7LF1+.U\2U-10B1TG@;38/^/4X<>KI"#O->)OM=WB:5#WP?1V +MAD'*5Q8-OD][*TETLG7:N#!/.3^BF1<HM2OZA1;/,H>SC]B-]_(ALCNZ&>M( +M6D<;S3:6!1*J'SJGF(W[W.IC6B(5]7&Y3(&6>\%(GVCO=OT$(,I_`%$PL&M> +MGO@%17P5'6XPKF^WU!/=:CM20(Q?M>^(B\MWPP17Z1T;1%)=PI\%1V+LS=3O +MAT3-LG8J57YV(9>02DT.*%+O1@=[@^+D54I'@/6LLY@O]J4&:/GE.$O-92AC +M6]L/R9?QE8DVL5_,SKHX2B/B)Y[%BA#DPTZNZI9MY1_YQ`7R6F_Q3^_B&V"; +M$6OJI/T)#]ODAZ%A89RYKZO4BY^]='--@Q-_2@34;BYJ=?)(**JZ;,0\X3CC +MYQHT[\_?KIGYE@4ZB.L'8A3Z8O*?V$02NP<"\`OG1"5UJC)[DZ7^[F\Y8SQF +M_45%J=@S;-:V<WUZ)A')XW01W3<\FH'<YN9PLVW$B`>[Z/9--5I`ANJLZ1@D +MY505CGS8X_Q*Z[%<4).+87DN"R]\Q1GP3CZLR.5=HXGR@V1DE%L:3^UB9^RR +MTN<[()PEU&G-Z@)*L/0/R9X7W=#3UNO'X0/LRDQ:[;6^ZIRP1J!\=SF_D/T` +M,[<J(V3_[F<H?`TSZ(HU4!;"J>V<)V\QA3H)=GL!+]4JC(X1,'7+:.ZH>5HR +M?<CRM;1E^SG>4Q\4*($O(G?#T2N,.LG5((@%-(XHHL0W4G5]R@5RH)/_T8[N +M;)&.Q9G0%\#0N;%C";XD*6S$_%/\.+(_A\FR^A1KL)=NG\B@IW>(^Q,=G:O) +M"`GG]:\#=<_XPXX,4RVT!A2DNW;SY$6XW)2$?@(1N$,]7VPFVU8IB#4*>,2L +M83V60K7/ZD+@.K!E]5)E'Q(ER%(%>CJKJZQ;K,(+I(A33X@4TB?G%RDNABKH +M..47K:GCBI0(T,TR7OC1^=@#,SG^@K5KRPDZ?4/*B@')GA:U[`N*)HP_[OR] +MR"5"R-O9/#@Z6\-O4,Q>*=R:[F=N=?EBY0?J]NN[5[PE<"G4BR14KOOD-\4( +M,;#U'H2]V%^%3.B"-U^%QL4\W^95Y?PF[0;?AK@2X7T(C&C4%FC0X;OT7$8L +M`!&/-33J:V[D2.XK&FG+W6]I&'(M^S00GC7LE4DV)+*1W&V:Y66CA,(.#7#+ +MEM$ITBR&?>@DH]F#<U0"-!<AQ:CY^?,ABZ8-+0A6#J.'()99C(&XOV%\Q'6N +MC&ZNX.F#`8:[#F8](E-(C[2<']MJ3&KB='J;M?/AFR.!+AEC,^(WG1L9?T!6 +M66Q!@;[VT_Y6Q''\UDQ]GP.C!4`;YB-XIS57:2M>R@NW\@&\X,V2&P(T+A;Z +M`YR`JV$)\%<*+RJBUM]/F.(IJL$4DH^LN9.SDVNP6+2=2*!@4(O[!@(@S9BY +MZKX:\<2G'3.;(U4>05`:4,(;S1L$)!_ZY"'85ZW@%">J0Z49F%4EI=HU%N@1 +M/&FW/:%KW.(T\609;SQLCM#)O&]?O6FRJ0"WOR&#$)!U`,^+:3U.F]2&6UCD +M04P-PW1VDOS90%O'!U2B%`]G;),ZHS>]N;A=JYZJW:H;DI^L9T%2)(--Q_#O +M(9VWD-:D2"NNP"J$GZAAC61HTP(N0\6+$WS)ZT$1%N!TXT=)6[N+Z@0PH?G1 +MT<JN:OEEU\Q^`8A#GH/IRB3PCZ96MB7X^%.I11:T4?.@.,Z>DIVH\#$7\#E/ +MS,()+"P&;;9CM<SGUQ)'7=J]88DA1F#9;*PP&GC&%H3QW*H29<X\&EI!)802 +M($]REU[$`/MV?CFNBZ]];?I&&9,OXVKL'Y;H>5&_XDVW(VTTPBCW*`?DX-U% +M:2O5'JR'($GBB&(C2F30U/YS$9%RI(A8\O&8C`5[`/<E"KSW$3(`ELL%IVL% +MJQ,QI09LT/4ARVP?.1SBW.Z/?^6>Z:),B&L5:3.V6:?>.F!48/E*S'&JX$^Q +MNOV[CO6IQNKED<B"!'X3MK.A_5&-O\8N4_/&ZT;S(U<NH,QZW*+T2=PWTGN= +M`9C_)+93IN!->3;X35.%O2M=IS3BAY8]@^Q@IULEDLQ/-N729NS=0Y";X0%H +M-HEY:290NX5DO3Z8Z#/T^MJ_I--SX/M9+J==9DS0/*-#?3(''*H7;IJU`S/8 +MMGL@/HE0$6)H11?8A!E3PH7W'^WP2G/R?:IP%)SP6+)6JWPS+#69/!2$75)> +MXK**44^/C81'T"!5$1K[:L58VJT*RO8.T];M*Q!K!WI>F.&U0?,1:\&"Y-\R +MXE-2*CM,;RP[XTJZ04,]W,%XYMP@@'GMBQ"$@.R\JV&+YIP4&H3@\<@@X%2A +M5&]\!!*V'\CH+E\`UIEZ/^+]%*D^I&"KKWY]Z>RFYZ]0@6W78.CAPK<+:<9: +MX*XD5Z$S;`"%DZ5?*?"W1^>,Z+97P^@:/4\6;@&O,[,,_OY`^0FPN"R+V"Z_ +M1J*R7>D0D<450:\"*0A[*M@!E%C%M0ZYK>$?B,S>6'=R%[EKM(C-H%99\ZDI +M1HA/-:*!]O+L28Y$7MVEXJ86GPH,KG]:4HO*I(_1X#V0YP^DX6%=X..UCPQ- +M`$VUA4:R/;Z?M>6<ZKY%677EN^L$$5Z11(\J"*R=K8]#531^\*Y78ZAC^$:F +M/"7MU)(R`9_5RKA2)U`4K'8^HW197#2CT-T>UOU?U-%>@-1O@0+GHK7T.L`] +MN9CP)U<GZH,#8%V9WNL3@O8L_EG1DTZ<"(2^[DY$.TQ[]BPQ&DLD$C+D)#2W +M`72M/8IP4=V=X0&QZ.(%$WWAQR,1$:\'K@0<#<:+4<J<-P00^85]<MI#!]D0 +M+5Q'6JG8!0)LA!Y@-'XC0'G&`(!%^8!21R0JAUD6JGM1)S@Y*#A4<&_@UL^/ +MEL!>+]`'6-:R_M*^6Q,C@#NW+P43=DM/')_),ID51[5_8*[BF?I=^@'<W5PR +MTFFY0?5G/;..*-X43BU.?PT_D\,XQIH5O.3:#.V"7EJB6<C4$DZ1!O.-UAT# +MVT72.\1,E8"*J9$[WB,O])LH#5&;J3FV9T,'1JEK/`M(HL%GJ3S"L]619D-C +MA4]TO8?Y5TPGY];[$G:\K2^I]@?\8U5M]NZGJ3P-P]-7<7;C%O>18HRR',PZ +MKX]O@;M(PE1NXVC:X1J7H=W.I`0;77,8:TC[<N[J@(N.,Z\A%'3#7FLB[%#- +M/N0.68"S_S)RNH&%QZ?XHU@I82LI%Z));.HIE<TZ]9YX2Z>8((W^BCT"!TL0 +M5.F58!4N0C`03L#*;5C*A"BPD^^O>@??S4X3=;,DMC9_;_$0#U9^VGS<[H_= +MS9,T_4)LZ73R/6`?/]D4*N52:XJZO0<>Z_,08!DE2`FU,#/:"UMB]&*N>1>P +MI5R=IM*N*?4_RXJVYG8VY19C\IS7H-@'!PMH9(:!LON+E?;F0FOB&-<5#"M2 +MRKE?:N>\<!E?/O+[,44)R[":%;U-HYA^:<9JG9)&!02T`/+C/.[]C@M$U)^\ +M,MO.&";(APK6,P5?C#A8>890'/I#'AG4&&_=7MQ4WD611G;K@X=H9-1*EJH! +M&YBWF8O;@*N,1,FL?<]Y<4U9\X?A^V1BI1SY7OV.0[O[EA1"_6"T3BZP3-(O +MOBDJ+87$\$2VY/9Y._AJ#B@R1=-^S>XN^JLTPC+AAB"ZW"!P(YN9D,</_+#. +MX(1J6F@[\;,RL[,1\6I[6YQ_/IX4R!</G?9,6C!B/PW7+)`;`E2#561^.G?= +M$,UU8E\.J&K>2$W)>6K!M*\3FY,!9\.<'9!RMO_T[#T`[">?I+N4)Z$9-OJZ +MK:L92\3DR:AVB72JCT/Z\.:GMZ`ZWJYW%?):K<&?ZB?3=^B:?N-;Y[8U=A0) +M]5E02LL%E17+;DE%I`Z7=&C)%$G,7@;VW3_MDT(6&(+$P5-P+8U*EYD?\38' +M!('UVE(:*!SSV5&.[SQ\^((ZH$+!8N\*QPMFJ'J9T'O8^@BBN<>"-O'[N-1\ +MJ@ARI&@@G4(M/3V;NXZ<N+A770[ZT*;Y^_)<D6%<'-4M(#@CN8?<@JKXN31: +M=T=?/@?0`O_[YF):E%GD&\P_'9,%`$=/;TJRSV:V8K*TU4G`P\96N:I!%"<# +M!!^F?>]!WHO+EH-%(J9O$^4\I_F[>C%!_^T_AJU[(-D50D4YU"39!&8-;MNL +M&[++FROO1Y3Y?'39#,\D71]K)Y(A]O_FA0.`'L_03\EQ&7]XQ@D_Z%*-BIX= +MX\2R,%7-+&.CWHK'#]1RT0!O;%GB'6:9A+)$D:2]0N2-(LIY=ASK#S&R%*-: +M>U8L4[X^4E;4D+S?:.4-T5!$3+,257ZA!$-V"!9A)-UXA9&AN:@KOF_#=VU9 +MF7OY=D_R10G]*F$[X5'@#H:T=^F80?J`N9;^YJN+M_CC\0#.2)XW31.+U<-8 +M(I:?7O70"M7NIJL50NBOD[FNN3+L9%C"W^Z;%"*Y?%P;F12\R_B%P@+281$/ +M%@VP'8F8<-7'*55I5&L3-7HOC+'SAAY0'*UNP(S%?@^0735O&[_@U@:G`D=V +M6;'F\K]:"#"!%E-G;3<BK?;DZBVANPC8+Z45N7)RIQ0.IDHQ_IEAM>)%*AD! +M%>'4$9DN>$^,[DO9_(!<++>VV*$8BUC%XPU.!DE:MR9;5-'7JXJ+3=8XSO-` +M!T>VEXW;<V0(2WG3J8BR2]<K'.:DTI4MRN=IR_2'C?-Q=F:Z&LEUA\)9N.^5 +M97"$8(=2>T\0O7:%@%NK<YV>(L'T8ES"C8Q+P8#<8UZ/SP[(9^E32[_9%N]? +M,'0_5+H*$F1V75/9Y1"=@Q=B?/C7)[N&ZKU6H"3+OSJ)NK6J$,K\3-!(=85S +M0ZK27,#I5"8544X;1=!8$Y+BD?DL[@$L97MQ*Y/"YQ=WR::OH(>U.[^"@XYB +M-/B$S3)"4(08`#]J,WG:$=1?Z=!=DQ)M%[IK'CUN3W(%?.>K)</3O%^L>9K@ +M:ZJER?,4H.<)B'E<+[GJ=UY0!N-+H-^<VYB9&MB3;N%JH_C',3/9<K5P[@YL +MIER2Z,4>M&:SXCN6IX:_,^368Y%_:!#PLA$AM(D@QECJ<C@\-#Q(XONI[YVI +M,!4I0V9D0:"X-B6.86B_]7'$DI/R@2U,PMRO#2JK*^9L!86]3^[2264&W$U( +M48HVA^#9%6#9EC8JL2>]$#?[&8^>6^\N9[SG;RV+H')I![E&E7U77UY`I)1> +MV/A;SS\C,6\(ECF15OZ51$P'EREEY'7TY>F-]D<HD_1Q[..]5))1>GPSB]H1 +M0O@AR.@",/(D+7H!B:^)5.5<F'_@S6S^@_^U!\>Y:E[\EH8:1PKQ1Y+2R9WG +M`D2LIA)M`)VWN3%U`-F[?O+#'9KH`.K5]PQ2EIBMV)+IA[Y4\]#?41=R/4^] +M`&3SBW!K?O,^(EI$Q@`%S(9R8P>X"U\1:PP;LXI^+@&+A,(A^XD7`!2&\U"( +MT0&(I,O?;:FI'1[4"3C@(YU>H^<]TK$,?O.X_D?'4,!B=OC8\%V,5G\WJ8V$ +M,@XFVJ0?K!GW`22_T]QOYJ2SY4^.8@#/J<)E.89\Z_YFWW\8Z.1(Z&@.!%N& +M%9CN&[O#'7H_9X>_QA*V,<GLT.%P;MW'\"G(HZ#]4BV.W=9\_3\3#VN>,3MK +M("*1I04`!J6YQ\.:I"P4X8M?&T=+E8W\UWK)'=7UL2T-W`-<6/MG6NQ24/G^ +M"76CS?!J^Y3R[$>:4*T\%V>6GBFFZ_X[$5[!?VED8F1Q(4N.1Y.5EUO.HWPX +M%5S#E`(+62\;T).\#6$U/\$`<IF^H/]7L!C6\.<?=K5X<)C0Z"6/$(S<>X\! +M^'1(7S9@G7J4\^]D^3Y@56WY+EF2G.%L)V'70QT?#,].';KOG74R2LXXZVYL +ML#;&/^KK)>L!.4^/_&<A3FB6"0SU!*=E859E-KKK0G35KVR/9ZP]`3<'%ONU +MJI,Y'[4/*[23F(#NE@`_KE3C(U>@"FI\OD@`#:O4Y'4N]M\?&-J'BRXSW^UR +MM0`-9JU#]N]XM;@3>V4>V;@E0]@L*UFPHI[NSSJ5$LP:WX,)PD1RGP<(N3]X +MF,%EY!"\+D$A3VR/Q4HC^7X7`=K?21X"E?*@D>RJ%*YH/JMR"`GS">Z?=@V: +MG1X<KODO\_P56UD:G,AZ_+CBNPRJ"=SC#HN)HV2,]FX-8!N>VF4G1@K!W=RS +M33B:(Q0GX%DM&]LOX>[]S1W'W0B0M(_.G(T`J4H53JMF1A%^YK+,3IL6Q(+. +M?]<`GH#(@&XH6DR9VY?L;N5B%:UV/Z?%D[K'D<4LC:]:I,2QOSFKR@W;13R[ +M)8WHC<]KT;Q3T>5]=*C>7^V:#YD<9J>HPQAH0JS%/<?"/BK@=6%_[9)1O2C1 +MHJ43N'YHV(C-[#R>Q-<)`UAQ\P!QI+=RLQRQ1=AJ$'M-$8'-B,]!/HTFB!@8 +M=@N#/2#3RD)M6=/J0Y9-V-F++MJ(LT/DWQ/C+<XW&&N%!C[W)B`K,!62X50H +M:<=H#7[FM*-_G=7U%XSS(&+.L8`?W`'#W]U!2REW$12(+G__JXF,-+HB&3R$ +M&-@JQ?EWE^`I=+"8G#])"F\,WMXR_S4`<KOUBH"AM[OH@@:T%EDS;-4?8%TE +M6YEQ)QA^*WEHX&]<\]]C;\.(S(D?5HX6K\[&195>-`==T_(W<A;<0I/=[^>' +MO9+?V=VP'Q<[Q'%HDK]8W/U;M>02T(-%&<8Q^_L>+VB8GS_"H]UT*A!`A8<Z +M!<-1_C_>GB;I0T'YEHSWXX2?A!&ZR%V%FYHVNM6HZ1A3Z_T)>E@J%(%-9YJ* +M\\\]3K-Q,7C6YT#D'5087QP??GGL;WT)%@.]*W\P$IJCCXCH)V>;Y`4"N(0] +M'Z5TJC`'#*T_Z'NB&0N+W2HTY0?W$-D<)=:K'CL`0BLB2Z6>F/^2Q#)(>ODN +MTPF2T?/8U"!&.?0S;-P4VP&D%SY9P5JV*#*C7Y+OI!&CHJN_\&V;LCTKE(0# +MU13L3U@ZN**6NB#B5JB0X@)CF93/2-R2*"M]9%>\*"U0*X1XA&V,4\[TI81\ +MI.+KC$3W![.8#VL$,9$&DC.JPEL^VH=,&A1SF3W4$)@G2P4:9=,,NW)"XQ^R +ML3$;I45QLT?+-1YJ;SZ)@HW]G/S&C2/7CO+.H:'A$A7RNZ_=K>*HOC+E3&8= +M0?05!K@'H4H8%:1L/0MHVQ*@WJ<5;5,M&/B#'L"%))+.[&XAA)+D?J1CM5.% +M'MS^MX$!>5S+[[.D-YM+=S]2JUQ%2F08_X78Y*=V?)P_8]IEW==J+Z7ROU$> +MSP-KI(KY7SBHJK=IL`)#5SCCA:[K:$6YQG:TY]/<Q9M?-?:+-D<:-X'4$-@, +MF6']EE!<^$R`R$?W^P87/:?`P4J@@QEJH,];,TG!$3HL_9!2X\FT3K6UDVF) +M<"1):EGNM9EME<P9#BKZH>EGZEVE#\%F'#<H13/=I6.F1+YL3W#$VU_E\I[D +MD:S::=H[R&RW!@+ANIW;X/S7>/P3A/J<`HE4HL?:EU)<D%EX].'^E>XH<0BL +MF!H-J3L%0YX-89_XKB#NA@S0RH_^[@?8M/C*K86'S1M-*:'\@/("[((7]HEA +M_$$@'VW0&ZK23TE:%"/R253E0_#X3A>,V(/(#?NF9-F&#\(>,?%"3"^M5R+L +M8VW"/8R^Y&U\E9VE,U?4YH*H(IFV"%."8U?2!'UE0_+^[7$G$@@0XIE^[<"F +MHA&H4M2JCD^'X+SW)4)?X\.$'Z.L^S>Z+DD<+\%^G]QNDK24=/3XSF?+NVEM +M5JYI19<FT-TV<DG<Y/Z6\>FMIZKX4\R^O0ZTU[[F9Z\G3ZKH_/B,T%*=$"2A +M;OSWC7GLM6ME/>>4Z?>'H2&_:H=O;2:TXPK_[2E$[;-?"$DOO";"\EK2-O7O +M=+V]4V83X!5P&K@\FVXE7;DPHY3YI6LV4]UL7&I3;IW2H4,""=I1%`?^F/RZ +MP_L"9TA#^JI4)R(WDS=.TXI,TO=26D^6SI'6]C@,6T>[JA9:@QY=93[_?U-O +MWD^TC=<H_Y?8H.J@4F<0SS_(-N,C%"O7HYJOT"]=Y_Q&UMJD"9*.L@K^@O9: +M+D1,.DKQ@EE=*-,1"OD5:^PSDWMND\7^L<1^4018^A6`".5EI7T%8:O;\QS@ +M17\C=4CK-7T(L4N.A&M$GRE:!HO@Q;8BUS//6T&?:/+<A(%-8"EODLX)&.GR +MK%)I#8&6U7SM5.V"-R()3'K2$&@Q/0.>VYQP17LU4P+,-VZKL$T4%R#CJLMK +M(]'MJ'2;(T;>;\ZX!#11MJOX<>ADVZ_Q'C-GFR\TS+B3'F1A&/;ZT2B77TTL +M2N54N`)8C`76)>7(?(;=E2D>2NAL"ONUI07UCP^6DI);^ZB9B.'7-F5UX^=1 +M/6,6KV$$._C5.A(UT>))MRUB;N4)Z@T[I_;,4J!`VO$1L,F&$K(HG:'*,3T3 +M)_GA:()AGS5676:$F).<:G#A,G]0JV`U9@7B]92133W]P#5T72Y(\%K0NS_\ +MBGPP/:B:-0Q4N#]/B@1C#>/.3^=DTRHJP;#[5CO"O$(V>67ZT?T(!)7)%`-@ +M%^'K"%H66V$C:*D'QGC/7WCE8H-[V?!,&YJ+BXX1HU-KTR1_SWBXY3&KDE2, +M]91)/UNN2ON2]0D0[30<)0W:JP=6>]*;RI7(#(@ETIV/;Q8G!P/53J,Q\M7` +M]N_>PS=ZJU4Q',J(B$*,VDR_1#L?3$C\]U+0_47^E048\#TMMD\I6>WIET$W +MB.ET15@JCFK_::BTD-^"=4X;15&V^B/MB_'>)-5'SH.AFWH%H.E_;.OZGT6Q +M?I=E_#@')B2_VAQ>&YF*!UWY,!BAUPDC"5A>'46KK(42\;A<P[5R=#;I;[7O +ML@=-5@GOY#FV0(OH"@CD9-2`J:LFJ5%8Y9B(A'%/5>5BV<R3!U?0ILXS[].$ +MQ`8DFFYPQ4B/FMPRI$B@B9"Q'.>%2VL]]GTWMA!28F=R\2?#4Q:`I]WWG^)C +M6-YRX^3V!SC1,R_4Q^;M,2G;2WB5NY#-*3POCKC&A.C1#L5B0;M57.'6(N%) +M!_-9NKM#.5-EGC&I7O&/K<5/DF+9\[R,$%-4[O#BL$SL>;QB*'.3%_[I'"%J +M$4?WC1BQ8':M3EF^U3U2\TF;/8S/,@/_I+L*L*$J]+;T@R2#_R=1*_GQ!)_: +MOK:-P)P?2_'.2:3&5=%F]COG("!/Y3JJJ6\V&#'I>XJFQJ"3[*%1@W)+RJ#8 +M]WEM\9-QEKZ.3?CIOIC@Z4LHZU"#WH<X42W$YD#5*`U<#AL@GO(*&HZQ%PRH +M>9`JL"*92R.K(#K!/&>>$67[M"(:?K%0Y&&_J1G[;N@#LSUF?%S[B[.OZ[`E +M1&;/CR=_/';@I;M4COC+)XC0T!W[P4B,8A(GE8AD_A>#,T4KUU?N0?BES5,X +M1W"72.'D^JZ>+9TV=_:1N1@F+I76I?&&PA4YPWS,PK\RJ7.H9K>3+*A+^VJB +M7VF].Z73`6+<U<&Q:'[N_QUJIN$[R_CN90CU@S<&]5\<\A15]ZAYX8$<0U83 +ML;B0(4@-X=C]"#SP:CFP5(50<.HV(<[9C$[C:7PT/XUW>;!]L,*/[USX7+1B +M6\0YW)?BQ;=#$K^#^%X$'BF8#FW$Q--5EQS)IA0=#]3EFZ4"+M]L_S[;DN6# +MQ,LH?>7<U"^XN'UKB>NS:L`(J3:N1X*>V=0"?3(8;2Z+/-5GJ(8JWPA5U85Z +M%!DRQ/HYRS67!N]1B+70"]*UZ:SL;`0I_57Q\$-]WI-G_YTH`I=_4MV=N.GY +MJ/7W(DS+I7RX)Q;RE3W^://+U3T5\C*?`6Q^;+A+JV))W=;!Y?]YGJ-1/GK8 +MV3<;"_#'.?AQZ4KWV[&8O*<<?E<6R\A*K.=+>0:\\:(@S79S56*3IDZ5]FQ^ +M_WQQ%VAMBD`>Z9YF%)@#?PED,7&`M2J^F5<'C)*S7[<^CTTS/$'BW;TX_A", +M66"K<U(P%:8J'DHA2]O2W/:$36<B%M;HG1)SN8M1D,$P(9N?^@N4-K)`&MS_ +M-AY!=&/MQT<`R"(8W,92Z%_L!""NY<=@RN`W8ZEG^0E=@:T0Q]UX,\4<>W*; +MG!SN^L;!B&.Y_)-STBGT_Z:64GL74ON:?20+M-9@`;2O,@LGTF_BZ&GV2,YO +M3+I2S)`=;)\('C8PZS6ZGF,"3U6T!*3/\\E5*+>I`IC@VJ,2(.@IFB)I'`R9 +M+8XWMS>PGW#D.([`H9Y'.49F[[RE&O#+OU':*NM6Q=E2+4C>XSR"H7JA%'-Y +M!UB<8Y'/<),80E5,:]$<=8>.YMZMKZ`4=>QZ$#]?@L)MCF33KMN"(_6=#.;X +M?1.KAGCQ+*/JRV.F"'XWQDA<$1#GO6X#F15C/XT8A)#4S$AH;<$:]4!?0O^( +M^$1>!`[37`_XJ6F"<@#(:H+P^/V6W;3+]/,1NCMZK9F$2IG2LY:A8[J]=!D% +M_,#I3S'DL7B]H)["(6NKI[7A-\D."'G5=2@K!SAPN1\4UDC(W?<ORN^:&VF9 +M5XO5""*.+8A^?^610FFVGGT%$@$'!3^ZV[E*7W&8(`SX.#"!RNZ`C51.!C]T +MP#+8<E26?`J[A9M^7(DX7;CT\@FR1\%#]!T?(%8%.Y]?APA-O-8RTX<8@4A8 +MJM.?%E+[75I,$-O\H,M?S2LM*BLK`[B+)Z:D=RFY#C7[+&4:G<U3#IHK_4A4 +M5X(LDM<]X@%FEJ9L0P'WCK2?DPRN#[T^G69"(7S^4AHH?X<G]\7!4-GDPZ4; +M#16)S_)LR:AE?TI.\KSFM(XAP.P9G.9,/=KIOINF,!,/$*U$J<$UTC;,&^?( +MM,$0(\*55-X'O1QXW$(KC;'$LCD((?6DG6K0U<%%UP)$.Y>M^")+8D=A^/+0 +M3!*Q+("+U_W:TTW4PBU^(N/(J;PX2,*S'E61U`3;SJ..^^^HL`+>(YQ^UBCY +M!+!)H<E>ZX$\#6^F-Z+\59"B4&U;*?:R+TQD@A`O<,BPX_UIX1;R0+:75YT5 +MW:TWC7&><5\R>\/;DAO4A*O\CE@]*T'")`#=X6JVFLW:SD5##S`_!DWQ;'X< +ML$5:5.SAU6M"VK"5S'H5935Q8$S0/UR1MH-FZXN)8G/T)_2:Q,2>,%^Q5+F! +MS;Y4,2Y8,'3',W2V)%5!49M]1+[<1L-;H<`?_PZR)!3HAY:$]LTSC3I;,(Q( +M#(-R><849%P`0D<53:5-^R471CS[NQ\$JZ*`!PT:<A:DUR407J1.4+[(2D]M +M:L@%@:E<Q4J09JF0*IF_]^53#B_=P^S"QE+$T+8AS3E_&D?(4.D7(=BM)L$G +M^+UD6Z!H?<^":[CMM3&,NOU=98MY8^I10#8K\AMW:?G"0K@SE*GNC$[:0NWW +MN!/-<,B-,4^82(*#0)UDI,C"+ZZB`<5':D1!4Y+Q*/.$F'A6GI:T*1\0Q=6` +M`%;4LFD-IGW*H,),WNS/=\IN0F29H6!NXT:PLBE>J_#+@3;(+^M*RFADD7FC +MO@9$\OP"89.>PWI1-(^QJQO>X-]6-K:>("LQY!"UNQ@KX&K9#I*GT9E?"NL2 +M/P%!6Z!H7Y[@BE3NY?XVOH8KU-.O0FWIDZJNP;OC_3D?&^B6)9-;QI/2W7"> +MBDKB..=RZ`M%F58Y'G=V&KOP,.Y:K)*Q41_6`SS\//3_O=J&TK'D9H`)^:9X +M!8RO>0EA(,5>(^L#:CA<N2;4OUN&F(YMWBIW-CW58#B7$`_%-]CECJ;9\1N@ +ME))+=(:KWD*$@84$Z4-&C2VUI>9>N+]IS;S9OTW']]GO^U,<T*A[Q^D7A<DP +MQ'U`-^UA`#=Q<96,2@VBI-K)G[^"<[X[7S?)';`EFN62P:P[08C`)[?\@S1H +M_IA.YC('+(P/&/7]GK&T7O@?@]I-DPCLB7E3_LZIKL12'F3/-A'9B:5(X%"K +M*IMP%#)Y-,JU&6E\A7<_?#P6_X1`'JD+ZD=AQL,YN<#8H2J9]WW8C4SHPO4J +M2KK?:@`LN_[7,+P6E=^E.'/O`#Q94-Y""TJGT8]/$@F-V^EEKM!PUG'VR^6Q +M@<HW;!G+'=88Z8[>G8F!VZ"U"+D$<YOJB$BI$!;WZH6GA[RJ;C?T*W+"LL16 +M:=[_XM;:&RG6C(S7%&9LT-Y.*5?N9F0^%AP2-E)=85C\T@OZ72Y9@>8J5D+Y +MFCX=&4QPE`[<_#QR2!*6>7L)Q=4$;(LCN?W7T<P.P:N8!MA=[48^NGVFG!0\ +M6PJDA?PC*M2Z(EJ2E?K[FRW@):13TL-X*P[A#&A]@I@0*4@U\6I(A]52:/T\ +M\[="/=NY(_OS(*(YSJXS.#;-]QX=AL?,N"1RW9P]L112-M[;$TTU;V[;;U:- +MHG"@FX5LW#=0GY9GL#AMG9PQY*`D7+CFAN0UX-]I?]P\`B5L*Z>(`@A?%>K+ +M,2>S3H5FK)04PGX60?L:DW-@BSJUV)K0/SSYT4#+8/.(D]:5N/?E2L]XQ\+U +MB!=[PI0#*Z9+'H^*.?*K]P5SB=BS0>'!R,J/K(M5"`*X8=DV^P()6H>VY?!O +M7K1_+A<?Y#P*P\[*N)]ASX8R=3[+5<S.VTK::@H5J7[JR7W[7M3XN@).,4JR +MG./6GS94+R8$\I^LU#79[^^58*BRHS_JA\J/U0RW/[1><L7I0:AQJH29QKN4 +MB?)/A[IE2#!@FWHPRBQ:@AR8A9A'QC>+LK:0S[Z7[QL9N)-3+\ML["^G^0P/ +ML779F-@K\&@8(R`[A<D9H%,;!=%/]>M_=RH$0&X7YWE+H!VQ&+!&JG`,`^3/ +M<J[NDS:$AR;;M,W+H?3";,"!B^2QJ/7&32F>9'NN`/B/^^5236X<=MQ@@A.? +M/9#4KGA''N8#]L>R)?XC3:W'X6!T/R,B]/:VCBNO]QBQTG/$.#'W5G>GK`.] +M:#M8E;<,TK@ZG-#O$4,.0IGUF%:.=J3+K-@YTF!U/MR]B!;$`CX^>;N=@Y_J +M3,E06>9YNIP7T3AH6L'S`\^ZQ(:T=9`U4?I<NX#K,GV_+KXEDHC:'$4SB#!< +M[U`1DK<8\(&TYN*XV"6Y+7F&)7#WS+I,7G!8HUV'1#U4C@?B-'^QK:E%2@*) +M`^,14,-]P73IKZ.>9C@`21Q(GZJPJ?/<!_RUN>HZ'`H<Z:<<_11\)UTO*)/Q +M`."@(H$6PE(Q4TG_/*,17$&B4*T&;2/Z;;G#1>VN="4""H[2632OU?<1[,1] +M:S&7@WP(O,`>A2@X%J>+FX=Z"-6I]C/:\AOYQY_BI)>V*AAI/_7\NDUET$.7 +M4CA&H-/#+8M@5S_\'VGU-$]`5[K%[D)"J4]@Y(Z+^B():3]2C7:S&Y[A%3>> +M/Q>")<,+8XM'K7G)\//G+V\7O>*_YA:XFN:?JC\6-\Y;$R`0C!<*TLE<NR0) +MC+OH=)LJ//X8L]S9W-&=)`<MMJ)O%G(+X)^EHMT7HN.B:U,##!9S&I[#.OST +M$+5=?CHN`23(5?$C:UDD.D:[D(O*]]T7"6#-,WB-E1%/K^$45TU)!H9*'T5X +M7]D8SBTFQST(62N-$LIBQG+^T;'KC_FIW(PQ0B4%`@G(WS"_<D%QV\R$T.+P +M'+=:\RVUX$#D/&G4O$1XI3HN<Q;!]1(_GJ"A`*[$=CB+N,5"A-*3]T3,ZOA- +M73'9+S4%3H710DPQ>`TBN`;JRXL%I31V\?_\W94AQ&P.`@$650.:SMI4Q5WK +M\V'-4[BK_4\3N.%.DOJ'>J1K@J9&D2*=N/9!!1D2A1=V.6JD'D(/S>F?HJ]5 +MY1!=(KU]K=4NL@=K@%9/=+I-);U+X(S0(]'X'YHP=0^Y[%K[@C2S=,0:3QGK +MOQ9+[\LLD[7_-:+58YZ8?)HE@(8B@;@9)]T*8Y^!QI])LSY\?7C3KZU@N?B, +MOAMWCKU!E/?)[=3B"+[X8)\86CW@5\"XN"O4P^G<^ODPGPM-3B*R)-1"DW#< +MK^Y>Q%_>2-X%<H-7WJ&1GU^2C'^Y"&L4SG%V=P`]?TTL`<D6%(_TB7KMZR_" +MMP9CIJ(_!3W?ZE\X"$1])MQNB%*.^L1VZ$]);F`$4;;-'[DC7A[]B76TT>^; +M]ACGB/)=C4D,HGRW5SB"9D/Q"ZK%3"0D:Z/8D)#BR;EP*U!&'X,.G_`HZAL/ +M!9>0Z,:!<#7_@L^8/9MW[5YR[B5QY]LLE.2:JV=SS-M=B04;BZ!_9D\].G>+ +M;X7(`<UV1.#7H.&&$E@8$U#[!;MH/J#C*L3!B%\PN`^Y\#)+Z]7XI?2MM;:I +M&GL0>X'(#G!S)=T&5U7L!4-\2-.FEO;)[`.)V@"<["'C8^!.;?9B%KLTGP2@ +M)JZ7-$EO_`V4X^!?,]!!2J6]1.T%1H^*!%L;]4(6>'8$L3TS8-FX,U:`>6>1 +M:%,OY#TLBE7WL]!,DS:]M=L+L%04'M][2V4R7W>P;+$\U3?4HSWF6(N3\2L< +MYW!`+^##2[C7(1F]DY=M\"XD,.Z"O0Y8=;6OI2F+<OQ%2%-N;<`B(/^6././ +MO6B/4PZ@0F[JV%#=.+?P?%ABZX=^%0RD!7C6S$7Q+T'Z99WDMCW5AJL1=I*J +MXU/$#L(Z#?6*S4=`+?AV6SZ<N:3!;N,`P*W<*QP=`RFX%%2_]3U6Q=<[OB#\ +MF:YWK0'YS*\V:B#R%8"N$<7D$F'/\WI!XW*B&YYX7N@!+C87:>[.!=+3C^/8 +M^"PXG#2"OR#]QD(5'1K\U.WBW7FD4\M?G'K8&\]9.CY$7^9:XJAUD/5.X^8% +M(2]DNI]!:J=,8PW+?0/A&:1B]'6:]^RE!PH\8B8C*A7Z(D^=)?=V*D/#$R?J +MZ=>X&WH]V[8OSHQS4(:<\CPK<NV&MX='+/&QV_-><\JW\KD-Q9#>3"\UG197 +MU/Z9]NIZ^&VNM;'@1+39SNK$(ZPM:B[4+LUSAQ]2A%(I(N$S6*V%#W^_^8^? +M>72L'>+5NJL/A>BLVYZ%Y2WN]/.#(A"YP$\X#9+]760.8>%T76@D.^"'?]/5 +M\CL&RF?M[J8@=(5YBSGW?A).@(]9&%41Z58)*1;Y(.&^#Y$HL/`MX2(!-PJL +M60,,*B7R-5C1X8_J.K:A;U4NDD>G$^K/]$V0R[1RV5@"6\;BP:"S%3/,A"*: +M46JK&CL<Z)@R!BY=B?BE14V+X[@QA!$.<CZZU56GS"8RJJ#RU"'[0)7XS/<9 +M)9N$7%*2^O8JR-O&<T+N$W#X81+[1)W\%,EPK6F>;=&IV*(8:`7WW26ML!,K +M@-4;Z3@.AP*O(I5@[H<ERP&K>M(RN!:Z?5Q216_@.#4;#6`\0_Z=E9(2L&I] +MQ6]/3#K\91B3`T;JFNM)3VIA-/O2:8*L=Z/B8[!B>%'R<-,=\?2"+TSGK.MM +M74S[L]\K/:J0$J+J%&PSI6(MKU-!X0"*J?D').(X<@5R]M54-<UJS[4`ELYP +M_5B+#;@7)^&,S6IAC;S;8F^G",`D/<?!@NYNUDX$/6O,6P##:U'>VF.$9=NE +M#``+3*&0H+](S\/GW]'HP0Y9@VK`R`)[.@D5^#(D6=0!\2!O^D2C64K&$&.L +M%)D?_WQ+`PPDT$3:XIP!J&64]QSD)N"_P#XJX>;=H:-O<NO6U8-GKOZ#0%W= +MKOA`%H2\6/.8QFJ44^9ZG08:-.X_$RR$/E6F+CA6P,]N^PS0N2Z<]76'!TE_ +MDSR/W0I(=.FJU(WK77W],U>C@M?%0DXZ5-H]<[3ET5,.MG8Z40A`9E^SWK.P +MZ!:`C*`=(ECHHV)$,I>Q`3UUYGM^K!11?.(-"Q[**'=?8)G,$I<$*F(Z.M## +M3_P>T^XMYY%L$!Q@^,<ZEMWB&$<3^%52(L!2?UHUH8;WF-CPRV+3=![^S<S> +M?QH+S>%@GF/@W52=3UG0V\!B\(\3EK/_N!'3FZ^M?[:_Y)/\7D1Q^QT:<X_7 +MY*[W\NQY0XA@)SM/_#;MT81Z+4QRJ.J;1'$UJDG8*?*""X/)M2/&CEVCN1O; +MKGY>^.$+>WY9>!UI]5/(-.>$4'74<*Y<UDEPI2-*AS9S&$]\<%F>W\7U?M%U +M9>GR15R_9*+]/)@W*0X(HPSI^=90NQ?A.3?M5?M2NV3>%U%(5"WHP8;G?WS; +ME_>$B-ZM]@X6S.&BSD`A]PB!#E-[(AWC8-<'[?=O*F_(ZN=T/@38\4>DNL,3 +MP.#@7*"ZT*Q\DJ).Y\*RXX@HS)<OF2:F.+W8\,0!'E-:Z-#48JY]P8`-YI\( +MU092M:=9;`_\IP$B\;GGTCY;,X=V7Y>7IG#M:X54,2T$](L3I?0[R2EEIX*1 +M]0'"G#::)GQR*BA!KYL*%U2E/VNK0@0F!#RD-B4T-D@9[Q8UA]L.4WP^@CJO +M@Z[RM<D#,!3^4A]D48*!3YG31I)=*?_Z>0M'!\`R0$L^HM!U9FV1[K$6+N(^ +ME"T-3!-8$EUJ[5(&&Z68#B'A0K/'`O>^XMNQBDAK-96.*Z%5TPW^ZB^2%89: +M2!)2\@N8EGWA$`3'9MGDTO+=I>$G@Y]!3"_^BN3B^-`VC=?`+K&->O!$7;8@ +MEVL<4O]B+\_J073.X=_(H@#<9_A-AZV*TBG$%D5T'=1$34-$(>*MA1'UIKAU +M>V5@J5MT^?7:$G"2&_"<DC0DWG]A!F`+K687Z+;]#/_+[KBDDT<6A%<F2>U& +M>!T#EG?A#@+5D*Q<9^#+Q&:72SKR.$_1CV[+WJP&B8^YYA'XRU)81UL1-?3: +M7D475BQ:LPSO]-1A+FC)]'1`7(ACIU@&8X/"IE=A/W/_;R3(.W.59H/;G/#) +M"`<MIX&RIV.W2()J[4BZ^_M`MM)1WQ4-['FUP'6"/)V'2RTAVQU-D)$UK6G, +M$]5:7ZV=YAX%N-9;.J=5N4V%CJ)N2,27%S*7-S0!B?Y;.N!I;E/:391$&J*4 +MF;`*^A9?YMDU(9UNA.'M*PV>5ECH'KX0H58)9&9GCFHT@@L5D(M+*5CI6"'? +M:04N(9ZV=FA@B0,)7'I.,+A?PLC1%C9)R8>L&;F*BWSX1&ZD=Q<\VVK;8R7/ +M+QHF_THPH3L^PV3Z-"&L5N^^/PH3&:8408OLT`P97SY\`(F`)Y>$=+:#5`H: +ML]A*\J+*%80QGIJ`.DGP3V/.FDNDADI!TR&`_B34Q^`5KDC]2ON%8WN_VLZE +MZ0I:#_/WXPGZ95Y#J"3SW=:K,!ZBN)W::P0H11D;49JG#Q)R,<A8/!<]WFA2 +MY$]6K0$4[['=I8YVR12K]3DRMU>L%U]9*3E4@+"/;N-W1M43'YK=X)0D=)`N +MAY"5XUU@PSZUZG3SSEN0D>YO401[3SZ019`F[<.'3<MG_T@1PVCI^E!&4\5F +M#V*"^T@$@VZAH(`DT`_>:>W^J*(9>&>493@<KWVA:,GGC%X9WIK/.R$S&9JX +M$N#'6W2;JP!C<N'RD\>9LS-<\%)^A0UI`"&8BI[EOP?CDK'YR2;0>E.C9BD\ +M;P%#WX$#]_2'.Q!M=$Y$H<&VWR8I*7FB;X.B!ZU>)IZK>!&8`KI]`%_\7=B/ +M"DO*XNRLR=:RFSS/J.1Z,A,WPW+[S*P7W4Q'Q=LY-50GFJ-U.8R)K"-^0RK` +M`:S+35D92F`E3F'-E@7^V&>T.9UM5>.7.=IL:<AL?+N3DOE*,-;G`/[@+;VX +M(52/BO:+NY/R$)Y96([[':1IV^!Z.[3PLVC%.,I!_3:!-(.P5D0<9*Y8@7\` +M7^7.(;PF(.J_>9ZV2L0U60C2HG4<$6VJ3MLZ5@VE2R%EZ_."OATI)%K^'>+. +MLS;R'\H1I`(!%;.HF<[S=Y#64;&;3[C0=U@KV*L\7Q1;LD+5HG8`/2E!E42< +M,`&F:"76B^1@<MVD'*9#8`(`;5$<B5E[]7GD:OV-%,8+I(FIS]WB#<\C]9R# +M:\?6>S%I;2.(JRHG*!UC94>?DTF?^%'>\"N>T?I,?<G9-,'$BBA5*-P.0:Q2 +M$:90B@D6Y;=##\OY+..BP#G*[/U+"ZK:10<$H0)-:XH$B&C+!F\MI(&D8F&* +M'?6=UQ5:6J-VP0Z+_'K'M!JYW9(/EHGT-MU.*,AI"$5/M#R"G=H?[ZX?'Z\- +M_R^>$8JDQBT,`HCJT.)PU_=N=$\H@]/PV[B)T*6D4M3#G,0%]#D(<E-O/`8) +MRZ2/%Q[T!-4T+,CL=GCF1VQ8RQ#(J[3.GH,*`UL=C?#0*H7V$+$Q+SW"[N%3 +MPO-`S2'$/^$S)-5M2+IC%]G"!(OA7:2JB#IQ`6>(4KR"^8!A3JI,RR)G/DCZ +M.6LXCS*R2YX?B6KU=H]GVUHC55<E4&,%H/TO-^G?HW86P8AZ.7W_FHN,XQJ: +MD@0!6[;6%S&CUYD'[3_NB#;&BQ10[:P=SVU5X&A:0]%\GB3VB`[HPMKWX="4 +M@'GDU+M,O$(Z\:,6#UL"P.`116<_PC$9LVF-UE%NB("*P#@BE]0,W:;+MF_A +M]="06*;`F#*_T-HQ)K*WMZO5HWPJ.-U42@<8H*+!C/MM+M-6;MSD=Z!V3=FD +M\0_FVV6,"D`@67KX(3O4K@=-%=J-L]2D?-`W2_?$`&?(_?,H\LE[?F*N"9Q4 +M8]1LM\I^ZY"GN]UPN;JQC4\.69?CQD!PW5%<^)&6M-!T'%"`+.1H?K%7.4!M +MC*Z:T?G*]I$H[-!=C#A`HG.QD84+3(;/J1T8"6YNNDGG<%G!6MTO6-NU$YY@ +M-"7]#(Y[?FN@V!='4[,'P^ROAJC5,CHFD)5X2_6WQ77XJ?\(XO7+S5-POM!& +MN&,^Y^9-SN3`S@?8VB>P&&DTME1XY7K";Q=0X1@UEH&^OGM8I\H,D5UUMKDS +M[IAR69B)_$07HH*!XK86V7YR+'3K:B;W7%;OPEJ]]V[;MR%5\#!%>SY^C5(N +MQUSK/NB(L`HQ5]'^N"1/M(Q;Y^DPC1,V]_WE!V#*1U+A/>-BQ"+%W#M1;<_& +M05+38Q7.84SJ-Q>U=T<*K?[(/6JS2US7]9#T/`$I41[-O=3DK',4@!7D`NQ$ +MPX:@M-U'HC^CYBWQT9)A9J/B+;*RY0-#PZ8:%35(@^1[*BK]=)YUX(Y.)LS3 +MLGB%B]TB&"%]QW:'2.5''0>\MJDOA7R29)*ET?Q<JQ0=%:-`G7'B]%CCP+9+ +M>`_@L;A.>%ZXQ8S@G&9PH%*+*2F7ZC@?'@C5(*V,#.Y:%2-5YLQ,DS%44>FZ +MTX/^,ZG/FO"Q=+W#7>[LKH,:3$0_IB<]+;O+E!1/FDWY.9K/ZI=RKXL`1@-@ +M)TZ99+<#9^H]Q5M3.FN"_$IW60BC.!0K7^XIX7Z/^,H!WFLJP2$=^>>&$^IR +M$<_'1&9KC+/YVF>=6XQ"%R4^W<?>9^XM\]2#MX;Z4OYH/7;*I>;WZWS^+?_? +MS:'9,UN>@D;]Z;S3F*6T3XL9!VBFYL`WM_3?DKT<P$8'7^G2:#^:#U&V!.6_ +MC*$E=%4X;NH$.8N0?`7@Y#<`6-7D/1;M$QCEN`YN592;5U`GH%TY_$T6[C6@ +M6&`*7^(CARTGTO)(S]CM@YU&_.BKX(=XR%P6NMX?F-,6$XWSE6M:2IH/%_O! +MDCJ.>9'/A(VSHFZ&F1EB/XL[1&ZZ"W.-.T0!M..P[X%HS8<YWZDINJY3W;L] +M@X]`:J!..![3XCB=<K]`#8[P\[PGZX^&%SG._$0^V(#/&2W.'*?8QA`<H=>* +M8VH.*0S5;DC&4`$@?6-1\'"NLEB>&B[WJ9B,$>59R^II)Y.A0:CK$U['%?40 +M>W%W?Q]JA=7U8XR&V'0#)2'VBYMG=.TJ`86<?+QKCWP7MQU?B`TKKF&])V?J +M7!?N36M$V:;[S'M28G,EC]2`:/*"5"&:HGR_Q`!])N83'\=/'%6<V2:HT?]Y +M$$^TEF91=U*(:P3)0S?A559;N[80M/O8?/#^81KT,X]G3-5W+E0(;DP=OW&! +M]H:*&Z`H?Z0"F4]$G;S<NPUM@ITSOX."0YEGSB,^-;<X%6GN--&HXLG^RJ8. +M38!XOA'<8KEB_4GGTD=S=F5>?[(AWN\07%'])U%4/O;XD79E^RGGY4"N-]TP +M<:%UH!A*%Y1][QV.\G^R^])7W`6;8[<0VQ=)#6$^>;VZ%FG]0JP]/^!O7>-$ +M>JT'IJZR_`SMZ.JE'\S"\6\[5*+#&8LNAF,WKTH#9UGT66(9'EL'SW'!'NC! +MG_5\P>/\+]-5&DEE257OZKI0<K&PVF8Q+MTXK7$:5K&5/I/N_=>X<ZD^O%L> +M*&0ZYRY1976L-$C4-)R`7O9G7\*%`$O4BP3O)U&JU9@T!C9:S]-SM@>4F@B< +M-/Q%<[3!LJ[9ADY@A:H?'N?6ZL_M44`+C:5"(T35?P?`*T?0A(#WRMV>'XOJ +M[T"]0PSRTLAX3Q5#6YS<[']7U7$XMT@GTH\7H(4#0*HTBC-*#$H5R#\$/533 +M3)/D;8M[Q$!4<.!K'V28%GZL4>TBE<%#HME7TWQ=N@.1F"`DN2,[1>AO6#?- +MS3/6?XY+R9M=:[I:,7S7T`ESF;M/J]+/GIEC0A5KWDS+B\_XDOR>W\7=11%9 +M3!W7X0`SY#AC`$9+]-4??U,`M''KNKMZH-7#%XG''CN/`**GHV+^7NVBE!Z) +M9$\AI`JLH5V,4(U99MC4FJ$3+$ATRT$I=X`QI`>?M2MZ^=];?,$3PI)T=`R" +MZU@\"#`P.ZS,_<K%6$W]_^2GKDJX_!02JKGM)1#P6TTH=KZRAQU<DM^R&-DI +MA?$`\*TP@)>,QI\2'6-),5JRJ2_0QMDD2P:DM<+CPJ#`"M#3-Q3G4?#$U.Z7 +M:H"J*%(,8VV+C/G^TL'QC^ES$]SC0OY[321R,[\Q\9L,8&*39_@Q2-E<,U^! +MA1`FB5,'A]:*X''`*T4^T3HG/0(<S+,AD^(Q&!'"1BG\%H(HZ#.3])9[5`MY +M><E7L#GL7U=#1W;RT"6AF=CT<1LGGK`I47?$*ZJI5CER_)&]A;#,V>8FX(SY +MO2.C!4)4<Z,S8B0Q1T$5B\LUF^CWUB&-2'6LE,*E@[/,;[TAC0RNLEE6T>8; +MO(.</_@2>MV-UP85MX\YXE0NALK&1Q2FH5^6*5@OS!J@NKNQF*<=BXF+6U0& +MT81HCM]]@F;X>G6WNE7))T3`DO@&>,J9[++\RIY;Y'F<_`F>P/U/@";/)U37 +M'*NMBJDHW![?T\M)>MD1M?3#=+#3/7U8J["@K4FVYI#4+9N!SR)]<@_3UW?) +M50VGV*$)E\KCH)+&[\&SU5>GLSM297KHJ@QD*PL,+2G!;114RU>-#H_^+A?U +ME2*>S#75SJXDT"Q@D-K)6LRKQ1)^CJAV>N,H9W4F,21H@E5D4.@0!0D/%6DC +M1FI[<-&WO<15CRH2]B3Z\1A[C/YERL-$:]C6N*`!F^B%Z3N25Y/WH]OPLMVJ +MAU=WS3/FN?X]==Z"CR2(S7H719)10T@-^]L\75-KZHS9&,].=^7>%<`L=%YT +MGT<RH*0OY\*MYJ&!90W4#=?!T5A</5]X3\L*!D`,!'\'2&:5/D`JT>7O:>LF +M!O/`/K'C'20JQ']C6JWL7%8S5:24AS.2$..O5**GGR^.,]*/`B[<R[=2H/XI +MI8P,D`/=AR!Q'R@4EO=&[2S$E[_.P!C6NS[':03N\+'`S5]V4#J(;FQQFK"H +M52;5)U=T!5O5Q+9`G8AK>7E3_B[-)2&R.\/E1Q9,^#UMYW.AG)H@_#`YL.*? +M9QJ#?9UJ&[U<E(/0R]],WD;>*'$?02WUMZM!?=B:JC#J!O(LUIQ@:DNRO(`P +M4'>&'.*%_N\IF@&VN]\F+#]K[TGA\]^4<AUR"7!^P6U/UX,#H,63222I&/A[ +M9Y_SOG0D?EF()<A63Z]VAC_\%3.S]<0,N.&S%1BVS;YTOPQ"=P[*R1<_2%89 +M#QBN[?E;R8+=F^SB#LN\F5_U:5AYDNRAN)([L+[2V-R^;"W+Y-*68J.SKU-\ +MV9!X>$+_+$$*[EF`6RS1?*T>0(Q>F@(*XB!7VG_AGK10S.$0L^-B<MI.-"=" +M%%_MQ!53%M>)'18!\-#/,O7C6&O"<!$-7^&UZ._W>?2)B!P':9=)S;1;P_86 +M'EVRBT3H-4T+LLR;=Q\D/(O9&)?S%XX\'EQM\87$_X]R._CH5MX]P.I<:0Z* +MG_MBJQZ?)AR.CL&=-1)8DINN<6R6Y-U7":&^ME9Z-B&$E3H)2>0C<;UL5%(9 +M%40?>[=__98.AZ@,U]],%WG7!'UQ^[Y4_2R@=ZUB:7'"!VHCPCVA>))K\&+" +MIUPU'=!.L"F)K5(Z.3HF%/GY;L*T_1\#O.W\KW%/J`D\EI009;9DHMCTVS=T +MK4J+%72SWOBZ]RWF\\+6[XE53-]D)F0CA>)>UH+3ORUM:%E[2''=FG!&!*CN +ML\.2^$L-<UF_YYOEQL@P;!+8?MI[CV,QS$TXB3.8*+R7Z1&E!&[_C9*><4CK +MR&73D>8#QL9@%!RA%Z,^]NB(6&]J6Z37E@E]_X,\?,Q_B8V1X$#\TM%/M$>K +MD_$KAZU2I%Y4LIEX),R5+FX[E9%.@C%+P:'2\LA!P<'9YG_>D%\<3FWF]-V; +M3Q6QCW?O1O3'>(:[NL0&(O(=!>]6H[N\'#@:"54.74)G7L>@@V&`.Y053T(G +M\:+'%YN2Y07'WD2G\F!B$;$P;*0N%G=YH`_+A>Z9.2_![PF::R7,H$K#KF"9 +M8FLOV&];45(C!D<TC9H%3O@U]'65BDMQQRC>1@.E&@%A6UE9SK?#9N!!8N8: +MWDJ;DL4A"AB1-YUG2=N3W%N?[Y7D6?[YCF?NHPH:BB86Q.:5F!4S+>S#E[EK +MWRHU<^?I7S/7X1=5Z>0MDRU$N/>3#**&;KHAO2$A4:&JPDKP_UQ@-E(ER<D1 +M./D=8_1DY"SC6[KBG]='RVR#$RE+S!F$\Z>=.+YF/38N!@6^7ZJKN3VE;RX] +M9;5ZI>U5$CJ',]D,^W=9NB9T/\F[HQ-FM@2[H:4@-!)>)ID];_[\S>?192&J +MB+XCAGG9O(*I$50CG#3LCC0IL6K#H!5R%=ROW542:>C\44/EU\6XI1L0?9/C +MWV,S:?O+_EVFD+%-Q[.@O@YG0L;2KP!N*\E_M<)\E1($@TVOW#+=D1^-E-<? +M2@#@9%5,>(.@*MBCGJN9,^2V@-?SM^=_`VKG2HI8"&QF!_>O?]R[*H)@0EV, +M!I%4,Z*,%'@MJ9.O`']I3N*4CMCY^R[5>8\KE//K/P7\G=52UN;-%<ER-=/4 +M':KSSA)>T)CI`4#[<81B[[0W:KRGQE$;5P^A]DKBQC3;8/PNV,EO$GKYS7#+ +M\T"?51![U&;`VN2L@[SXIIE>D^)`^E\*%]M9-""R>42OXZ2BWNW7'*#VT`F! +MVNX*<T!E=J"20M$*,N[_Q%0(,(VB.T<GY<6_,)L09^44V;I+N3"6AP&JJ6O9 +M*X!9"57.O$:"EO<EVCCZS:XF+OTXL=\#T;8-IU!':N_6Z@DENB+,>_TTF9:W +MH$M;4H4BJ)34;+CZ-;"D,Z2M>/\1LT\Q[B$`AYX>O93<^6SW7WU2HXH;SFPW +MKNZ\"S!+&9M@-QHAD:H4KE?C9#?ZEKY#XE&1]W]R9=1;+8L2FW(.$EU*&(Z' +MNL7I6&M#&+"RDC:_N3[@3NVU,X],5HBKO-);B[=JR6ZX<L'?&`L0KPU/O[KB +M0'M/(O5?7H`2`I>!K%+G4X#XAL1GDPLD<&+_M,<UW*$LS'((-([T1W5H"0JI +MW6E[-AW-WQ\.;-?,\L)%^CAYB4^C`R!TNWC7A-<>XTS%;`MJ,0DB^:E!%)VE +MX55.SZEB5^]&G)XA>I'D*&)*4L\$&BEGP=2PW-;I<S[?:S;$MJZK8XH\TV1R +MTJ4;74O[FP.\?E+5G_+/I2U=H<Q.3JE8H%].ULCW"R6;Z)3.Y2*9-:J4!#%Q +M/T656H_=L=\PO!+DJD%GU")SKQ1=DW9K34^;GZP>(G>I$0H>,LERN./A5V]0 +M)30`@MFW5'L^7;:/=FFY"X,H_VF9T-]XC\K5>RDM#F$.OC!9OU1<'CD-GR7" +M7\Y\6[!1%%D@<H*N29`Y7F6\P#N5UWBCR2HC?;`9HHT%R;\:04JO&COQ&QLD +M%3S[T)O4>8:LT$5C3L;^:[EN[FOMNJ3U^1.0ZO\R9C+#;1%M$7@;$3,J_K68 +M`+&"_YOO^&)8:(JY^4;`0"%#^QYO6/UE3BD31Q1",EK1;^CY*'BFS"J!?1'Q +M(R."[4),E',N]XJ'.R[&,:R(&[WSR</#E#'#8ZZ$-IA1U$SK>F>UIR\/G\9I +M0:`FYZ.3>)W^I3$7G>@9O%CXXE6%/)NV^^3AQ#.76U>A5C^MBP[KSS!W"KA^ +M=S=Q!9:;%4"/@YJ0VRJT2QFM)*(>Q:M#HY.@+`(I/D)GK<MRP`_+-=(+06M8 +M9,TR`/8_?O4?_P49..%AF5*)A)K%29!*=_C\I&/@N0(M%5Y:5A`VX8(S+M`[ +M6]ZRCRW&4GMI,&]W0"XO<5+/IO(CL^C3<->XX(W@_7]1W@P:#Z0>%W:R5?T\ +M6O#X$I9XZSR(*ZWA5B1X`BS/.)*'0;_T"99Y?['$(:O'>_8D,4R07:R43J8Z +MJEID:,(_=_W`[N.<2R`PWKO[34XM\*YI^V9;<"-O!!WD%S=O-^)(YUB%3"7D +MOS50MRZ1BX"&BNFG?8PBK%9W+[=BP")EC^R-/#6'Q`%RF6?6^*[+NK&.6>OA +M&=E4?I(%[81S,7D\%^B'V50%IR65PS35;8'\2;Z7@.%_HTM<_?9Z&].*I^Q^ +M=XYM(_W;P%JR9,?;]&'1*:)S7B;2F4Y?B@#<B4#`&\NE3\2LXZ;82G/N^U09 +M([3A?P&`\^5E&8*_R$S?M($VUV'\=N$CY/@34KUHN_0FO5R(#??)ZRW3AQ*= +M96%8OK&&Q^T4M;]X``.>*=ZF(<HN.G?P:?DI^452P%?K25*BK,W4[T(8K=GE +M#+V75PQ>S?:<[^M5_S8:PM\V/B]V9ZJPGVRS[ETA-+`["Z"YX\-F/_1TT<CK +M#<SL)Y-A'^:$390H*G/F.#C08$>XR0WABKZK+G$IAH!0`;(<0[[:!OO(;S>F +MIMX'Z\XY+?^?_'P/K5^&&4FW\T!!&J=0=)=)Y5/8W8H^6J,((OK5`$7M>4?@ +M8E>'(JBOAY?/NH7F3+=V2.[[;Q2EK"\1TN*,4,LF>K:`[M.;P;T19B?2#IOQ +M1ZW]U,7)MCZ/>17-<L4PE%&]'QLUUZG!IAPF:*%2JW:WCP5\F]ORL<M_E;_V +M']<&R,1M^Z$#D38\&5*QN6`SGBB''-MH.#DOJ6DLG\8IG%;OD/;J.NW8,$;D +M)`SRO!,!H\$7]]'R#'!;6N^"<H#@&&!@U91P<`!!^C1N</<$\?#+!O^#OFZ9 +ML=Q\Q(3GTH(,8EITP0=X@9.<X#&Q>*TVB>8QC$BI8-H`G;4]`>ZL(XM;(/\_ +MZ;%$-(6IX9JA!Y@9LK0>.Q_]Y*V:A9:[VLBDS95UH+:&!@NT'<\1A)^%\<MS +MQTEJ>?J02'VSH*RATPFL57>6P1`[6%_MT2C?>4OJPJ4ZUK.=5%%URH\U>Q%: +MZ-/,6:)I[,A;?.P<BE^V\W^_:='UPHOU(%XPS=O<I,1B;.45XH<="'=UZCP7 +M1FR%</BPJ[]MYEF3^&6[7@=$)3"C'::TVU:7M!85HMM''\`@G=,ZD/&A:NPN +MN[U7L_5,1WOS`XU%A*<(Z).E([-?#&S39[D:`.W_7*9_('^%?LY;*;>Q[VVQ +MJ'Q)VB$)><-'9`J+4A+5XMF6L8A3XXU@$Y).2(_881^-4*:[;V5@S'OY_X\7 +M((UPDTFB]-O88_:P<T9PW..<%,9.*MNTF050PVP$B[`P+0=CE^'3-*A%E19$ +MGV;&RHJ)MMPC)QQ)4*H4-7F"YZ;&U@C"#.+%F_/X0Y6LIW`PU>R/J@!K5Y,\ +MUUJ5;(,CIZ&]P0P8J"B<YP"9C5M]UC1OKRW\D.`S3\_K.'HQ"H+9\/8#NORJ +MK98LACG9+_QTU$NM9WW@IPEWK6;'`8YP$FCFY()2S9\BS:&$J7,#`\MDH2GP +MS*25?@JQZ2OD[#:]SAEW+YZ8;A4OYH+3%ANIBGDUN$W'WSL_']H%RQ7?)PF8 +MDK>//*"S$ZUU3J'0^FXO$0$(6,")I13(^@_+.1SESP\A"Z5$\IWFVDL/J/,P +M(%#USBQ:(T"2@`70?D,1JW#%#HV/.WF.6HZLH0G1?73C>18!4/"-E"%(O-V_ +M362-O-5`]'\N"HUU17I\KF)^6N567&43K>K(YP:1-6Z0;GU%Y1&XV@S0([GL +M8*C,/PUR6>[@M^5%GR(EH-(!D5`B3@\I8').TNW7%09^W"(??,](-]^^3:"U +MTL8QA.&?/<"<B>C6_>HB[Z$CM#D;O>(>MEJ]DMB"XMV8K0"TQX!#9Y?-4NWD +M-,M`T?UR*\O'<;11*>P>R%[DM,*V%IQ=_CK</^5+Z,XJ9G^=0Z(!W#2P(M_L +M,F;\^V#)+`\&:SR1&2(A8M7'?AOJK2PDD-Z[/;ZL/4Z#$8?$4PU@A;X/;(X' +M\3%R1=Z1?5@RF.GOT_[:DK)+ON=K3T8%MSLS/X%K%`"6AAPG47(QJ)G10,K7 +MK)OI=[5#$<&R?_6$WBH1Z-/:L^)$V",?GRQ3?G+M5_&`/"9S,ZDZY:TQ(OM. +M+S1.)(UW<6P>.4,V-UYDOK*Q[@8'_$@!V*RY!\BL`6^2<TAJZ1S$)(S?\:,0 +M69$2D%KIL!B%HPO4^S!-+>]"SBJWT%6&$;V$9'BH1_^:H`RE]($FQ#:JM&<D +MO]GIX8?$"L1.H-Z8Z-27=0Z`((@;7L45JSW89)_YNB>+#GG7)[$.E>2B\L9H +M:T?#-1_SIU![*QJ$#NKOAW!:?'`P1@BVM0`4Z1[KNL:VO8MQGR)"]13J;$?T +M9C,OR,@WJ0T`/1C>[D07DP::;+0C[66L89!:H4HN9Y\L)B'ZB>SKRG-@9U=< +M];8[?9E(=#MX,W4MW8"+DNDG!I+-S-=9/>X)SUA/7IXU]G@[`*1J+V0>)$NH +MZ]8S]KU)>3XWFCM70EM!-90?F6X=!G$N=`-BZ`/0FI0/</S,)&/"0[-E490U +MZ*L)V2>A@2MG,U+(*7<?L2<IBDM;VQ4ZS+C?OIU@[BN_Q?28\=^XGA0H-F#( +MFYH1H@@!;&90$K]/?.:.]7^-DC;"'H1,:S7W+!";'<GCXCA\W#E/312)>BNU +ML^&$I"CG,5M`=HS:`WP:$K`,$%=?M:N[1`N)"X^.PW41_96&`(#V!G=1,$.@ +M4M@RLS'Y-,E=M2Z]0?^F<:<W,S?2-EK:DY$W4JL)K%#0BE?4Q_54&Z;0(N^1 +MD@=B8<HK.,4JR)GM.9U=$GC8V=';3WRK>.LLJ65>8B,<I5XTK/T<0&'SY"1O +M36Q7H#R[:?5SFPL1Z.B%>R\X**<B)06%O`@EZTF5Q\N1A7Z5V**`5D&;^W79 +MVD*TJT@D^)#"RY*)VDW#KLPF1Z,C+^8Q_?[-CLBY4I7DM_,PO4$`8D*N9^J\ +MA110LGLFFKS!_H0)!<<W,X]<^E1I@A%K#>8A0WLTASEAD&N;3^L*^GM?L6G& +M5BN[^0`>DX\`1C3T.R&NY,25!FK@>V?DLQ':S:3<D1*"GKS5%8?D.`5_(+T7 +M693_7QE6:KN:JT<&0`Q:.49K^_9A`XI0F$H,\.D'02?]Z(8D\#P4[DPEJ@&: +M89_FGE4(!7\`9*'GJ40EX@-AV/-8\AEY>B]-*GT)%8$S[16H_PDC[C(ER'L= +M9R"9]E-80-99].@ZF:;*L=ZR:=-QY[.\7,Q8$<M\=)^+/W`RD\`%0G0Y)E9= +MQVI_FM_SJ\S6JA5Q0TD8*]OX!V4AQ](SA]7H]?!3P(E$)0.D]:1J[!BOJ'^L +MWT.<JM*R\\=O8#43%7/OPJDEN'[WAM^Q/PGN2'T/A?/56)TK5BW!*DF+N_WB +M1[AC";-G'K$U'2N6SI)C]TL<V#-@W%,P-9CJNEU.>[`:>L%WF&GAW&B,Q0)3 +M>?"=[Q'R,"Z."O6_9PO,W3.EC%+V_2A]@L0K@G6EL(@0A-'5A#/N-S+\19*K +MV[\<><ET7T>H)0`3U.#J_OZ!Y:W*9U%A@3W9V7*][:,O(1<L83JVK26A+@C^ +M5JX^V\=)M_A!F]`98\+4.MSX_CZI^MUP\O(>)LS!3DR6``*`[%WBE"WUY(9W +M97BB3(LJV,*&RJYN-?AX)LD6JRI@UL)P7=^F`>TI%-0$PY.7V+?<\?KP?Z#$ +M)3-@\QSQ`=;SXZJS&N0BR_XG0OTTZT#PSTKM1PS`<FC5T-(`R0OF4%*HP,2\ +MZ'E^9T5=?`2J+J-[*_#(REK!]X',*[IXR:_9^:8U-F/YMU7C2:I,'BJ;C]5S +MS%TB"-E(QA-UCCKK?S^X@>'I.\O6%%+FJA+,6M:@7H%B&+8[H+S2-^#F>LW% +MK/2\A#4NB4>8#W6##NZY5$6C8KDU(Z=N,A^6GU$W$`L9TBS`H:>UC?)V[=(% +MM^DSR>7BU/TR.\NO&X=-X-%N580_ZNGZSGH'^L>B\#!]4GB]*#(#X*[9RE@1 +MFV%FD(6NS)DRLSZO)%C5[#)I09+3!\[ZI[O`&6;X2'T45_5:G/F+GE_.J=`? +MM9CR\IA429MA)O!O3T&6[X5(;VHB(Q_!?\WN5_<W'(*YMOFT4J4H7\2S<)^1 +MS)L;ZJ%`_L^22_>$J0+[^Q!LXP2NCNV)`7_:CW@04T;'V$<`W("6-E:M>\>< +MM.UOF7?_$)R?"SH4=/P]$YC/2&?3'[3:<T@W7B.>H2*A1"*_*H'K:T*JG(4^ +M4IP*=-<3X@GN3)VP5H=W)GVAM52F*'UWJ$E]M1T;6NII6:^*HT)U3]VGSB2# +MPG_9*\:)S)VHR?%\B_C/3XV8G!\S!]$V@[1\'?JN[U%I5G9O8E_>N!K),I0> +M<C<YQN@_O*@!0;U65T6(UF==76+X/=E>N-G."9(HZ$0@#W17FUS=SX-&,JY3 +M;[KZ.I_5/0PR(SPW)R'B.B"#5=JZ0M5^F503UE_\L*Z33S!T%K.E<E5*7>'G +MW@:LFNMOD;YH,2\H&'I.^BZ890U8;0I\&7>)^8VF^I,;WCVM@8YGXPX*RKYN +M%PS[%@Y?!D7CD*$%X-5]N+C]C!.;A)5\&(]6%;6`=ANX")5G.("\"/%?"'&\ +M#*<#1HLY!ZABW1%KELD0I4:.SE]?Q8=#W4.:+`NSQP.$$]W]XPN>@^;!IREC +M;++EMTW!<B.EX2HR*H8OL]L'@=+9D]Y:!+9DNS^9FY,8\3W:#@.3DB>;Z"J8 +MA7UV?8F3WIM65OYU<.N\00I9UJV"3W!73.F6>@+4.F3C3>HN&`O7EU[]K,3Z +M[^>JO$,>(F.`U(409#%96+H3*`/31&?GE[POI"*#AWKK;6$>5V!.2AL[6Y1K +M5:)AI"/!B38T9I9G$_%7IQ#I4*6O?IDM`!N^<+E[NP%)]X.S5@NC:3`([!H< +M/>[]:P-IYP3N->$UJ9\*G@/*Y_?S=XT''<*^I&O":7-5EX6!A6.B%J0X&\_P +M@+D@?[+9K.^6XMC`5(K7'GJ&XOG',NZ]L`U:Z>/CZ'K'L=R:UB_&&2D^[SS% +MPV;%IOAC6ZD%3'(B+'EWTU7KVLS%[=>-6I]Y>OLF**Q?')?BD\U9K]2/-&J: +M`\GD6M2X:XPW9#7O7154:1*=)@2L;6;%RRF\8VQ=D+T%6<'NQN"A6+&UV?[U +MLQE`Q!D*/"NXAP=L1?2>_?L+R\>-!=0>K17@W*7,&;^10&QEZV#]#Z.&);4Z +M\JB1.%?4@[MQ%A[&5,^D,HS]-9?+Q?C=&B4#,V)&L$US!FRW7851SL%1^7E1 +MG*/*>M#8'!*5B+=.??"#1D,9ON.-$>G.C@S5Q>HC+Y9@[S/#M,DXO]'RW(G2 +M)/13+)9I_ORFYUY\>VU)6]:N@GLBLLP0&NE@+D.=58Q+;86\,5`<1&?J'@.U +M>,`8&T)\BSL*!QK'/\,=:77\/BN1;Y[@7NVY8$[)W6)RC3:9!G,G]:X(?=NM +MK:'/9"WPIV`&GM=>FZ0W\,'X!H40(-L$S\D(X83%EYQ8^EN>"N=T8]_&1/3^ +M,*N'(P'Z:!R.O+AR5G(=J<J0(3[A520K&[:L4R,>S!?P)@[/I/7ZMZ.##>[+ +MO62C_%KT'0W1(UZ"C@[U2T>09`;_&;$?`:ZVNG+1U@7:+8>M84UIA14M6V?` +MZ&]R[3@"=$F&_I.N53($\]7K)S,GFH6Z@+`-\405SL8+ILOQS!KV2D*-@=F7 +MLB?\:/*K9=K=J7S/FU/:9OCH&E2DMKV<M!820?^M_OZUD'I3SK%7%7@4B36\ +M]UOY/;"5&`A,0S`QYWNKF[TN6E`E*=@()20J=!!/C_6<%IC>Q$!S@@02@KCT +MM9INGX,6=O1E,'*'J.QHZ\I(FM"TYPLXWI0"OC_57C1/&Y`XH=8X+BOE++TL +M--\HT3"'6CCK[E'^45-/0IMT<9M@UK!JGLI#5AI2O8)L(D!HOZ[?*4?@F;,( +M4K6AUBKZ0&A)K+\<#L/.XLDMC4G3V0S18%PDOF-D6X^:.,?/ZNB%1.9]O5EW +MJ.^`6;VSV!#(#*D>FL)#A@[=AEJ&=YC2&9Z#YJZ9U6ZIT.@J-752KA^!Q',0 +M9J=_Q$]Y`KM4J_TVL\52)0:%<):9XKI/:$!_?BS=S6(N+9)=L:7]M7P:??_. +MM:++[Y.SL#DL*V`/9JT""HTSGRIE+Z)]?V<3]0,U$JT9>&7))FG`ZX-2]YR6 +M%@E\Y)@+Z(L'3*GBR#X[ABT[K#.&%J'W++`PM27)S#XB[9&X62_:S1G\;@H4 +M]?^`&D])0`3TM(9/?NT%JN&Y]-?Y7'<`G%&123%#KHLMKZH>JJ4[#$-:3/]E +M/H%I:/2CB8C-GXR=9)UR!05DA(H/O/,K.TE..J52]?EY64_T%.'HD<*C\*_! +M6@7FZ`VB\!-%I98U0Y\\T#!/5MQX4;N\"XR4S\]2RN5SX\H]H._@6RRUL<#A +MD1F(8;FP.:R;E):5Y-;IV^(CPA+MD%1AU@/A;[T/)K+[OJHJ3YJG";-46U&6 +MZB_;4_MIB\9Q8BC]]]\9ABD&^LJXLH$6(XB!S\.\LYCGT'??6#F_%YF?UA;+ +MF<")F;S.@*9B"A)R\=9!K"$1B''5:%W7623CXU1FC4`(OH^TPF\[&<.T04;4 +M-C&EU46G["0YS@6[?XD7M\`\%G,C:$EUAOHK07"/!`W1(NF+S*#V[2OYK22^ +MN9D?##GU_+#ZBV4V(EA;/"4-Y$QY+)%%63W%&.5^O"Y5G0(;NWCP%%8\THB@ +M!(QK]G(G2G[R#T%;=34NH-S'3UI[XX.9SS59%F+@;YM%KD&);'JFZP`!2V3M +MSM"U`U'85I:85LW%ESTM4W'-.S:M^MCFHROUXKC76FSMW"DD]V8LR8/Z)LME +M3B<6%=0J57^\WZP4<_WLZ-7W"QUCLMR$@<H)^E%*WK,,OVE9V9^`"QA,/[-8 +MSS!7/Q7L03]6*&+A<L6AOR'OUC$DO;7ZU$JCSP.1CD!%H"<!DH;')%^107]M +MT2D.]_*#PU0I<AE-XHZ149@9F)(A)$3<LHK_#!\*'?C.8^/NU</\(Z7`I_]= +MW`BPC/>8HAG2]EF_"#<Q:HKE;F,8!4MK"?IK!"HI%,\Z=ZPJ]CM@E"PU[[^Y +MBT.[!VTP&FP"7,'DUM?A,<#:'&?UF##N&#&]Z5WNVP\;*,>.U>JT"2<^XJ/Q +M/4K&QXV`Y(NI'(HW9L?@?6YZXXHJJW)Y[2/\[=,T"\:B80(P5=';MBHPQ-+= +M(N#X:8T47X\(#H9WNM;'SLZ;T2Q6]L#\;12FN8Y((3-,2K&QNP<<PRN:2]=- +MH4X!2VP0,K/-$GC,JHYDO5B<\"[O3%D/<0P%=_+"IN>$OL`'S.L75=S.[KP( +M%PS-^FP3DD]#+X<*^]`K`IW2YB1ONJ4/O?(@I=VN7>P0'Y'ZOSY0QKTO?`7: +MW\\=WTOHM>"[0_-_8/ERE&;J<=AE;_-.7Z\@]K+]W]\2DU\1S3J]"FV,<BZ! +M&;Z(?"D;(8=01F#`;.R=I6L)=7RQSF8?0M?XJ1Y^?VYYBQ7CTXJYVR@YXY:H +M37ZLI9D-X7I[(5_=YE9^=A$BWTM/#M,O<7T?L)WSR8.ENR.EEEE:(=3_8N`D +MHSL&K]/Q_?(\NW=_YU1KS9TRW%+.O3AU_1[$53Y7,,?:H6F79BGZZW!+"CS= +M^>PZ+LZ1/&*0=8VT[*=[&268)N4"\-$,>0N-XMX4H=XR931.4G=VY?4<>+Y; +MQOUB7++/ON'ZMDI0R_7C/S(5M%_-@X4<T)^KW!.B9B5E`?'L/(?ZN=!F3=R7 +M@IB'V%;\#^H&2U$HR)YYZ@,DHF+[13!#'5Z'WP*V(C?&`EB?J.;B^?[BV"MW +M4.S>3^BM7$]IS.GNS];-NZ7U\[N2_(<_/Y,QOXYSXX7^`\ILU=<:_^3;>'Q\ +M\=VG]G2]WAC)'J')W0H[##(&B(3WRVAT!:>?!JT`%U+=@N3D7BA]^+4X>.'( +M"@9YJ%P#`[*3YQ-:VUR0"ZXE>EP[;?#<$'=&_Z2G8O?`Z(,F/HAGU=SSNL!P +M^KQBS3*$)PD:E\"RKWQC\"%5'5QNL5ISR?W.VUB;Y1F]O7:TR&VD)QQJ_P.) +M"A!A&V(*Y+!8C7CU><++*B0MY`(!4*%H:Z<0\5P7TFZ1831?\I(28';J'^"8 +MS9QMTP=84=<Z=*#DP/G_]FC@]8B"2CYOY:C4L_?N(*;[WV1)\U=,82A,LI=2 +MK@T>^0<T9V57FMXO^\4(J)MNE5D26>X<.;#(6P%7*6":63-!G[H*"19DY-(= +MP\157G$?:?88*-X%OV-FN"=$5XHW]TVU&L1;29I`>/#IK42(7PN&;[(Z(M6Q +M<W-^62_G3@)X8@^0*XT3CVP"A_A.$%R5<3/@W*M\O3B4',:9OCCGT;G1MJTB +M)F64A?,8S!DSI=O>LO,[1^A0@,>]KE,AM,G%_L@H,,>K'WVV!=D*TM[:DPUL +MWO;4E(;^V%A#Q>-_#R'HX6&MS:LNTG15+0INMO3#TI[D+`%B1124/NI.%,#^ +M_0I4<?3,T=@O4X2/(JLIOR(,-QZBCD0EMSJBU%_8.T7M5MNL`"Q#6*>K?"%] +M9MS:)*33%A/]FDX6I[-E0`V%]U<EQFCHE'S=N@-6>>>"A`77&W/&?7R2LH16 +M@GY9`TOH8U$H&TF-OG77LF,%$,CSQ[*T]Y0E&F%9`[SZLAW^EF-M/PI</,I[ +MKHIK_5I<'](DP$]*[C_X&^`7$IA^B;OFV06@'K#'<UX[1*>Y;NT?P;-TE5IV +M!,Z_ATB/&(1YSC^MYKPRVEY3#46O9KD[92N"O:`WXB=_?*1[UPG\![)YQEMS +MNT2JS%2?G5EK1VY0W!E^S._I.02%V*2BMTG5YV2TSTZ"A5(<+F^DYBZA0CJ0 +M^K-@?H2[%9N!:1HP4N2=(N8$R0D[:^O-EIS/_LZ%C(YVJJ*N<>][C,,1;%<< +M$I'TQSS*0K]GCDG(DS)M'ZVCB"=2'O,Z@C.3TGG8K=L(\GI3K*R0RPP)RX_W +MK'_;NXN]7!B&AI=ZCAP\H$L3CF2-QPN2#'VQL.-H&9Z#>/UK^;'V!@G6DOLM +M61P/]7Q*=R1T9RFBW/6DX-^<,S,9ET>^W[O`NJ)PT]1L]]\%X+.8XA5\V&(P +M_FV?%V1:5PD&J6J5MU/;DAK>A`?5H!?7R%4"K]9P8X]Y\M/KW8473<)+N/M^ +M%YVN?:(WT;(8CFEWX7<[C>![`SYVA>J+D2+#_8*,Q6[`LO^Y*7M(1=-KUMM' +MAZW@"3ZLA.<%;5NM=NA].2]/3W?35.0E$M:<,AYIJ3S5I+XKR(E8+B]U-+$' +M\BP[VRI9N[PL.-AVZEJJ*VUF2>/!`IY9,;O_F2FE58$,3-$3(+Y>"<,?G<5B +MQ3,:XT*6O'WCPM%(CD]GR%#$4`52Y+)&8/NRO-U3Z#D\JJMD?/;G/HD]H<Y9 +M(U_8M4^;7^_M\U7$*,#N/1E09-C=T$23M/X"=DUB>P3?%<O%49OW:-NN$^^* +M1TR*_?(437."Z3;JWQ)#!#T:_N3_J[K',L@7@:+WK/KW0\;(:5KZ'49+DIQB +M@,)?I@"I4E?J<;P8[S*%>3D1R+8$"(B0G>9>ZZP,OMWJ#">1SN*V2[/_[?P[ +MNJ0+89+4[*D@HM"('["KMNM-S0*]ZLUUQ,J:P-T3P)I*'?")&>LTWB>Y(,AQ +M=T`7!-PQ0F=A*_0TYP::6FF<IGK4]932.\HW83KOG`"`KRU7_]'?JR;/"<J[ +M-@(W8`^]9R91=1Z]X1?("H2'<STFT#XY5VGT=0Z\.-GB)<(2,2^_V<_9*KV1 +MY(<[ZM[S@NJ7)216J5PE:W!KZ7L.6]P[Q#!<@6]_$C$;5"-;X'!7>!\CY4ZV +M,XD2;R`E04'#Q*`N"-&(B<%@PRPJ^3\.0:S!2<H"?*RW\[#0M!Q![E0QN&SE +M`BX`;CW+NPXH^YK*O8!UK[N(GMV*1WN'\=Z8=(.)(1[6U9DQ@_YR/R-M_2X\ +M4E!4PC;5*L*UM7CV0')+<ZQ8[1OC]Z-*H(N#X/NBDQ+:5^_SF\(+AGT6%/"D +M20_^+PP%#A2AK52ZE@E_8830;QE?0'@RA7;.2KYDAS7J\OJ&=`&BWJ.']5ZU +MY083N=0]B?EI."#SH3M/JB,POI>X+;'W!*F@NB"P==H<L?&RUJP"M33#R3)( +MF?ZH1]I5Z/27=.?^.8-_\Z@#ONDJC)8,"Q>X+S>O>%KEN+[F\EG>TO?FUS1& +MM%>5R"9P_/`>!B^!B<E?@/D(.S*7]8;0/A-UOW_[./;T.;!FJI3W6G440#,I +MLFQBO%#BHYA]WD'M`9%*$5X0'-/[@`82)_MX#"IJ2T7!\4,@K.39\6(#C$ZD +MK=2(?/G/_B#GW/U).3L\0.=L:5#8EW9\T6G]A<A;VL\Y71%V4!(XO`.A*P%Y +M%>-FK-T;#1[\4,<\&Q`G4]@V!45._I@%-+Z*RY*FN:SJJK#8C&"P%CHO;,&[ +M$BD6UT!]_"59F?`4B1P.PU@O-[5+IW>G'0KGX>C`9!<J//<)"O&!E34#;^(B +M7;]T&9@8?TU\9P4O8C?GX)F-L->$K3@OWW,_4*_8%(/::9E]+H]_CO.,%/NF +M8]K_N$I_D3F$;<P(L]?0DD)=>'[;S0]C^Y/C93MP.?>EX*EA&T%3)<I"K\)Q +MO',`98\EB3F4W&%&'\,OK8V[8%L242'\0@U.AD>]R%W56H3U%D$"6III,RPZ +M`[4W\!8)>TA7N?C\8^@;@.SSN0D$*@#?WF`!!R3EN"QB$8#/7D3:W!;5_)>& +M@<ZE+#H#G7C'A'QV]#OP[R2Y#?'.P6,_.9EB)C":EF&TA2,SO7Y!&+45QHP> +ML&=&P([*<4S2,=2%VGJK13!&K>P)5N"TG@<;3!+09J6/+MV<%;_RA)JFD>NA +M6"Q;/[]Q[W;_I[DRWM6WPM5`T]Q+Z)H9-#.FLZ:W=YV:/.`=9?#Q.43:^X8( +MD>1#[SC7)>Y#(G!:<6!!<W)%R_RCK;'PB]K0=_4\"04LQKCF!:"&NM#AJ^// +M7U\)CP\?<U0".F[5M;WDFA'!78D,IR,5K`?FNF-3+H+P+C$HTV6E+/+GC3/H +M60\1$2](G<ITZXD2H-7O'A$ONY;7XE7XDBR><$4.^25;/ZAW250PJN/&N15Y +M9=9-IY2G*-^6@OU<DO;N8[Z][PW<I\;[V.Y5WE;"6R!/XCLJKHV!RB^/?F*C +M'Q6^_E"XF6"P4&BLLW1?Q#ST>O!0#FU)>LU@/9R3&E*E@==_YSX:7.*U1V6[ +MC:2P?^N/_":OCFC$=80H%ZZC6W"\PG@*P!E?<[@1A_O@JGP7(3S)=YDA8L<% +M4'Z;TDQ'8":0-^38$`B1OK,E\\(P%FX9J:C1<.+"4+MB*=N*T):+I_-7N*/M +M/I.GG)8M0IOS26!X]J+8F7`-,-8V#%GZ?P4E!N$58V:EC7/=DG`\FM!I>IYX +MC2B88S)9<K)A0:6L@/4WHG0J3?Q1='!M5LVA!0,H'7!V="`*;UKE@D&G)20_ +M&=HTTL3@54;'LDP^1)\YQVM1&814-T](&B)PT4;W^M&]]L1*F=P.?$A'H)YB +M`BP"8U+@7(POW9EJ/*M,'IQJQ(]L/)O_CV_W@FOOUSQT[4J_F%P2D)(-":[H +MI2D6]:,/TXP@YT*X_W@T?#HU1NNV51+Y.O&J#-@A.YDQ3=F7>>@[=IZ("]E8 +MQEIGA]G1;_H6P@V7[C;Z@R9';FL?V$!\,]#K&5)*_T_#ZZF^/W2Q\7YSHT)< +MY`Q?@35^;)_+1DC/X>V6*7A*-U*RY#-4UR#TR$"BM$!W2W?"+IM"]/L0(]O2 +M'ZN=J'=]Y6?U8?2LWS"$W%L]M@2=&GOT^(YLZB>T$UW#Y>$M6BU.-YH#B_L3 +MQ`Q$BOJZ-`!EYMKIEBYL1I]@,D'2G04?6SEGT5I7'3PNP$,35S[U073M$0EA +M?\DJ8`S-IY5L'?=$('H2E;"U3`(PBABUD/C)^K$:XL(O6>AZO6XC$"I\Q#(' +M@,R0*.4\Q.J9+("[CD.W=\FCL`J+JN49`T>8QFF\8T]WJW^0JT1Y)Q%1`_GX +M,'A<;VH#EWP:,:@:N_^WQ8D`GCZGSET;[YS_0>]G-C/SH0DE<FJU/'BQ?O]H +M]2_JJS=?^BB9Y.ZRGG_@G=4=<,/#P>BU-2N<HC:I3F2M_!2/48SLSU^>>BB: +M&2F??-EL+IW\7\:W3J=[*S-Y8L?N#/]<`FNLJA942^UJ+^E__O*T9K6(=`O= +M2A(L>SH.1)J[]Y%7AH"UAC;1U0#5P^\J<*1]$>F6E_)E#^PBG4]@?_$+7-A/ +M6=8'ZUD+V7BN.$B7Z3,C#:(*'CKW;!LFQ-G%+_8J?L;;TX;351<DHO4$!5%4 +M(KHAB<;5,DD'TQM"BK8B*X/?&N-2GR9V(AM^GN;P0'06+D=XQWP"3!#D.15/ +MX(VC#_9P^YO`A!W0Q)`J/!U#ZGP2LSD5N*.#=K(M@GXCS+<")]EU#Q#\7-&& +MMTC9'MX;"9/RYF'WDYWP@HTX1VRF[BVS1RQ*XV+A34K][JN\"42+SP#RIOC& +M/'T"XD),Q[%G_AQ@1U5)CFQY9Z/;0??;'R[1LODBW5;A;ZJ4KA<#_]0U5L3E +MHJ&[3D.;KI@+CAMGP&0@)<QXB6NM".3%W;&M)_G^-)ZG/H;BICL6,:[^BM-: +MQNAIK3O$/^5#ZA,2<TWM8/][C311])LIVFI"G@JM\LWWTR`_9WNGV/YCC%YJ +MX%8*=L!N!N1>QIZX'!16J_N?&X/!!]PZNW;(_"5PM920`,O23;+[Y&R@,9,S +M4E6`DIO6R<D^U$G/ZI3+X\&/.:!9`ZX4,\*7EWF'?I,'PP<>>"Y]6*E92M5V +M`!GH\).Y.A0/I/CR.Z0NF+T5X76;V83&0KG<EP1S$_H'[]SV6A"FZ6U%IBUG +M%YL(%SN@V*G<!8-@G.V+=TJD6,3+1O^"=Y8.=G#C2TNZ@I2/[T'UKCT_G@LD +M[$IWHV>S/YS\)#@^"A<8^79`5[3@Y<2M?Z6G[9_[ZH<RVAFQ\!,G^12EEO0* +M?"-K?W.@Q`?<A8=J"S*LPZMK"OFQ/G(5IV1\K#)>O0V3>!JCR!$^=@SYW&0N +MK)()8`97C(SN?\H[Y<#&]>M/!<K>[HP]A>HY5R+]!AJ4XX_@`KSG03_<-]): +MM'ZZAI%8;0UWH.T-<H?-^;$M01QM=E30^,R[]O7I07M/%7YUF9!%'G<4_G/H +M0I0JZ^<-IH1N\%T7]FO[JU(WA2!3]@2N=F<@JS.O;GOHH'X/Y\?!.V]:]%B] +MN#6I^IM@1-(;X32'HL\/AN\HV$7L"0TN7HV^I!$]JV_AK1^G>T<)524JXJBG +M(<N3F1974J49].D38TW=1X37C''H,S_@.Q`\CV-C\0*Q)066JW1%P9#7J@=G +M$4<V9,,Q>+G5AAJC/AIW@)7;9(HU5(#V=M.`&ZNG.Q&J?!]6DF&>%)@[.ED0 +M*VWITQTY.\/FX=G#0L.-B!$KJN-AE##AUE5E:VGRHB:VRN[[Q^1,4(.!M[HA +MIZ\Q^R/S1S.RK4X"AMI`CVUXF4U^I[W,37J#;9FN:Q",(D26%:27I4-5@`_? +M#;E++(O@V6$?OM<!BR+"_KY\BI;*4&+PE'&Z!33B]R7RWI&L,E<O>Q*[62Y8 +M.WFEE6D/Q,NG_A6XKF220D>=X>L3_0KPTCD)E59]<Y"7KT+]\NDZ8+Q<C+)! +M:\A<.P*<LANCMXQ=+[%-F$'OI'CNW2=[;ZY$&KWAW9V#!UG5<_TXW3Y+7[*8 +MW+/XW;(7MXT6!U(H*O2@;\!6G?,V'U@_SQP8VPI=:DD$#VH/@G%)$7G^%-U_ +M%<%]S[-8A$>6>8Y5[RUK)T"0FZ95+Y'0.!TJQL1T7.P*N;>EX@$21E@;+J8" +M$RU%W3819;5;6A.<Z0W.79;G;3K`N8QN)F?LK0LIJDX0$>YA(_[G4UJJJ9]G +M&K`/_*+0R3&^L4>5=;>&+H.9[[)6H5Q&,<"Q_=*9,>Y\TG[,SCY5P?9:;G^> +MQ/]:$>3U]&OQ5!,28AA!,*;7WGTG87*A72=`3UOAMDEV/N!36JR!G(RX4=50 +ME*DP3?FE6/BZF5YDLD0Q$K%3^1O<M?)!99`I>CCA\M^UC'F/=4$3M)D>CA5X +MT,Y*P/G\N(A2!'36-%2(B2,8DCA\B>Y4Y@F4D,%1O9*CRM5D;H([\3PX#UW\ +M0M9IDD#`WB&;5$,A0[X_\*/OD$6!%0LV8'$N7*`,2`YH'I@E;%9%CRI*X(/_ +M,;VP%$-1TY84G79ARX]3)]:&*(Q0CD'X('XJQFY/3FU6_P\SIQ]A&(C0VLPU +M4X]<!I7S1NE$)HB=T`P;6D!;NL;&@#="O4X:8FD?&3['SLI)20PMB>QJIYU` +MM5<571@'Z"$CV?)Z.:OF3\SQB<:_9LZ<=.V4=]9_LMVQI312B3A[>VCM(."7 +MP0?&.^YC((8`L`E`$?5U4@*K/_%4K*C&`0+6Q6O?Z3N,GC6\\L<\W[(Y^G^2 +M.*,=_.7ODT3*VR+_;%;D^R'MM-,-L:2WAE"5\1EY:R*8C*ECK8L"W9JL:Y5$ +M%DDU=[%`=$N.^*Q59-:V8>$QY'\!_NNT<NR4*M&KYN]2;J=,A;82_%>!-<^R +MPVC-(<A!;M"\'#7!`C7FGL<W>Y"4DJD*P0+-0C;"=PO7(8`!:-])I^ASX$/O +MV:&`IB*BCU?PKZCF]2GHTU`W4/R5R[S@UMHV]=S>]MH@,?FG"?`1%S4YZ/'X +M&T"$BML6!2Q':@=P^L1)N*$!3Y1I<8?0-EL],W=Q2V"4,N4]RJ<MU^K2Z!#7 +M.6H1\#ZA(`.=P[H7PT0#I+2[U9/A#<<0K4_JO^M`TEU2=QHCMN@37RDO#AX` +M?S5"V1IH![]%8U!#4]HG^W7L6UT6<=LGF5'V_<*0Z\'$*Z`33O]1&I^2M^T@ +M)Z1)X66$PG@2BL#^7[T3"W%X*H)9W^8I3F1J3S:NZ1*P_*LND8:R;B,Q`5N[ +MAFE#5OG@EW%P)7)X[#*?]T9FM*H>..O([?C:Y;E4\\N:HZS-$PIS"B9L';E> +M<&&R>YENM/MV&X@_+5J%\H41>2P7U//>3H6FA1M\OOGJA-<7-%45Y72O79;^ +MWP>]K@8`$.STBA,PML`VI,=F]Q/`^KCYRNGVL!UC5$!0*-"D\%ZI;-N="PN2 +MLS`<0%47C3/R`)D3MX!/`V*VT(Q3(\O%&CF4>[D=66#MZ=!@C(%&W:)W9SZY +M7\%@P&</6"NS\ZAWRDTDN@5"4,3WC-L]2:(K\XCDRMOE,(_HYV4[7+L<O0;+ +MD=:S]I4KN/8HUL/[^=+!-HIA7'?LB#SIM^0!1L$Y@(R=;=7:C\#;Z1&U"<S8 +M-\=K>=GH=_E693CA`&(2WP&:J!R7J#L8SKH[.PC0*&:3$XN_4P3*_K(7V"#I +MQ\'6/^,"VH-(8%Y:'YWU,5PU!14WD!O!C5D3Y*##HX,G(3E#3[-(L&QV,Z*# +MJOV"+.Q2EV\6[_C8@T_U.TLLFW!/#%4!<RA@G\UR!(22`E2AY->_.2SU6PG, +MDO=H=%=.4!&?2\Z%E,E$<>DPG'I1BJ=MXZM<\*;>FI)55.O+#05QMK="0IYY +MMKFQV.;/3#>(L_D63Z'+>E:S)'[T7'UG&@1ODUD5UG=%M),4FZ=W6+HQS/=W +M\2XGQL'11C:MAG!?P0;[?MX0[#%#38FM\K:(+XS;!O[=8%2RI6,5>SSLZS7# +M15BV'\'_,YABW9N"'LAB&"QW1$RGUWX.>BA.Y>SG[]K\=^QMD]]!/9+SB[%R +MJGSM(]H*Q8Y7:]#IL,.$S^3O$S#*SEAX%J%M[3SG)G347O3OV'&V(">Z;P%- +M/T#5GY/'&G&KX\$S:I:*ABW907*+%(]1**?9.[@/R<ZQ<JOM<I2K(LN.)52: +MF#],8<[H]#:I@!*V.[UZSVPFP>]1Y)#'_L=!!N"U4CD*+:;S!;M8ZR1_SFL= +M'WD2K,,SF,GI4D$BH?+4ID.QP1YT,VMT&W-Z9VY"(Y+2H-9_1C7QTGXEM!F. +MN98.^8G<H3?P(Y#N<#%V.`25.I`BAU3EO-,N0YV_^^'AY+AE;33>3&->]]1) +MX$Z@3)?H/-&L,-7"&31BI7;(1[\3=[)2D(J(92#I/<]`^M1IK^">Y#"B;K"Y +M-0(J!S9IQ:D9-')..6024YPT+(SYFT:<KDWK%.I1&B'X)N,W7;@PF`'?V=\( +M88V=&+9\DI.H3$3AO?H.$X)GRK^S)B7MNWX<JLLK35)-(AZ.NWEGL([@,S34 +M`)%SH,*V\,<!/#L>Q63.GZ%S'.R?8B#U.0"`JM9GCR8S)7V]XK3@F6H5CP\Q +M`%EU3V9$E8Y/D4?,$E'->_VHV0S`Z5.WM!<-8XHB4K?98P!/4:_.VN*F8CQL +MG/>\[9C(FH!>\$=4O_N*>>Z;GX%CBF/6F4:K,R5C4<."G7S"[L6Y70#0>?/: +M)?*`PU>.W@DB_<R`9ME&?XO[-&K`6FRM3@*#_-L(U:Q=0L<Z*9^)M%-HE'/. +MAPXT6R2(:=YC_\!TD:3\3EJ>($%W4=CJ#^L!A61[P3<%,`FX+;GA3TCES?9R +M'H%.2IELHWZD*01GP(9H8LUG)9I`@!V;^7.H`2AFW&.9)0$..U//3<B3)KXR +M^@8AC]_MIA9;R7!JHOAR5"Y1WVX2W1D1@!\F3:Z,0AD&U)AS1+B[DM2VGV@I +MLS=VXP#-J.4PHL^O>GIJKS/@J)%'O-FZ\HUBKI<PX'-S']&4?2?KR$\D2GTJ +MU]$,3\CZ,2"VB"$]V#R<@C#-R_O5(D_X.LSIZY?4NDV.)=3=I4NP6DN.FN7" +MC_C;*+20P=1.[]LC^>GP\XAZBB?="%NK+D_TL<!#;4U2P;I+=VDPB.-B4.=E +M1KVP"(E1E]()5EZ7#,<:42\DTX0Q#_)/%[7[$8RE-GF;5\G@DRJAUE="7Q\* +M9W4ASXJ+VG0S1FTLRRV=4]Z(Q=`NZ[9''Q93$0?!IM]+:DP]A"/D;C(8IRKZ +M*EAX!>D-2T!0:AB5OS%R0-6K*"J).>.)SV)MJ1]JNSSVTP1Q,W`"3;[\350S +MFZ>C'6]SK8*3WU.A8*]>$-3SUKZZP!T^<*OXP\#XT4XL19G:U?530#38LQB% +M=;I-2YFHF!@`?T684N#AO2T!O:8DY+>ZA,G*P-;J*5,,G^;$'=W<MY&R7?Q# +M1^9PH=?G3=%-PSI_P,LB!"#,D3S,S%3^6UQ*SXQ]2KBA0B7LYG$;C09!LFV@ +MC4_74_:SL*)@?IXI^`")URH'<+#]T7G)$$K6YK2M2)1QCO]5WX\'@"<52JIX +MHO/;V/7XUP(Q+V(#"&LC/?";QFCQRYM6?9+;GS8EVO5+]^-'.H!,#ZM6JW;, +M"?XP-&S7SEI\&BW_O[?G5FBYMH5ZX^KH:,)GL@@J.SH2=ZZ(;4$=)O@]??>! +M8?T\IXR494UWR6.=\Y5W%B"7:,*6WT$B[_B)FO_T/ED.[.1$/MYA(/#B_M7. +MG8JN7>W>JGX.#T;9)-X`&]%E]]N;[K2T-15QSC[ONU_&1<!_W!B#.%-(SQ9X +MR4Y?UQ*<Y46]F:URF)'-_0HP.<N3+''K[D'P6)BGE%#ND/>Y0FJC7U6W#AH0 +M)?K%*"PTA,AX+2M\C(<"+D6J>(==P0OD;XCI2#Z(*R4'7O9QN@[@[GHT%YWE +M@D8TWHYW=DQ-03=)4#KHK@[M3;FZ8BF)[F.-M>;7=G5ET@*F16MA\Y";D)"4 +M^N>%Z!MYKV[\>HH*WK/HLYH0AW#]:L-67AK<BR_%`.%(-5/LHTTS@O4OG\5Z +M^O(?Z)XIS&N'\^F8$R;6BW"\Y2"2ZO..:)M'8RL=[90U8KQOD`[/!&].%,RJ +M)?NTPN1D2(0UG9B07R>(E;S#I\B=K8=#4U+TYL;Z=#F1-/IK0EX=K!QS`!]! +MGZ9O8OD9_6^@42EL^?Z_#2^,>S"L_HQXGCEL7-8Z3MB1%VEOZ:FEWT764[`C +M^IM>'>?9+K:GJ\'X'ID_1ZZ+4M8_2>_;5`&)W]=;#LS-3(I^"#@:9CBE\FI5 +M21&>]:"1/M:+*B-:W9-9ZH`T(N4Z7E"<9":"41#(@<6I!,594MAV'!-S,P?^ +MFGW*T#(UO404#2FGV_>U;2F!V0[U*#3,L!TVM,5`_;QH2F.B^-6COV?WZ-1M +M@TB(IP:-<0G<7B6E3"$/6X0IQ_M75GA9)K7,^FE&ASVVL<+HD<!L;W"^8?S- +MZE(H#JXW[\594F[;#J_#*XPOK((!TUY!X,DS#__F-[NNZ>&>++3?NF1[Z`Q8 +M*M7IL&PY+T``_LV'MKG>P,BKFGR%_#BQZ@?3;0QK5IQ5O+O9&.$K^C4S+))_ +MC@8[/!U'1<8+D<[D%HP&F7`ATZCI0:U--MWSO.%=3BFLB^IAKR#2:RC=9PP- +MTQ?U(BKN>_A=36O<(8$('LA9CC^ID`K^+PF^YB:Q0FIB`_#2RL1OYV)SNNZG +MJZY[AA.M&D%B`!E&V;L88"[8$#\KVA'.AN*$)3=D\BX=B5BA2RP%%K`7']$, +M<Q!;N-'"?7W9[WN,E*9BOM'(E-@C2+IK_N\R<_]U?R":NA#*7-PNCZOE>7/7 +MJAZR.1S=HY2]C5^@XQ<,T)KY>R$('E,(^)D,N3C5,MHCS*C,/10.."S>/+"M +MWH7@ME]LMGY,K#S&57!M-K)>73=!R`'P/07]7D?JQ;J,BRI"RS^)7^+?-IX9 +M<ZPFP5Z#TL3,1:E;@&%K_B-6Y<:\X0W;%;$GN[M_*G=`?CO"TL@<9[MB\OU- +M,"MLUYH:AK[=0!#<E'MRAOYUX6/ZWUS$](O[8IHVJDXO/1#`BZDF=`CK$MU3 +M)E`TSJT(8>,P%[+",AU&,2)?(+=B$1@9W`2O`]=WI2WC/N=6T:K4$`N@O1A$ +MT@V!'S\;KY-&1R/=U%3>YT59VBB[&?A(T:X@%1""(9-W2ROJL-69UIM(<DHH +M$%4FS2;J(QT#?95>LN.>+\C!Y#V.UK3MZM3FCR5><^5X=BI/`C>?306%'_M- +M9#@X7IA9:3<4RW'4-Z5YA#_4Y&,?;AJ#(:GM;3MNTO%@VY3X,.--1<5';O+X +MQS<$QP:ER36V422/.#(1$>_]DXC2%<B0(LRB+^EK]1(\QJ*GX"'RUHDTSBL/ +M<;0@F]S+(_>6,<X,-S4R<%[-'0VW:Y2=]+T%+HN"]ZO(OK#-RI[FA^4\+U5' +MP[9)%"A?FK"G!TN[B,HS3V;9*,C9].0PBA5T!FY^5YYG)&W1GF%&RG?/\0O( +M5/*)75S@SB.$N0'/KBT/.?5+5!!;U^#4-5U_T6Y`L(/:QRH16#DS;OWG18\] +M'A!3"1-@'$(A`365=B\TX.5!TBP&U#`3NL7W?C5`LRD=CR@7E>2;F3U&/3C6 +MG/P)1BN'@<CP>&2<$D3>I+OL#(*@X-?<GZSS+/[(?JR(-O;`=Q?*@+XP.'+U +MULNL&4UMC9^J&(;7]8D-J^MG/[62557M)U;]T9JQ&M\I5S*U?%!1B#/G0!LE +M9)MM<M*WQJBAJ68B-A`3]"Q/5OQKRU,BU(Q`NIJ[ZA9RPM)-QQ+X.-IW[K9# +M545><'W+G=W'#BK[PN3(XF(YTC2N^=EG4X+!O3@%LIF@7E`/-L[^,!"A=F$X +MQ?:UV#O5#3T)G5=$H1]KB^H<\^]`"=$@@0@F/>0J48O+:+,0*6Z65(*;'%HU +MDB4,?"^&[F2_F$NG=0X\V<)5>@DO3P[.K<:TODZ44>Z/W0P^_:3+\5N.P/MS +M(*:_^]#=GCPR4U9]F+=6(FOUMF<5Y1=*)5;K7$]=/47KI$"3?,VWC<F^\RN* +M`]2[4.3G;67/]79	K/:Q7#/U`V%LT%D.K;,UIPRP;NK[>_3MS:@!28&$'V +M2$DB5LQD>UQ\6YN)V+\@ZE_*PJ,$=5"9:@:T".$.[)+-',G3`\LRG"N]U2:[ +M;&]C%F%EY2ZNB)/:+P8'$RM!@9@[>`5$#_H!T/-\_.@X\PEGIM8#!$/[/3.[ +M6@BYD0BRH4^NU67'-9#+0CED,JW_ZAW.(Q#[AC4(_<=P:-_Q*HWLV(TSPE%W +MC*;ZN!4+,7\`KZ`\_F"CG/[*)(ZA#QS+#)6*7YB6)/*O]_L+LDUP%CAMW@GA +M`T_/1DFR'.-</\D7.S.<B^&>G3U));X=/M]14=V:/]05_V<J0+)VG!J,#6HJ +M=?F^\BG\=^,MD6QOYRVK6,J-NGF`NO[JOX+:E1\."T4A7(!7KC);*J1MN5J/ +MD79)]("@ZC7(9`6&,`U[&]P*8#I\LD'8,A!YB*16),<&D$<\N8A0$9987G)Z +M0@O,J9"FU%$0!]27?)C:BBM/O$:<S"XX0;JMM5:EA?YN(@>)C-1N]DPR/-4Y +MBM1#R'9A[,:!\_>X-6N]XJ.C"AP\J>:"KFEK4VJL3#K5B))M'WU>2I*I>Y`] +M:650M\F_<W)WNT<=X3I^X'FR#^=1@:E-*HW1\0&0;U@OGJ;Z?4I7V`871;K3 +M>*D'[M+AK%W*(JP$+PSD$2P:3P>K8UPGD^/N9PT7757'S;%.'$\X;YC"+%T6 +MRM;[U1.4L86C`*B]:2N>R%,_'W#]B?&+K8Z?:_+'\(!3M<UF1X9&4A%E(90M +MC@`ORF_<SHRYR50IQBRKH2K"D;]6==$V_8>XLBR-F/SU^2M+%KK_!M<F`D"Y +MJ<0[IL'5!QI(UC[,(E;B'K$.F'A+%PU$&Y-]]EL!N.\0D'"43R88!"E5C?HW +M_&RGV3LV9F+@!MS1)-M-?E0\&JRI_?H#O?K/M4_)DL0B#=]9F(K-C@";E%YQ +MI3"B*+=%Q0:7K3QQW..+`TLBGJ*]4I>=@7QHIWD=?Y05"%U"YE(G`1$)0OA6 +MA6VJB.^5).E/7+!.@-PAI9!I/9)WD):"9,NH6L&)1S,3]:OH."?X$$C7H6>C +M%\A_/T]RY^/GU5NLL3]GQ<7_&P"?#1.R3M8<P'/59M@TB'&>5`E%TRENWJW. +M\96^6;I,-@WI%NG=E_!'"!)C>&--C&S>%'/\CM,DOO*U3*HUYW*&`PN?#F$] +M_):Y6`JN:,H2=J\^E8?(%SM,$.+6G)"1!$?KHKTQ:A2^P[S45DQ*J(ZH%G)2 +MS$97R6Y,O<J=]]B<K/:R6':0B>!JD)7+KPC"1B7W2DF[;`3%^CW^#:D[<;WP +MFV*6THUZ*0.4UD`7.332L_K"?22RJ$[B(?>53.]M.8Y1ZY1P7'=:^2\1Z=J$ +M00!6MI(TCP2()$POV<3F)C^#J'FQN"(=HM6>@7,6?8!0MNR@%Z1UM^`?L!R3 +M,B/1!293T_)7<#/1!*TN?B]R2AN,.DTYFU;S.V+6_$?,J/JVK]!Z2'?B=*B1 +MN!]]@R,325R!S!GYPA^2WB=HKBW8H$!:]71UOZ-'9'9K-)\%^+)X4?=*<3:$ +M^:#]!"0++DRZ*/>IM+G!$5DVX"O(UXW4J=O%NL+K42M])!/3ND&;'PX[9[K; +M]!V2YCH-DCMO+SH).9O;C'D)R^&ML0[2W&:D0+OS+&R,&5C01/[,D[UC<$+# +MC+V`K^<!UP-$%[>C\YG=+GWICX.^N#4>5>/X?5?//^6L"^\)H%]LDO-LL<;W +M>1VP5FPZ<7?PT4EM'=X(:]F3\.>@/S4#I(<O#[]V8(Y/K)G;OS?P;)LP8(_Q +M8ZFZ1%NDDEJ.J@=+2'4'J+%49ZJ,229;,O2"\;!W`[D-),A6*%DLP<4SZZCR +M-A_O(LDA#[)LWY55T=*/C26XFV3+UE=P.8+?XP:![%0B`V7:=)<`DA7W]X6> +M"THWXB[8!6>.4J9R*KI'5K_W*:])N$.5=%Y)A`%S-=$G@_;48X@NAEK1GL\@ +M/7CAWJ7&G'$`I8YJ!Q"*47C!O0K\1*@=RWO4)%L8H^_K#QJCC(L3VG(`IHV3 +M2,6I9^5IIA.E[$N,@00OQYVH<(7<K3U'.J$.A%%919TS7L<9$RTXKZ'E&TM- +MC"H20$PNG)-?-C[?K:@8(`9G*.T(<!264*^R?!?#(`C?:`EI$#1UUX0I(L\N +M7\M]]_VZ6P]PT/P!.&AZ[P1^FS#-\0FB)KR!]RLG1U`V1W*X$1KIB22BYJ$T +M6C%8(;;Q+??'-<1\]N&4=14"LQ^-I&"R&J_8+60;`PFNXT?C,"I7-FLI,H?4 +M%N5AL6$9\*_'*GMI+,G"BU@P>4CE8:(VY6I:GE,T=0`!:WM?)H)-+CVEIGE8 +M6-B@)1;]2_CWAC0)S9SS&&$Z__39J8A<M=Y(10/K?*;HK,75,F:>6U`!R\#J +MF/9C.?57E7&][IL_:L*2K?7-4ZB'H:/@)L0-5[!7N`R%0&\=8Q%VKA2.9<5E +M"X,49FK\+Z&R,A0Z5>^0+OR9<D#6)GH=:'D]E>3,&[8M**-V=Q0.!IQ_)!3Z +M>G:;S5<AGTK5_W85.5)6&44?_8S_J1-$/#IZ+.Y7&__OE\JJ#H?M:3355)!T +M[R%@H8`<</0QLXG>6.+Y3MKTW>,$9LF#5L]&>=H7)F&7A-X*S@5EUB*?FT'1 +MNCJJ+PDSTD^C`JG0`#002NA?0OFCU<\8=T6E^D<8/*C+[/4"8"`UDVI!,"U@ +M^H4G:R#@.-."&2ZTABSDB]'Q6&\N^#5WXD)%LM`/TR@H<^;];2>R7@PLW*+Q +M4L49AG&(%KP"(;V6D?9YH<JP(I.I6"Q%))_O515HCP$)FQ3@2VKA/T&!GX&5 +M=BW#-T@W66/PICI>/$:U-;[$8Q[WEB4WP=0+DY&0OM`]W4%?BW]MA54]>%2( +M4*/-^(]2IL2/6H?YB]62CO5[6RV<#YQ!19N9-`A`"P>P#5HP]_]=,L(CZCGG +M%=R.9TU!95+!F,PI@CM/KRH.%P=/EY;Q+T;>,$S>;2^%8J%)K%ES:3*.DTW/ +M/%[(U9:NY`D`,U<6P)U?-A7EI6]\Y\L22;\0Q#-=A"SR1??@ZTV#J$O'W4\2 +MO*``A@E!C`FNUW7\6VFU`_O&9RXR'M<7YK_!=`AGV933_(L=6=;F7(V+=,T! +M[UL>@,\B^N[<P[&@9PP'7VKLQ25.]!U(("Q*RBIZ^[.-P=Z<[LYY>_X"1<=] +MO?.?@Y:+JCP0[$@GC'?9Z(0SV%F&W\Z.=&=S$Z!67Q/@=`7Z%ZJ^+YW9_1A% +M`3GE6FX"@;QEVF^+ZZ8B\4<&H0_\H\^DT+;4MX%+0'YVE`LW*-RZ1Q%E>"\8 +MF;%=N!K&6`&`=!,_S$4>XO&5IQ5342VBE[#MY^C_H,D6FNO)\P&);`6&9?:! +M,*(U-G&.)*4G#-XV*WM#S/H5A8V`5'GO?(-^4CVXJ9JK'_*.(?(GQVT!S=5; +MV1L:WQ>[;2DT-@72[\DX/EKO&R6"7>E/(EOAZ4*TA+&&\K02\H4TN!P";1I5 +M"E55!L:7I-*44EFH3?_)[57X@`WKR;/Q^DHW3GG-^A)1>K"W74O,K+5#;#)2 +MC3EHWQ":P-VO-#-K4$GGIT+2Y%FL90K+ICFCP62NY-H=9KS%6/1K)<`FA@66 +M9)%YW\F6(&:H+\4R8P0,'*PGD5)@:5-R>`JV8,$<HYZPU<]#H,#U8%Y,41BM +MLDM'=>S-GL_5U&+,>>-Q07EO^1,]3[:O:23)H&%8["S>1W_)"Y<-N:AFBV:O +MA*7=7"Y/4=BLGFP)F-#JE(IZ*[0/#-=![S7KOU6EK=Y^6$]!:2)Q7A*Q)",T +M7'_*`7W;X"YV)2?L/F5RW^E?P6D9@8\!>?(KCUX,=H*S4%L4]\KX6XQ9UI49 +M7!0%\.9*624#:L<!(IX!61ISN_T.12S`3((",@K9TBU<]Y55Q,;@,!AQ:2W6 +ML',0XVB'I<^C,V=_)@/VUIA\@XHA@4Q(8=[T_QN;ES<X9?X+DY7>P'(LUIW2 +M'7/);-M='NMM9.K,L5IKY]MB1X1BNS7:M%%86_4_F0M>PXIOT"A`G-.624>D +MPUW/_6\4SW%;OU$<0$YCLVA?8EQPPQ]^3%#_[#4#DEF[7,[M0G;=50-REF.4 +M)BZ\7%+2"D_$DO+'$--5["1K'FDX+TG0K$8:9N\EYLS:-XM!=]['+H9)&9!V +M1``*,KU86S/<?T?,I_1*7],@V4Z1:N>N`_#(5"(*FX.$Q_F'#JJ+?7S4K+E8 +MVDY/1@[B:D<_7MY7]V8:&R.3,(20E&9MZ*P8]O&($GLR^"+)KJ$)>>)D7UBU +MY>W[0F[3=NK,Q''RP3B/=#?EJ=NM4BY/C\;SYV'#2VX,;N(+`4,D+%POAL^P +MT9HSD.*TCPV_V0^&W:@=4">E!]8!$@_B=R<?9BK.,/?+I[LW24['EV).Z@8[ +M2/&KG;CM!_:8!+8=D#0(TVL>5^O@4;F$M@[@O1M':VTMQNCQE32:%PKPF(.K +M9)2QDRL99EWY@'@S<E9"W;:9O;XD$%++X3QSJM$NJ<H=133Y865%,ES!<*>) +M@["M1_[I+P]8']:8!B"$H+[S`Y3?Q<Q(?->WT.QM@ZGGNEV3<=9@N17`Q:LB +M4,2F[;FA#I2$"%]D.8]$[9:N#`2%5^Q%CXR[2(0=)J""C+2M%0>D+1>#/8#_ +M3GP;YJL<]A0X'=?5<G%1?V',0M@T1,280?KD[C\F=84LNE%)F=U58Y7AJNI2 +M0$A-C68@.*SM#1N'1[8L1N7IR2['R2]H24K.GN')#ZL>P)>CES\R8332.-<C +MPNH\BJ+%LHOV6'O)E)#VH.KY::1#4,B*6D#+W\L8Y*W_*WM#.9B!6=A,%G*Q +M4,]`@3N(\7OFK>9#A7]`Q/UVZ8I)68QH99Y^;ABITMD2+`5Y#U`A'">31^%; +MU-5O4^3=/F5A-Q;&WHR\C:NY%F\57LF=E<IBM!6!$V-))$B>0)NW#>/:J^AR +MHW`7PK=;:!06L#=RDH%I&X$>B+F$XR4\XRDJ`Q0HX(0THW?H$\OUB<`@*<'& +M11+!]0^=A[9&U$[URV&(V7=[B72>8#%TR_@*U%+X'+.4#:_<MHUC(-0U2FGB +M>":;K][P),F&UY0:3KG4A=W]%+,U+T!"VO=$1KH4`GDI#,O$Z>KZ)?N\PB'7 +MYRWQY7WK8@Z4!Q+O`UG5F'KYED)GEC=L!0%+S6)6#:5$&.<)H[Z"3@0+J69< +M?"Z.UCZG1)HU,5ME!3V:["Q,OH!H,"MQHD!/+I,E;=#N_^,S:H/+'J18O5ZJ +M6P5<YQ3Q[:IHV"//$KTS>/0HU@TPB\N("\WO[7?^ZMYC'R3.(?)`"K*3=;,K +M$3!11WL\X#=#G>$,^1"[`V^"^$]@/*T6`!PP#J,S=\BVY@0Q\DL2<?O!&?;V +MFT$'73`%I6@+GGV0XL_ZQXK4-:DN,UPMI_EKN3:]'VRFH=FY]SY>\ED0#HL= +M:Q@*B"W!J.M",+I<3R'9HL(,&FK`Y+JFO1:K+ED[L#(I$K'DXI#]_@+^/<BV +M0D.*,^>-Q+\#4G3!DJ,,L4J)0)<D'9Q&%(%1Q.I<R,L$>F-KHIQD@'GXS,!I +MY!.3G&03WC^XOAJX(;+3S2ODV6\Q9&'!*`/A>OS.=XC,B)*N?'OEN^\/V8WJ +MFKI*;G7,JS5(06ICW/KQ@K:9ZSRG"!3=X(GY'7@;-ZY\_X["<#A)=:P2KP21 +MX1R$Q#`F)'[4T.'$]IV&J8<X^"A-B-2@92]/`R_[](.LO(#E3</P`TE&QC%E +M/U26$;,BDSX=3QRK=SG`\B>Z8T<X]L)K96D'K$`>')D**VI'!EJ\RZ[4<`5B +MALGB]Z9==4:,;%/>"N"ZF?2R&$[HHZT\Z2*M>?27`-WWK?;0)2B$TRZR'Y7/ +MO=(#NV6[;D:!S,S)^<YCGY'R]Z_!6K$CQJ*41XGO^.S,A!#<)`P)\\TR.GC@ +M7&N&MLMM[)+L#X$^HR"XXN"T?1D%%DUU&\3<QYP<V!E"68D9+F+RLV^;%3#$ +M@J`NLL7Q\6U_LC&G>DPKV5YFS.A8_=1O-M^#&F"M[EWUF.0K>\-&!BQR^/V6 +M];ZJ>2/GL[<D"N",N,\W4!$+19AKA`DOX][$@E:IVIB39T`3#%1D)K76<%^- +MV&)G$7O=@NQ^B&QPM:-5?7`I00#_=[0Q:0COUEVQ)BZ!,<9D6H&NB.H`O#GX +M8`<%F?S?1*8`4S_P5*7!Y8`=5^9PD>4F;+-"+360XZV#I[05Z6W2],VIZ00X +MK_CGS&0*TM2KUC&_!@X"A^^"-<X%TMJ#I1T:=4*3XYU9"A<-2NDL=Z2CGBL( +MWUK$RVLHPSW\'L>5R8VF')4?AAG!U1%U1!R6DMNQV>98L!10:&K=;,*/OZI_ +M&4L>!T1D[<?U+FB@9S7>8'MIYT&[KWEC`<CB&3=]4EK5K774S6]0+3C`5+3" +M;9#.;*K<[^9'2'L"<>D0`>M-7\PDVILYD<<-<GSS/%-M:]OLH$&DS#LS]M>1 +MA!BNE\:5^+%=6UEQF*F.T=@/XCN#W'<=)'1VFQ$<;=-NI+O\&TX6KVB;O37[ +M@VR.^!W5($!5!N)C)7_M=)._E[V%`\^/2IV<\\Z*(H]8!*_+K^4L2H4E8$H5 +M%1-`H^IXGV<S>HORL&M_HGR,AG=-,L\+4P_^+5A+'))P"=VPEHU"*0M%?8M6 +MKNZ(7@X,WO$F^AO)0L[K!4P4T$[:B;4Y[DD?SL2X\!)U\(_=5%,<_T>,[89+ +MR?D$XOABB@U$V42P4CBW/GT32$5BN;$:Z!;_+,:O0$8"`V^OG?N\CQ4P*"8L +M`L$&&[UP+B`K@_W]84/B]'0@Y&AG,WJJJZN^K$RC8]*\H(79+:2MPO,`9_98 +M>A3F1!88SY!EL!(`O=5M49[GH^(#>*0::EFZ_Y'PW0F<1#Z@F9M\X^!3-%%K +MR.!V0VRV259O98(T]OQRO9SRIFH]&T.Z/,1)8R;NA475^GV&&&S?POK\M='Y +M<?+4ZD`S02SO^NR4O>_6@?/%>Z.[5+WKBQ[!%WJO@O;+T#@H<.=I=N/5=246 +M89!'-*DB1Z##]OD6RWGWD%"2N[2!LR.OM6567)77:W/&1[5/N-`[8+X#H^(" +M+X<V2SH=`&-\5DB"]2Y318@:ZP/!4HG4F"@RLFY&P8R-F<80M/+N>PX_`&T0 +MHQC<D/0:#`490N]''VP$_0IM6LUL0Q#D,)<4KI#GUO(4'$3_;?S2L`U<$/O@ +M/8'#I<%%H;4J(11<\-1_J"C+!DL`8,R]``RE/^B7K>%@1TE4>?JA%+`>,0*J +MR#X")9L6F=:0/?R76^@P,Y_H%=,?M65G!R+TL>&HVO.Z*'GCI8[8!.6@--*E +MAF8',%V,X-+!UCW8K)];UBC3/JUZW&J?6#OX8T5*S>F0$+'%`H@G9#0DG\F> +M=K\Z<X8;F/:+_`=Z6("*+&TW75IBC`F-]VR:G97WE4$**,Z$F"B#KMR"T4DA +MWM1D^PH])2.3A8(VAX@0DS'\R2CMNI\++ZR7/Y8%W$Z>HU<!R6'_C<WJ7W4P +M!9[8">D($?876DZ^O$("CZH1V/))`WY8`UN/(=1A"<.IW+Q!_=$7)>X27GN/ +MTCL.[TU7F-TIL]&U.L>91E:^,G#7PZ('Y!$U(K[WXLGZ=)`^46)O'6^%CH<$ +MO^80,O$5RQ0`YNNC@.*Q#C?]6::?L!%.1VBKX;C[SPEQ!Z<N)?5DUD(EZIYQ +M[LG&TZO3#0O3#X?H="HW)=9/I@#YUZGS&+'3C7B]Z<59XR,,XZ>%6HKVK2\! +M0/CNH9,=/"Y(3A1K2#OM+U8I-A("([F]#:`DI]Z'%AW_:)=\"!87J%)OV?M^ +MHRR0<;S*_&H9KO6B!XCWZI"E*/A]7:'#%PJ1F\A5/V@<"_W`21/OA33,S1`H +M08O09>=9.1W930ERDP.\990UR0P((_AH6K7'Q!OK:,PBI.^(,:O+'/0$](1) +M52(L%59N8)"-PO"OI$,()1M_H86N)5"TKSM>*R5[ONN>MZ2WG!Z#1K9$MQG$ +M&7HZ.F>;9VY=?D\*I7Z4P<80=SQ:RTTQC-%(*-B+H&<$,_1%HE0)='2S3[&: +ME6#&E.S'0`WV`R'#?"P],_!3T+V07_K)GZV"C(/X*003'Y'!8V+8$2IJ=G]& +MPMB3O-)JE7>!!K^W06@(`H>4XJ%E2&[)<F]'&N`D.0T(M+[^EX[BEJDATW5^ +M@@A^Q!V,#&3"R%%B6@ESJB*J0+1D-M:4Q=S.`HI8;[_)R-XX&+HDMH)UW\'8 +MU/7+PS0D3[+Y^,X\"S(6M!.T0-LFSYA>D#>>(X#L&NT?9S11\Y\(=D**!]19 +MGH\=\'RK^S=E^7:F/<Z5.X&O&!Z:W7:\!LGWF:W35AEPQ4=0-];*WD2I%AS, +M9.%9$47?/T>X!$7$0G[.KB'`QW3.EJIRUD8-\?EZ<-PUIE0UK\JK%!=^QF5Y +M95[Y-A\(J7$1'WHIT8GULNY)$[8P=U[])/5N@1(K>(Q#Y0D<R#(,`882"Y7C +M`R1=02+#2<!626G!!!_7X=]ON3Z@-\L&_^`BA$0%<,'^"7'/4T@Y6=3:IEI! +M0WA09O*L;?--NC?+0E]O#I"FN,O)E:';Z!T<#@O>X/60377CCPEO,?#XJ2AN +M)14101&_BXJ1I;A=T)W)+BMF`]2GP697I"!&R'>A"/APZ3]CO%'$)<#^O4JE +MI3@<S9A/BQ7Z&!`F2>4\LQR&AM.\Z9Z3%&GN4`L829TSII@-_X4^Z(Q\<<GD +M<?N0CQ)CD-?P(`_H':]$&=#JRB67G_TWQ$`J6(2%"R\[/&E!#Y&]0A>:'6(1 +M$X=_LF&EH23XPV<EODX"5S(Y!./B<*+$CSW<=ITH>P9OK_I.02Y'-PGLG9#R +M"UH=CUB+D?N2?D)"+NX=^TR%!3S;'K*9:@V1S/BL25+1A=P;G&2;Z/_,RAHO +M,66Y@L1AUGUU>E+3G?5"4F41^F60MSSK'']A#G8KU)XA?!E4=1FIW!#"%6CM +M_?739#O9:L[;Z'('BYEMRFX6FQUL,=3[D#_.:LFR+(%,(H+H]35*WE0AV@)[ +M(Q;5,4$O\$#B`HNOV5C[:'/O(,O-3XC>6-[(,13>ASRX^.D-.Y[+"Y0A:QX5 +MQ@ZI11AMI>TNZ249^@`D!H#JJDUD+PE=\/662TV-R\EY*+)ST6!(Z%Y63]!( +M.#""68KM0COMH64(0;=(/TE`F>2AN.8,W5D(X15Q$ITN.$_9Z:G>J-;O@^&W +MO9+(,$QX*15M=&M>T10\/7J$K"!`@#]VPG6<>N13,Y!(N*>#8WRCQ\?6G6H8 +M]T3ZE`4(S!\G\6NY@R[*]LQD)M'/$W@ZKG0!\=%[R^(*\"":,"`(IG'=12QI +M+-BB&J&>L`-9I3_MZE=()BKK_W#7-!A%BXK[HIV.\F6W7_7)]B/:1YJG@S8# +M4L\3X!F2FN-<Q1]9U>?64$N]C]"JW4:U$A<5C.<:DY)Y84\'JU_49E>]]HG; +M3KKV+K@8)OE^N.#<F5;%'T*NA/(^"LEDV@VC!PL'LY]K?L6)&/#-_7<C5C^5 +M_AS6[)X#!V8]@J`V3R>/E7C=0Y@TR;%V)(9G3K]<!,DG2L:&HI<`)!=-KB.4 +M2_'\CVFC%[M=U)G,1(KNT-P%5PQE&@W9?0FGGM[.OC!UV:ZR3712SC)1.3OH +M7<K!*_7-BV<M2549D<4:&MM;;*2JP7*I<M;=^-]*%_Y#@#K3AA6N.<V^*1-B +M3:ZU7;^J*CDX3J\F&*@^"3@8.?XF6*SZC@NL*9G%:/NDFQU-9Z6N\KP@DF"_ +MM=(O1!<O5H\H%LH[("X*'IX3$1UHRQC^5=GR@T[$JB1>J(HOZFWS&)S!"P5! +MG$3;\W1U[398,A8_JZ$)]E#BVXBT\VL:#SR"?.'!+P#/[_"G_F'NEM:C,`N< +M;\3\Q-"#SI]3(U)G*I%9@@3#=GKTBH$O'\?3DU)%`A1%FR_V/=,"#1)Q^/M= +MXAV7?%=Y(H!:]6G;+Q)6DV<M(0A$G4!<=Y*M!YDPL1K5K$+)Y9BINEWYCA8U +MSZK%$=,&(M$NJ)ZDRGCKJFQF)OY3K/`SE71?OV!I;_8`2>0!.3?H7I$Y6DI! +M;O>S"D&@+0](I'S^6=[/UUOHW(.$IODTW-$K)*:H3;.?O7M&^49,/+*`4`3, +MD[#K=*;Y3%0RGKE(M[]%CT%0OPV3497TY5N7I'CB9_R$&H2H2[MK_RN2'"8M +M4TT^F=P'W*U2QOE:#;^A%D!-#[!<?:UP[0T<4^N^\S2_&N5\QG`@0-T/J;)1 +M=X&J^Z!J-W*;Q[%Y%V!6H07_S]"0H![9][JYQHX+XJ-U=6)OZ*.],E]L#!1B +M?.K+&U1,6%E089^G+)+_WVVTKQ'#?]G:V;YV<^U3+MCQLBU+PX.G.N.9C]-T +MBC0##E0F*L!Y1PG8<37=68T!T;D:GZ#(.6G/-/`UGXZ</)^8#43]C1)B&(?U +M=")P@)EZ?LLP+8O,)ZD#+%P1P@<)&J\&&"<T0`A<W`ILO2INN_H>^:$-ECZ, +MHB(<9[2Z0_.H\@O&EG5?`;.Q$=\+V(&;"_"?L5W8S&V@%G<$"0L8CGQSG=A; +MS6S_N$<H>S:YN946`"VV_$OR2X;&A,RA#LRMDDU5S'6PI'K_KA%/A[%6!_]C +M2Y(\C3E./=<G[NE7C>1U&M?BQ*2#I`QK.WWP]<6D[@C+>?/'Z$_RQ)E#R/*6 +MVFI_5<6B<6.Q!X3^,E/EDF*8NE`TZ3'.IEU52F0#9ZQ<_OS[=7Z:3YZS39WA +M:B%\EA4V1VKN6E`R7-)>05!QHN@<B^DX94-&D/QAJ3F\12FQC3P&$.N]K_5+ +MX&H`'3(B6=1>`([;U[34;D/EWDPZQVG(Z\F<GF7I'%V:^'U2,*KD25A:1K@A +M#ZE?W7U-R`$0N`5783W=#$*JAXNTG)MO<!'C[M':$$?)7Q/W?VH726IP%I'! +MZ4WU5H4T$\*V;\K5M#M+B?054QC6F-E&HR,+J&_5DTMB;_]$P7RCHB9]"OVD +M6199\=L\\=."#H^IGY(MIXMFA#VHJ$85*>9^H#+:/XJ&UO7Y`PH+<-\<\I@B +MQ!-OIB.>+\Q84?MSW9>UZ85^C@0P?`&XIO)<X7H?1XN!&H[$!LGW7=:7JLO( +M1[D]5`D*MM!B<<MTINJF1`5SFO+1@!VQ&UO>&P)K`NI4VVNMRJ`JGE=6]$+D +M:EPH0:]3J;45/-6Z=0YS76A85H1%_`?B!%\JPG38'@@*KA!A9H"T\:KP\G*- +MOPQE,,2P4&Y9+[5W;@$>P6C=?EYL_2S/]4W2`4W;)!@C#/3@O?'*YO41!;'0 +M8;652A5K=D%C/^RRUH\;"B!D4BRZ)_B%6`2*RSH4]U:8DEN-OC8%81S_E*PC +M7;%T.PBA&N]]AIJCN#?O&H3H=TH"<QHQ`4T-S`E0C-/X4`D0<S1[_ZFNB"RL +MOKKHHGBX`)_>YU)L391XTX//;E+L><E:MWN`>*)I.NT==/Y!'CH8OY?Y>'&X +M3_J'W%7!$,1")"V8&N6O[(\!O!;^[>:?1^WR2ZYO)&*D5A8T&5P\PEZZM!V` +M9.ANA`=>74T\056#^F2R&I)1!EK.Q?J8<L]IP#/R*_FJ@`R.X.2B4H6L8@-] +M"&'<R^Y[F,]I=(S1HM/G(>\?4O.8R0T^Q_WOOIB'@$/VS@)"0N>O,N5G<<J' +MO`1S1NNZ2^>4L=R]5AM\$W7^E6(J/+I:88)(V?@OY=-E.!I>!,ZN9.W4TR9J +MN"._GW()@2_*02:(N9&;N:<T=<&JVLB<[4E7L?E>.=@_L&4"XCX_[$@E'TZF +M$#3(U2'63/N!2)XUM]QG:;9]205Q+^S*1TIN23AR/J2-6MA].;G;W)HF7%=Q +MH:7_6,H^H:]E<NZ"3T(Q5@(D`&EWL(D%$=%>Q<@D/H-F%C.I[PWI)/-2SS4^ +MX++I([K>TS`@OMA0R\52*1ES!0W)`>V"//AB(UK:[7$Y'QCJ$T5Z.,JN.DX` +M)I5<A;ZN6ZVAK\HX6]Z'AO22-427D2%`N^HZS$2.%J0D`W4![S<[STB4!#*` +MP[WS.T]&9#\TG4TAK;G9001._]O93YLN#AXD!9\SR20T`5::W>_U0S[M#V,3 +MJ]GT+GJ6$ERZ+;@V2P:$HK-4]GJ#W&/CV^<R_*B*E,'9),NXFJW1AY2^%B-% +MSN@/JI3-GO!-?Z3RF[NH=0+#ANV=CCW9D$&O%@X#6O2=[+_-OGF>0;H*C/,I +M,0OUN`?B)K@20.8+#M_T/I3=+/SF4[E?X%]="-[M()O4$?6N=!EF28J`:W.2 +M_P4=Z69/']('QA4T1$X6+=6-?[O!0$A%X+1U;(7#"!V6E[Y!S..*R9I&)6/A +M]EC&V"<4YGW5]V3_FQQR@&!]RSP\L/1$@>FO5#P&</NHE<V4P\"N/"(?1,T/ +MQI$#O)A!#'+O\H5=F(0T4P!G#<Q^)`C]9R%Q3Z9E]5IST$SL_C"'C1`.<I1+ +M:''[BX(YIZ-GS.9%RG2YFT3E[`!@FJ$6X3%WZSCV@N7'I?8>7]Q"%H?#]P!8 +MPRZB]/>Q2>O$EVJ(EG1BGA/JT?#S%$9=T#L^M]I%@G7^T`11T?C(RS[(IYR; +M,VG$81[]C=#-`7E?3CWJAYX5BGYO<OM`1N4/AF"`)\0:&JS5!_F3?[WPNY^Q +M;!AKX=@-YC&M\B6ZW9``D^:[N1_XE<&AON?H%HX^<)&P;IG\W<2F>>K?A@!H +MNW0[/7AC@`46?*`']NQMNVDIR@'^K;^JK6KER2^XO6R<5G*G9O_BK>KNN$'# +M@MF,K#N!/6W;=UF3M$BGLC?#NPF_%SFEN^-/)F;/RT]I'M?+YSR/7!#MXM4/ +MO=XEX4[]!<]Y$B]]1R5)M33F:X9XK^L`?3'P,$DEO(KBD,PD$^L)"4#7<-$6 +M2;Y<LH3W`)_Q7JJ$]#!`1[O[/+*]'W[LV@QAZAH$`L;$]G&=&%C>$3O1;+H@ +M0)OX<]<CYDQ[[[S7JH?'6)0W+:`C[Q'D!S%0F6@`-T,QTH[CT+::,7L`%H=, +M;>HHRL)^FSB((*.F>'@'F"C_MT2&@B@ZV2K1NH9%T(/]^G!.WT=AU&C5EF3: +M*;WA_QOA:WNOI+($12,59ZFDU5%6QN+\("ZP+.)B3TIX`5?R&,P*0IV=PY]0 +M2A[<)4JUM_67Y*P!DWYQ-^$8@X<+"]?G$JVGDID5T4L%(ODGTY-U_&3<.Y]= +MXV62BH+\&L6/1HU[!A""T>5]AZ1+_QS]#ZD9XC'R,*:AEKQ'Q^._%)$U1!&U +M6:T#T0DK42/N:!524BV^[JOK_55'5LSYUJS.%$*72MV*U=82&H!4OI(IJ!%) +MXQ.%M<#53PG^VNLC^1]F-R[?#P5@2RJ-:5/BR2X($!"UZG'<O7C2;CA7HNMS +MUX7@2;_0L4ZFJ2IP/!GVR@V#9_V3_Q%ME2#%FC56Y*Q[96QE-:2G;;HO1`\, +M[&+!-/Y:8F?:X!K";;H%@1LGYA+X550*IOI9FP\:H\MGW!M)&+^I5Z7QQ;I4 +M-6K*"FW*5-U<(L(777D0881Z;3"@S$M]5;*@^&31Z>DC.]IECT!/E##,X,_3 +M@5S9)GZY[>!*<#&TTDN6-U(H]30SBXI9EW+_VA+9!DKQ4\$W6T%(C(^R@Y,* +M\DHND-4#XY\_FC2CF:GHBF71\"F5@ZQ#0(Y/3G:(/RSPEZZL`ZEK#C6A:Z(' +M$@AH+)/*I-LZQ5*(34P-RTCRR<8<LA+RXI!E'&*-W`X:.@C\*6-[-*7OKWV0 +M?7N"0M"74B!.6G/WNG`AA>H2)]4D56EE"91QJK/;,@)X`OJ`9%<>"OE,D?DL +MH)+1P)JRSIC*4P&3Z4+\L5=WJ./GO[!.D:G#LCAB?B#$"KB<P,86/-YDEM%Y +M>UNV*D/^M@=&O(I?_9E,9"D"98G6'P=FI)O;*0;`W#(#)D;2Z:T^<?+JK9^, +MP&8?2G](U2-$L10"\HVY-\613K.>/LJGE,=E]H4H4/%$6Q`KQM;>#%8J>@[2 +M06*U")AS]91PD,IHTE/VG5V^_=F33*9LXL^RZ2JF]I;2%62]#/L5I:E,BN1U +M9'IKPJL9OB83SZ-L:8G=5TN9PPA;'MD"&!?-)^"),9=[UV/&)VV@&D3SB!;L +M)X"*CK2VBIH`95L1I2G1XO:?]6N8QA'*K/V1:9B=]PP"L@<\@`8\9<\&.X5, +M`/D3_UK!J>UQ[&^.L=D?BXV$:W">BNBB.7Y0Y\>QSIPO%)WIPGJFP7?39+51 +M)?X&4)/NZB_ADA=;OZ'I$4#*RX!'YT>*07E*%/9D4ZQ:[@RRDDXR\0\%+F9A +MM!M8#$;^\+8P2V@"F\=R-M'.JUW;K@\!\<IVJ/&JS_KKB-J9`^\:03OZ<UI9 +M"<`7F$:[1&KV1N_VEBT<)!:LM9U*M?+.<F/("Z9V(&E'>Q3`O,5,]\#:E=., +MQ4(Y[FL^DKY<#3(D1*?J&FH1**4G;3!KA#:+6ZUL\G9X2.P''?M8NMO2:-[* +M"SW_,O,"?O6$@$1<?464P"]8.+ED9JGM[_"K42`<#Z;D%L)Z3$8=JQ6O=<VE +M3_B8":Y1^/72SRS$V)B9PQF'\&H(5"%B,46'&$,$Z4\4@2/*0MNI#@[RY8L: +M]7Z*]D4H:JY=F0HFR#3&R-_\,\8X9H$/B8L^$[P$`G<1JL^@4IQ?D=\_/IMC +MP%#0&%!K_;O5).CNJ*3=F666C./HD44XMX;Z8>BNA.;:T(3+0[*P%P;+2RPW +M1ZDGI9#(/=9/PVY<BNT3)+T7]$%=:$").A6^A'.^4T!<M5K`$V]]A]=WLK5% +ML+`R4</B)-I:NZ1,M+H;Q;ZD&_H0,QNZ>4OW$E;_T>%#GDKDFJ[3]1)B`_PC +MMIT71HU_*T1:O`->]]`[40E\+^RL`M`@7]U2^""E!QX3B@VCLG'Q;>^LTOA: +M'UBCPNN%\NW]"@65!1G%3/^,!'-[NW)EJBU52^Y:XD>5AV2#L;+6Y\K\9@-" +M3RAU-\.I"#-00R%K4#!$_YAM#?Q&Z8)P?EZHR'U-0'TG@H[1I^#C"XAEH?>Y +M:TOF:D]?HT3U:'837\_3II0BWB;I*O8@_/Y!GEGCC4(_IZZ_JUHLI_*J^-O& +ME.BESV!:+Z($1;)XFA-FN@P1::E$5G`G=6SG]*E+:XG*"(7<&I/HQO$]Q5LS +MZC'O#1&_+(7T$*R=,F,71FC'T9>2(!YCSG&C%:-6%&P:MU<N9%A\V\&XS)6. +MR);$>^U1=N\Z)?(R7ZQD75[X,OR\`@"7$YD.]#6,"5%:]C3E4QO2CC$V%E&1 +M7P%]WCC!7RXZ)G#YQ`>S,3P?7!(B0I<U/Y'N\\.$OV*ZWK=HFP%B_5$3'QD* +M4-M7JHEIOM".N@26C0588YI,&I4J](_@\LQOE;L18,:WM^X0*2YG]`B2?S8] +MJO09H@.TS7IXGW_XVN`7BGQ*6;BL@0&Y4<)](^J[XR8GQOA`CT@KD"8ZJ:-R +M^=8UE`6T5M5OWY*^M""..J&K6X9V,R0CAZ[KGQ`CP>3/S)@=$OMUI8J@</>Q +M1\-I5BJ)=15YUV*B(#.XZ@*UG'FS_83AT_R*8%\5\:]RLWT)K6A9TMAOB?)9 +MD7;^AWW)=?`^+2S-'W%N6^O/S-EC*KZV.>G&'?H*7FJ_L1@[`*/BS*C]I0Z5 +M$:4\T%DEJ>6I9*"#S3`NJTVB[GPLZA1ZH=5$>-K\`11B;"[7_`U7&$!8&T&& +MA<PQU6\"%FA;SD3P?UKIZW1LMO#FX8KCB\^UK4%=&1.;V?K&%45U'BQ/)XH8 +M5LM94"#6O?'\^((/C=0W"@&.-SRQLO%URG&)R,#/,?6QB4R>85U+A]G\H.WU +M(C+\DO69WW2E<%4VL\U#":I4&P2L_9]M'(I/'?S@6'4[?A++3)B!8&<+B!L2 +MRP23SSWV(\4D`#,2G:%_HY2:*E:T5V[I"BG^M#P"6*"JKO\'=I:45L-CCN>B +MC)C/4V2ULM&XJ"*/\USC/XCW$_;7?[-/''SSL#T1=XX^!K]HEO11E_G>=O$. +M7`9FZ]"FOLZS*N3_4$S*.4E`R4U4?!E4?4K\NW,\3\_R]A\KYL]]4^)(`/_M +MN-C$@TD&>>!"9E6-E07KMCE%.,U"6>#7@%CQNK';4>@Y/('$\-'`&:#SJAP` +M<CO.\7E#CHA/Z;W:SI9`.RT+SUHUV4XG*G`:TUE>GHBUM6&LO<,KYTU@GZ,L +MSP.ZO5R?U&X!XTCI&E*/>4A3O!RL7[:RU^BQJ)?YORDUQ5:/&=!-5V>[,R$I +M'V$'D5F\W,"==6LBY+<_MW!/-O+N.%AH/6^W3*L0TD$\L<L9W=W18G)S=QQG +M5+45%FS?:>9J&U+W#@]TD_^V#5$W9V.S,8[=ONEK*)\JB0TWW2O/P!@-<^6` +M>M:F^3O\LX+HNXK$<QPD^>?>OB$"3@J*O8%OK-\`Q;5K^LM%?]2FYMI1W\R* +MM1?>EEOKW/F\',Q(:JD7=R=84R[A"3,T>"PF`R(9_FL+HO!/PC0WE('CM_UM +M%6F+>D=W$F22:KV+\44S6]N:/+I;OPX)XO"FB".7.L!Y9;=P!43DH3FR#O7" +M2H^B250>%0"(\3]MP:;#5PW83NL(U<](-&Y*KFRN8?YPRH_@`L^7Q5"=[T"Q +M>%-JZ9MP.UF06IQ\N#_/2O^7S!F_=4CMGW)NKD5FJ9V'H^4+UBE_]7C2[T(+ +MH2",[JBRE0Q;CB69X'AD<)E04^>X]V@CI$1*<\34=V]>LLI.`Z4+KVZ)L%:R +M8$*BB`P,80S!Z4`Z/IPJ+&Y&O&!#2E%S'G;@RGE=KEM]#F'TARRGFO*/0F(# +MA/D/A1D<9P9;<+W$;16\:USOI:[1H;L:3M][^^Q@L3/-3QP<846S$$$ZF)HR +M(@.[LX]_)1UO.8(KJ_P^R73I^H:@]33A/8@A@V^FHBCQ2J1=29N?&=/"1`#H +M6FN(7EB+J#X>36#M%4"ZX81FTU-],A#RZ]5$DFS4EORZS$YKXB3:.7YQ7^\T +MB0X=0=/1RYOQ1X6OW.Z9_@C)DE!5@"R`9(E_J,W<[7M:Q(]$#DI'=2!+:'O& +MSPW;L!AWOEUD8Z_@V2K=@%7!3[+VY:-LE7!1G.L##E2+K\L]-0/8,F<CP_6^ +M=2X+`/`JD]LLL"Z^S1[N(D2."E,$"K25=2PK82!45AL]U]@2/\&8=;^XW^#C +MI\!L*Q'6XKC_^%`5Q+M8XG.*LE_R6/TK%(O1J:[U(+0F?GPE)A"JNG*H<EJJ +M>92IQ*%S[OK^H>\CV5=UTQ9!M=01Z*/R8;M,>P`W&N_697X_,@0*C`N^=`*4 +MO&>2;&+[<:$EFMG*!&1BX_@F'8M*L.1"PYUFU8^945H&M!0@M%59`VY/I[D3 +M,YO(4HP:/=Y"^5AJY"P(5'CZR0#;@#<E"BI[^\)$5XSSCL-5)]).'?![/XGM +M>(-?AM&6->2O5`I?@Z11%DZR7N>5%;KWV!9G6W(^B882'MK@WG^Z)P9[E/;" +MF%YE7&X?R0WM@E6)@-MKN:2%57!H#@P"?K#QZV/'[Q\Y_J[^`S19R2^*V/%U +M"(N)ZYEF<L(1JDQ:H'"Z_?]/@/,BJ8D'PV&>4E@,FUUJ_N;PZ<461T>0:3M* +MA!2,8H"V-E/J?0GRC;#;5T+`AI:5>W1D:;DA:?W*<H;&*L?-D\7*!_NF"[]Z +M4L";*YK\>@W3``%;!)4KR#H]`"RN5>7YR[)*;J[/G$P>^W>>1_];HHBPO9!_ +MH?=I*Q--N4U-ECS.9?]M'-HDW\W1O=HDSB!T<.@(!BHAA/"VE4]1+Q3LB3B* +M+$Y9T:^*B.<.+"QN7U+PH8]\P]\#)U&\6CW,D->_--]GB(<>P7L6LE[$88=5 +MC"2U0(9-^D^Q8A&ATQQ/CT$>Q+T.VQ5#J@VI1LV6M*UBD&&1>)G0X6ZX?MW# +MH+90274D3">V>,*!R"LQAY>23Y4/@UB.6PER'^2B;WI7$T(N7ZW_$OA0\BOD +M8/3'>YI_.(^N5U=6"Q-QZ@4>@T;X1M&>(W:?[WESJ>TFY:<6P*FT%HE!)*QP +M=Q/AG(TQ#<NG1-9G<[]^-PJ7Q.FB?F".X5;**,R,#59M)EYS3A<7BRKH3J=% +MC3PN0ZHA]H@M7E7[%I,:Z]4FZ.SC+K'FZ<G\1WO46FY:57)J$&W3F3A)*DI+ +MA9(VK;@W7#.AZQ_S9A0%4J!A]GQZL'F&5L:2ZA")3$L'B[LVB.*AHWZU^P%] +M]D;*2X*&4''\%631BBR`E!5)K.0L>#$BO&HCL9/#JI&?=0S67QX9"A:HI63! +MBR>AX"()N%M$JV28Q0!6"([_N!S\FW:'Q_-H=$U:S(93DRO:EPSG"9?3TX'L +MSLI&A\;C0&\55GE4!2_19CV=1JE4,=X];(IV0AGFSI2FQ&2#2-Z6DN3O=4NH +M^9UB_:KWM!6)KN3(.;F*`+TG%C?:I??J*3XR(7G]B!390L&S*+5^1_`IP3RU +M$/X6Y\B%T&^86.%.,)WD22PV>G?8Q2TL;HMP]Q'T#7$@U!>[FK-N-G[DI>N] +MG;D!QT5@ZBXXW<"1TOEF($5LLAIA\BK"?1-@2[7*;S#O(>A9!IAW\<'(77Q9 +MR0%$4OBS'"(P\Q0].Y:*R&BA'C+5^^O(-I:$A@TJ6E(H@0`<^$J]*"I<]KTV +M4U"V#1>[2ZOUP:X>RCJ`<--\Y!M*WP(&/3UI_D-='N3$U-P$3D8I`X.04W)! +M*WG\C+DUAF_:%E*$T/D7)[]2IW-RG.>B]3A;CF/JO8.W=E]O=E`A&MBZ^CT` +M\OG7<9W,E09?./1=_%(UB3U`R*X&CE>2]RN6:J[HL)0;NC\F=_ZF<&ZH+Z7@ +M+L+O<P'.%0C;P^2+<8*L3B`2S0Z)GC@D\4ZB-?O[/I,3CY&]QU/WNI.Y>&7/ +MYWA;CNGPG7%,18^&*J+N`'/L^UO:)6LP1D(G68S#YS41:4VTO;%C`X-/-YA* +MB8L!6+;^FL]IQY!BXLM'O3.B:_P=L%=J1`>H6K-*(;04:5-RVIWUV/-)5&X; +MG@JZ';Y*94U8)*\3"H;[_Y[/&4'F7AH4GB3C)-]#&1$XS,P"K**LM=>E8V*: +M;":%D5:I`V`>CGL11W0O2[MW]QOH56?\.1VJ\)/53X!&VN_GE,>V;]"P-^>Z +ML=!`A^M%Z-7CNS8"U"B)L)Z8\0\0YPPD]Q7N$]_M[$T``3K0L1'4IV16N;`` +M#S=A4PGLV,[++U<TVNN,GI8A7VI8$/=63<']XBU-3FR!!:KY0`E2"S9O<4<S +M9AX&(XY,HBCN;YZX+@_"W^T/W\A)_@!OI.]RQ4YL?>*<JS5!GL*S+U1*6K%, +M[7!BC<,TK7)4)C!TVF-^9!T'QW[$`6/&>Q%Y\01-<!\OC'2#4VFUQ.1/G"9Z +MQ>&&MVWJ/=AY=*UBS(,8UG&#T3T=TYBRWH&&J?C8`%U:_Z0G8"A2O[5B0SPD +M:T567QVN*^-GP;KY_@!1J:H*K!#*ZN';M/.CT)DZ/RH(H*/^Y]<+8P#&SWP% +MC*'UWQ/L9G+$;>^/6P52"3,(>'>>=>[AY5V)5(M!Y!E?%XF&7Y!3GE8-#^O/ +M#X/8OCN4BDF7GN?Y*S*5Z!^/?403\>1,?I+`JZJ=I_%S67K/>08M8I0WS-=5 +M8&'SB8*K!R*R?"%GB#`X,07S[7@YT\$'LFO..T74(%=ET)A!Z^-YQRS-^"N/ +M5M.Y83K?S:MG%7(<4A`-1PZ6(=@B-`?[\*QAQ.CRRT:8T,[F)2+6F^603\Y6 +M\-9MDI%0C%SBP)LBZQII;ZF`SDP==9WLI/>K);A]*_UB"M=:24_PK780HY(J +MR@B6>?S)=0_Q8YT`VIU)J#RAGU6[/6W!NYB8)LE;)[&Q1P7_IUQNN:$;PZ%< +M!99N<_)I^5,V&02.ID-]/)[]=,M$:J:TXY.?0H=M0-CPN1'<*W8!!$[Y2&G1 +M!<R&2/.BRZ-PL&V;!S\@C,S@:XH@.%=+72G&FG(8"\)"GFP07^FQ4V=Q-,$[ +M>66&0NQ]93/3(NL[D`S1,JME_RM/,4.BLVX@+R9>YD[,71C_MKALWW6CJUO[ +M=75$NZ*"^Q%A*]N/N8A0X>VU[TGTD]]_!UOR`(:5SD37V1'0?&MF6#$*E7K( +MB3-NEMJ4=XA>SY[>K^;&/S#3;=QYU[NDQW3"C\^]RB9R&I(@M7^'L,T8_=`8 +MQ:;'0VD!0O+_[H/L!X;-&4;571O$"<U$00!C(?Q!I4_1*T/5FT#5"$21W2W9 +M-^C`2\V\11B,4@S*K[[M$=5095K$3,E_$'G]>@GB;0CF!N6RD[$WC)-[0;;J +M+NK`Y[;V0@K3X=1X]&4B+03P+VQ]1;SWH4<,\"1[71'S:#VQ?7@&R,$-!N*3 +M(L8LS@_WE>\:@TLNTQF>F=\*JP:"M(A?P++[\GR)K>!<5-=*)"[J!^_='X$V +M%(Y8B'JR-`(_7^L'Y%PS04([@!6W^<M`_[]L.I.R&07:NYV$1@`<*=5X8[ZN +MOU((0VYMM)5SR5,V=LXHKP&P%'RD&4;$XCZNX_G?:D2^G'E7G^1;P8X8S@E( +M-XK3OO5+'3.>0VC5=K5(%332(51K(_2.@(ZOR-<"=/M0NH5EQ_E-PPI8UN-% +MPK1)!:*R7>J25U:DH'.OM`+*J;9^#5>4M#A>>V9%#1X`^.6[C6(%LGM+-FD[ +M3X,^>'*IF58*0*8=]TKZ`V_$Q-D[7-I[O7<?$"7;27@]4S1T,ZQ66\M/'.)B +ML?@5TM%"AG:]V-K,>X^D:6,NU9*CBA:J\%:[7GW!QC2M%.!57'A%5H#U`Z:F +M]/?TMNLUB]&83B1,VL_674!%]F2K^8HI6/NLUZ&[G=SYYZ+7%^K7RJJ-\_.Z +MWF:5LG.<7=$03"$G]$"G'5)ZW!??KF`F]=.^P36?-6@!1?:A46\"9.!7]A23 +MWC2(`Y27-U6"#-1GL>&EK)9F%M_HNBXSK9H"F3+DMPD*]`YW;YHW9L]UC19! +M@*7@=EJGM=C`:7UH#):1$(`GW/>7Y,8S/RE!GYCN@LT(FJU-;DYW[3'E62N[ +MJP+.7"#*,W>F,DS1`-#!`LVON..+%B8V;@V9I.!6PG`M6(3C[\G7V<)5(CI5 +MHK&:EGLEG_GMB,@4EC6^Y?'>0SLBS=E`T7BDH)C'M+H_;%Q#LR.,$U6DOM87 +MZL-<?:FX-AQU4[JP[D7US;+!GM6L^5HP=8H!E\&P_1IHOQ&>M8$#)T,^M6#^ +MZYI*2HGQ'%!0'<0WB3"Q8\BGC\!GG^IE/B%J?M*A)A=.$&KN2$_RG-[+\(-M +MA1\?G0*.HQ4QSY'PUY?$*KV,<69A[340SEZTGCNED2X"B98WPDL@Z?86B#\= +M3/Y,KONN_2\F^)`A3P>DNT;$A7!T\*YS.B7N=*N?,=6`ZX3^I5'5UXUQMN(_ +MIO$<.]5,:)5M-^EO0SK]J9HGJ"\6=P3YM@8%QID\&7KDF(GD'<5%RP>WR)T9 +MSQ$W`]IH1'7$2UY`JFR$L39V]9C/_:CQ.`EVF`FO^(B9;B;GG/<W.6-G4ARX +MBV);T/F$QNOF^A;-9/>,+1R3<.O@[.XX""E:S229WT$-\&B/,N!H;7,L_2?S +MLY,Z`##RX\?AI?2)RQ]UBE=]=T.$(MHU[`U([_*0^8V'UEO,X+=WM]7:H<3& +MO?($L5?-7.G&5?D/^$!K\.^JJ*C8AUB+9)"O`]>,@_;0:+>VAO9"3[C+NC_H +M(*B^<5'S*Y\7&'W7D).A[,LL&7\C8H9<HYH&]PDV>[9NH690)Z%G*P?%8`I/ +MVB@X\2W89XDD3Y[7A]/W89GX1G*=ZY:[4KP/,3XMBFD-`"6!=-N^&:%A;3DK +M0S-%<%X#'&!GB:K#/(^CM7/&M)=BLM*V<A([_Z^N*8,NK7*T_D[>F1!Q5L^P +M*`%-.^W/7&K=6:&3:B4>@/;S`+C8+'RC>%C!!4Q#S*U9,?1!%/=<NQM6B+^- +M[4%.%#Z>ADSH\?0'&M9U>^Y&TK0%W$<3L8IY+ATZ1FTJFF$_9<:!AB)@Q0<- +M7N'FXKUC.KGNJD*"QYNATM(CN=0/R1-A^Q=BMIX>0("R2I`W,N15@S]-99"_ +MJ?GTRLC#K`X+-!IKV7Q^/00*)&)C=Q$O=&1;@OS<NYX3SU7B7&:_/X[GY"#^ +M`3H%@]0?AYMJ63Q`S^6H!C5V6WC#%9RZ-Q)1\_\Q^#@OZ;T*8$#A%^/3'T@M +MA)0'^4\B'S!'H1]N"3?NTB(W.9(X9I)3?\G.G/O4OT&C;)8M*,",_]YM_Z>4 +M@D3P:7I7K@51=Y,:KT_:Y%P8Q6MUESB1#1C'Q\$[?$S+%AGD9'5#`21,2\O@ +M(@.['4^BWN.+F^4*IOJT5=6)*5%TN5\#U_W)@@B#`RMHA,&5BE^S*DAX6=., +M87LU#<5)A;I,37`C2/%X;JR:77M&"CH3<U3SD3II]P2=*>A#Q@)4TL^,'<(\ +M:;%"J2P/:;K+4KC5-X+U#^4'6GV1B#A()CJ_C#/+[VE^CS[H#K22Y##;>!+H +M^1;O\F\6Y\C0F-TH1B:RJDA@E%7J6ET0G9Q+A6R,>H+T?CK*]5^0E4^OP%?W +MY:Y,:/<"MI;YKUIJ!OK1/=].Z97K?_>I))61KD+.0'`,>2%<DQ%:0#]E\+'N +M#F?!ESF>^H"?XTQ:'U@/N7:S9:9#F$0.H::R3/]71YXRG2'G0T[F$/6?!(.R +MS5IL9DL#Y]H02S^:OF8"'(&8&9L+[FD-TR=]+YD@!,_^[,^]>DOG6PJ'>Y5C +MK#<O=YX9NW1/>HPC]8F0F>1U'<Q=%W/D=ST\3UB8H[BO2(X)87G5X-JGS!=) +M>OO;LGOY-`4`#C@!%7S.?J4S$8K$V=@-H^H@&G8G*7`L\\'?ROKZ2^'4$F!V +M`PI.7:5V1G"(?CMNR5EFO^<R7-E`WP8PDO764,7N<K$BL.2ZZ^J?O#ND`J]@ +M4B26K<3SBY8IE=`/9_G\@XWL(`39^9&T!F8H'`(\=*E6[3$7TJ**!M>T1`YV +M@@ZF6R/'NF3(IGQ%%#WS.^?(5!;S$$#)BT/#I<V_XXU2-?"QT<C[.Z/NJQ@* +MVD#0?A\NY#5LR%HGP.166=Y02O[3=>'WI#,3^KDY3U_IQ6Z7"*0;>!%9H?EY +M8D-A#'XE1,`P+&:QN<297^&!:DR'[,L?3J2I5R04/V:&7L>C$BI\5,8I5^9% +M!Z<4L`S/[U?+-D:2:!Z>)?BE15\!ECF',^S47FVG5E#]XW/U!!"G#F0J=\K) +M%.?C$@L[4G#'$F#<(ZT@5?5W+I<`.!...YV:(L9'\J.)Z0][=3XDB+SW07HW +MK"$&A4.E"C(3PK@+I!,6?1$JK4!*LV3M&Q*1S8UHSZ2G]*LD1LC"<U-Y^N>/ +MTR:EUDC7K`+,@_GE6;D8\#80\0"TDZ"_*S\Q;M?=4O#AX"?A^K5Q.A]>%L&_ +M,Z&E!3XK"NG)=?!2-,#?Z_PDJ"%?BI,D:!JX#-AX2T[)D*J8+U@3DPYZ<9!I +M_/`\L=%XKY:-Y4EF76N#11`>7R#1HCX+^.[0!4KEE=+GM\MNEAXS<@7T3.[G +M>/F3B:GP0.MBI-;G.O@$(EA<!20*SHON:L=<XOP8O+7Y<:))L<E)G]/DY=;9 +M=O,5UP,Z^);/"?JS0S]84E6ODRHU/!TN2,K>H(_]R'R@A&P_$,[/[?O"'BUT +MSZ^UE\@NF?=C:3]DI9`0]97-1@XNN#NE)>`3MQ&J+M#JW'5W=LB?"@S$!V,( +M_R>>C&,CH9K;H[1,A)<%_I#6#WRQO'EQW"B.H)Q9ML`F^+JV@LA$IT;UP4]^ +ML$/Z:.#CZ[*R!_4GDK^N:2O6R\ABNH?`GNR4Y.2A\@F",*[BV]$2CEUD2XH( +MN]`T^!EF28`E9+EG*<2Y:'"FRP&(&2ZDBF@48?*:L(CGY<NQNZIZ8$V]0UOG +M8>)F(WC(4EWV6J5(&6&PPZKWU5L%&#(,=E$6YA7(M/%48A])BQ',]:R"1;.Q +MASYW;M]LF3=N6B?"Z%\-U.@4&6*:/6S['WU<`U0BSX5GCY32`(AR!7!T0W2" +MG:CE'P@A;M_#"5UL3KSJQ(#`O*A3[,;DTJDS18TR"2!QU&^;+`*"5#$^#<E. +MMP7?I`(50"R)4N\D.`Q+_R66%AR35).<L1!Z(]OW6IBUT]8?KHD,XE*GA*&+ +M)&"53A,H8J9@X[@?%B>0.8+&>.KQJ>&'!94!!Y(DEYW]8N3F4WY[MOK^'3`S +M<ZWH+BDL"9V39&)0G5I<04V[DPA/JG07!(E:*C@=1NIN54-XLQAH0L:=L9_M +MG":_Z/[+GAK)2"HL!II8N%UJ_R['$'-:QIH91SNKUE.?\O_IN.4MT+"4*=82 +M2,*(4PMX+S7&4'9VFZKR3?C""'\N2U>JT]E3G5-V(Z9/'&4HF=KC^KY",[G* +M\MWFE.7@PVHJC-,XI6M]7X'Y3I5;?-<W*C0C+:23BXC^&CO0I@+N@F[QQQG: +MIES!E8"W#,]67(O:Y$BU@I^CS^?&3./\%["-*:!E$Q%/UE>\B$/TE/2+&0SG +M.&PM0V\U`-%EA1),D>XTHG&N!^-J)*`RQP[SWJR<2`M?0$="<I8XD-DWQ>5T +M`*8EQ*0;2RR9(7$VVL!.VLL"O:TA>`7FET`;KCA'%15/CLFU@:X'(W&1SO&9 +M">U"_DS_@E#'%I_]6.LS-,*K1"[-BF;8H>F8AXQ\M946ZE60\FU\9UW_ZMG; +M9\1[A+C=8B);:5`A+'B&>,A33LITY+Q4M<:T(1VQ7..VW=@W$GD0WM9,7L2[ +M+S1Y3.))<53$SQPV5%S%%J39!W40P<A!'6EYO'H[_2#`K_2]:\@UA!.G<O$) +MYU$IP<99MO#IW&9,T6&E2"\/MV,$`_XW6P@VC&A$\*0L,\[#F,Z[*1EENPP' +M*-BJ@R6)O:L<=EC6A'0W3^IL>)-!4JBH]-C_0E!7\O$($`5Z@PDU.19!TSG$ +MYV>*$CJBSP7JILKN-"_>_9[<C:HG!?G,UKKDN8XE'E5YSN!J\D<D\M';1*?: +M?SR'!5Q;MA3'-M]_*;<!I';;BKTD"W?%NF8LCL0\?.ML#?(S$5X!.H:?WR:I +MQV,Q#-NU]T]R1]9M(6SB^%%^#_ZE[]K0XG3NF).?JKTZF=T,CM(NN/OS/W,1 +MO.N"-9K6-GOJIPXR*B\L6>NUR`]=IH*,*J+%/$1G[SZ\6T`N5A[H;()$?../ +M3!7):$Y5?/_&.E]@3(NMX!]2_]7^3>KT,L[!/#DO<,OZ5A%(OA,7WK#'VK=V +M9%6T\W8;%L\=3X5A/QOT!^?,;(Y*N$"O!&1V&MW84<>N-K?112NB_Q>51ZCZ +MSWI"^GNCPAFX($W#I.+^55SOG++_>"MFW&`Z8G%XWT3E!FB-M_KE[K9\&.^I +M,(3"8R3^]/%C&9TZ3HKG0B$FD@-YP<]\9@4+^!DAHR%A+SL;..2\]]]^A!>6 +MSH[J)0Q.Y/D;49+$HRT"3TS(A+SLN[U>05=_BTSKX%J[4O#GDJW%5+&3>JN% +MY94PH5=N*,BOT$[J[<YAJ=TYJ&,V3S>"(V>BOYX\G?3^F'98VEK=,_53H\#_ +MFASJL\-GM0-6BW;`*.+8I'$:&2.$E&@!A42>L@ATL@=&U,1<=6LTQ]Q+7)LG +M(H.!EBQJJI9O9=LF:R(-KB&\T^4^23-8)D(M.$>9K7.4_*2DHT]FWGMI<?-E +MOKMT9>0)5`;WSPV&+^Z*J0T+B04T8V6O,R[P9TX.WVK([;C!()7JS*[^K9?B +M;:G;)T8[37&S-E`;?B*S(FS/!J2LB.77A<WL>C</%,8JLTO43F.;[H&?%.#? +M;6]`_1RR-`B)S%&[$;,&\BQ,="E#BAI>JF0P=52EZTX90[7%*N)7K*W6RO>, +M+3I'T[K?57MAL[=DH047_F1K9SX@89>TR`3AD-2L$!)KKI`@#EC,"`B5CIXD +M8@.JJR2"[VM/#+65:>809HGAXA73V[,&O^H]>A1DN9\2@!O2//W.I^`E@:=E +M']/<Y)3#\=B+=&",H:V@]]=?7J1/F+FN%`SXS-5:`/X-/@#N8Y>*-&2(`&[5 +M47Z&G%BUU!VCN&/ONJ0YU[N?C_FH-O4YW9`UL8>TR$UU(2Z!4S<55RQX>Y$+ +MGL![F[#$,.*BOMC'+D7)I)IEU;4DJ1RBV_SB_[M$(;0^=TU@_&BJ43HU\!XA +M2A0BXAKPLKTWMD=9I`2;4=+)/0O97DN,HB=Z!L%_]@[ESP?'*+-+P<TB^VEU +M;F:*%<KI!;$,UXGDD[UH3?9BSL_\1GXUG6&E"7@:6>B,HGHY8Z;*%%GP\PDE +MI@8IZE$2EBQ.F+;[0]->I/&IN1'/Z1D=GM>`86I$;:K<F9A'R6E#W54WOP%Z +M,-7])C*$:,QJ2&>:T64V_<>-I^OB0/=[KOV4%F\(08#"4H"'KM.N(`%8F9D8 +M1W*SJ2'-8`P1&Y_FG6,$.YT'X!>\1-)L,;6>V+2HU*8QGSAJ/0(RT?R(OSEB +ME^^_H,R3;]K1?(,()[D:LJ[X#I_XB1ICS)!Y8UZ]Y6@T<3G'\7&:OI#9E13[ +MX@**.2T^&U$!B.!!S9A?L_ZKH)#U9/649F7N8I`EV,AGU4E=KK=N-W+B&9SF +M.6$>N""L/B<XEQ$?C$.313^1%^-!IH-X[^2^Z>(J:+(AY0A6HA`@H#H4$56D +M9VDY_Q!77T'<T)X.**WZNU=/`9&`(W30N4!B&0KC#&%T5,3).*+K=H[6#J)P +M.;H8<CB@PMD^SX''[F4-KPAC1JS@+VL\%2^CKA7BTZQA\Z#CJ>:'.Y3E>G@. +M1)PN,<U5^Q8K['S?C0=:,T`2%08FS>306(Q6*[WI%.$4!EQ3,E%7L>0<XA:U +M177;1YTZ<?AULR,VK!@J00VZB(Q4N3%%*<JB7']IH=:IB%!QPX#]=TL::)?O +MSN4)3(X&(/>\1Y4DX>%7K4M[9"Y7`ME__#X_Y/U-=61W8#/;;!#)JGY5<9;G +MDXF&@'XP")H3!>?S^H&CV81&`S820KVF,QM*2.Q9!CP6NT^11D;;4PD)']4= +MOYO2<:SFDD'[!D5BGP(SKLARNTAF8?O`:Z5&2T3\Q=^K0@_5Y#C&:$O[RP\T +MPC#!U1V<T@O<HO(Y5Q'G.^C#_?8,'/Q#7H.[!Z;Q0I.LX!27-`]Q*B:312%) +M7=K:X%E-R)9>+!A-!W@C:Z1K*_CSZNL%5_Z9(0N*@)EH5Q@2$XN__C4_KR@/ +M]>2AT`^`V\W@8`KCID$/R\=D5X7+2"=L!E'?.U-N7#Z6ET?I]=)W)-]N.SKT +M?FZHW6G45MG4>HD0^8`C=\;6E6F!^#EF[JPMQ1LMU8]4P=5[6I^0*BJ;*6`I +M]$G;TFT^7-J$875?`,F]O6;&(BH0QF]/E\F;P=USSV61VG>.GB?+H]"A54!: +MU:7(KD3X!NCH*R[>TB-JFU^CV@_5%J@(\/=/.1I=.>N;7$Q/AM,C@6'-80/& +ME`@B[7XS+54J*"32=Q*![V$]?88:>5\A7EA:HA7GM_<3M]YY>\7PB=FW)OA$ +MD`+BA#V[\,3:L5MX<(KW)=@N!&<A>_AG4CYVJA/5:R"-B8W$*1<-T%>T9X9A +M:.^OSM7*'/[CRS12LR&`<VT*]M*TT!"O=@YWUTUIEN-B/=6F1HON(C%3@I)V +MP0>R/1;[,@N^1"I3EGZJAH_KR-:]8^V("K0'[_;_[#WE5*I6E4G60YTU$3CH +M\XDG0KD82B43O@B16PE]0_!`L-XZY4`*#U!@^Q2ZEE<S'><5F9HE$6H=RH(- +M^S[$DMM._Q.4T7`DX;4G+9UL"SLAG-,35K+MTXPF.]D,[=).<KR))M)2AEYF +MEX:1'/,0]B)>""F7MU18RI"AN4Q35:NJ19N=RG'3N=D$U8^;_%NMY0;HZW]= +M*D<O]!2;+0@[8O4$E,OG@$\5ZDI""IDK-I;I=SWX^%XE/,J=<>W*5QT:,2D] +M`*5\:9>3RYNE=6K9D)^(%\6'RYXW9![:F,`C[CO(XEW.N5BUA,BCE"5ZLKAI +M?X*/PU7*!-C&^V8TTXTU1ZPJ%G>/,=80G#ES'+W3H.;_D7W2!_'8EA_'U=;2 +ME;3A:\6])IDT*;*&2ZTA3\UDK_1QKV.)7"?#M%&2'BQ+;4=E(O6S[A_C.'F% +M;$AW!>J^4,D[KC2Z85[D5=7_!:3R1;$0#1$&"<YFI##."Z3S>7]0*J4('D>W +MJL5N,&B2>F/AF7\)2$JR+P$RQ`=E8PHP$8EL;_R+Z=<[;)4#ZEM(P!A`_-O! +M?J?:I7,*PPY7\&]N]>J4O<ZT@WM&NP]Y0+C!\%8SM,FZZVJH/>+9C_BA.<O- +M(=+4ED9&K`9>W?X->/^9.HA5-+4GGMLLERY)/U.H*6`3`KQ34L_$@/B+:>0O +M$U-?'9\=*WK[8$K]P<2+-ZYM9?=9)=C0SK];@19=I2S84#C"R>U^/2H,D'M& +M_-7E</G2!DC(!T3-CW5(8CMIQW0/FQST))?0;7;ZG@"/PZ:!J<07;UT\T^J_ +M2*=+.^3B"')O>N\'@]12&I8;=1EH:D21<BLE<'NQ_@`<`MOP1L*V$9W4B9.J +M^I1)S"W;I>8@<.'4?"VR3`W_-AF@-<(N3_@FH*\CXJ?*QY5BM[9\^M18H1EN +M87/N%!L/>.@_R61?9G>-2B8\9C=]$V9$2Y"SDSFH`X2,:<>43::R'_"'C;+^ +MA<WZR6C46KQHXS(LJ?=D/M)R9'\LUBE44<3M+`+HM*HQ+PZ*:M/^9?X)X(&X +MT_E1-D182.J*2`L\\]%B>W%AN<\&M<>WE)Q6-YZ%'O[@'D`FZ:);]S^@3BC) +M'ZFF"J=18[_15W@&X!?K[=T''O&WF)>\M\*?>,@28G2<8TO4+B>E@">L\/65 +M;S(F^':IIOUH]8[=E$[-S<CW1N9[.P_.*9;98R4+LUD+FNP'1L7/G&R@;U^, +M`[%N7N07%@L%!:'",494`4S;PA;-B!F#PB#73X_"5A0DW&Z=H>-!X[W:I..5 +MPG8'RO\+?5,@"4H#]IR6>\Z\351P*K0-@/^K'F]_A1:^Y<A]PRSD7=8MJAL= +MKG15/&_GP?D.3M@UTB-VL9@\_P"BDS*M0\DT769P)5D*P:X-5LNW"_(X-?ZC +M3G(@A6&)+VQQW#K'90@4\^>^,:<B/H6?U+^+OL)P:0(X]H!%D6F*6`U=2MD\ +M7?V[-!^WABU.H!;D+]M^TN!7':2%WL5&IE3:P5LCA\[DKG"5O%HSR?X^G]0F +M7-7H*&S25B)`UUO"0'><Y6[UMZEZU=BY(#3#$,=XJ,];RVE^=?PD(S-C_EZ= +MSR42)?1+<:;:-L+])]M\_C*8=3R'$C%Q9$8$\GMD%:),=.[!@+F@J9C;)YQM +MPD:P1@=\B(Y0(7NB/MUGR&0"M#3U0<E1CV:!JK+P7M->[^>:8S:0*2AT_8($ +MM'0#.M<5M!Z^!^_F&.%-I17HR,^I&`[L4P_W=2UW?;W3F=H@%-RYE6VF6BH0 +M#[:]A<3(,8`#:_L"K$"-(5<?E2=Y</!`6QX7+[:@FRX;&)NNFM/QHZ.D!BJ@ +M/9P@QR@;>9_1MT<@UYF4(BMBSGO9'M,2^]AY':J!G,:?M2_/+PVD[LO.3VY8 +MJ4NYS]/+%&]UOT1T*1ZB!=PL%;9D?$+Z(OX#MU)$GG=$;0[,V.]"O!MF[2T< +M\ZP6#J5X,//29,QF$H]'<''%J2M*KX0;O>IA=C^.>4!D;&^`&X:&$F2D&EZN +M@\K>SVM2M\B=!KI-64)^%!,8\KW8K'7OAHI#;$C4,CX_99Y8MNZZIX0YP/G` +M2>_#*/!Y5/X>XSZ6&Z+.+"="<7-9]J/&H/5+TK%IPT8++G:?GA(6Q=:@/T^] +MW&.]O)`H"UBL#AV>>G(SP/9_:7>>[3GN(EM"WLGHI\/+43*^OHKCK3-W-73R +M)X>VV+,A6CN0]#\)7'LD7++&_2BS/\`JO%@2;7:L2ON*)C=S9>1`3#-Q911Y +M.S-`QH(QF8\S<ZL1T8ZP!8?^K0%@D_-EW7M,KF_Y\5*;O?)6'P2L#%]G7QTI +MJTS.'@B\O-#X\IS!A%#_]KT#$[QRRX".LY(=).B<$EZ`-]&@<%H9_^6`*`EP +MG=#CGO6B9[$[N2&]&,ZW5IG[I_T3I"#Z64KNOFLJF/\7Y=CZ,P_L:H`Q99^+ +M@K_[AB;CRJ:^G1'X[D(NXH8CF9[^*/+XP2AB24O_5,3JE(V"MD"CJQQM9H;+ +MI,:($Y-X3]C_$[('_RH-[/`][3\*V.,4MZ-"J-<<YF=PU];(Y-&##OK``^L: +M*GUS=-!7YLI9>MD_D^*O:8-X)*2R@OJ^#CG?9!:2LP,#)V%.BNV'KDEOOWI7 +MB81'X3Y(U247A+-:M7"PHIKC,BE*FK@_?^>C<@3K07\^F`/Q[-`FYV4#BP#I +M?ROP&5'DGO\XY&3>S5$V0#730T:G$!=UM>%;;]&/U#Z=/4K^F35;I?Y#U3>' +M,D+O>TWT0Q8RAKTNVAU3^4;V$`Q7KFB2'Z+@1KBBJ!$=V7P".<KSQE!R[IO. +M/7]9,DODC/^B564R[6K7S#J(O:YOCF0G8#TA0EC#I0[5>^W6TT$"E=S$`0C/ +M"N@#N+>;X#H:2'U\E'`SIK*G/Y"1O0702ZQ3'^/6<Y$0/\"D%XZV9WVB=DM/ +M#5:35>%N6&--XVB!U'0VW(GNG,>]03E7%BX[$D[C>K6;V0`8[]-/;1E\>8J7 +MMC3],B16TH@Z_Z7S;M,JO6*E\&QLG-DIVR2*P%LFF$YD6!#"*&T28X_A9-/Z +M>,?3D!=X6_2V5M;))QBHCH/L2M=[CIT9C=A-D\0[H@Y3D*9:*RR\(+C/P246 +MI11/O-A9GRC);PSC`?.L0[R/\)7UU7^EV2+AD,+-;&&:$V[F1BBB3U.8&=QE +M\B-DP2H^^X'"D%"7LQT.W/@\1G9@PL<;6`K>ED'](,RV)I%0JL"_-7(.9A8B +M(J:/HNVTUSC16L^?96]KRB#$Y1]V7_+EB_7RNWYFVO;WM'W9A67K;(*P$_4' +MNP_7]%"4#V4X3S[!`G!SRQ\2N4=&+.99%)]X5=&WFAU]\[^0!D.GW"@VJ9G\ +MN]!<:.E42MT3RQU(.);VOA&6*6SYS(L,!^G]58'Y)8%[6A5?Q6S&U"F>]K'G +M,\/A%CH**<=BG!@?Y5VWOU#)+HVRDI>+;U_HD!SI<XZS?;C)(_GRFLVGP+Y) +M+TQ<!MR+M=\K)(7V7=20J3E9$:L>?L@EMZZT%Z^#HBW?VJQZCT_UX,=8:87G +M.)SZ1?/=3#$S9P6Q$@<SK`#N.[C*U8]L)Y4/3O9J3V:WK9I,>12,2(AOQI\P +MI>:I+MOAY]*#;ZV>99WZLO%<\^!S;+DR1$@!.$ONQP:R>]Y_FWL5C`57]`;S +M=16&H8$[X.G"*/"W0XRLO@;X[&(X/9\K#6+*_BA>H7Z:HX'?XBO=U2?+<F/, +M=FCGU^K8"X:FF[VK.+7Y%M_905RO:VD5_CY^8:88>HYP=F6\M@RRVL8W97SB +M<(FE.N^)9!.8W>?\2=J4;2=&Q!+;'$M'Y\-"2!QJ;[+OVX<\W0'RY485)!O4 +MY)DV6>MH_$$4XEFPCJV$M_NF$2(YT7XEN1Z!`U.+)J2&M&D=<;'AYL+#["/W +M];-V?\N<IMYTG`<X1@3H!ST_^O]<HP7)G=R<^!D479O^@;?&-6+/V3KJ<$PM +M5AS*V$0,!H[!3#/)?Y3U:!_-5E(C39F#NI'WJ'A9*[H=78=<R&<-E@:_VM18 +M&'99Q4@(O:M5/"]&M?07TB-4;Y5S5PJS6#ZX^4AO^XB+P!RW.HVO:"[,?8A8 +ME:D/\%'N>/Z"VN4+_=U\H*.=2/_]+B==O1CSLJV.%TJYE'>#D3/SM6^W)QI- +M5O)+M^,("1X:F!*%L=O7]3[A=+U1>]6H?6)<!G_+69WTUD^\WWZ<H+HLZSV( +M=)ML;]N-X!3;!D.F0(!X:)YKJ]AU,M9'LV_>ARJIEU;>KM$%-8N]A+I;S`4F +M0TKRD91\$6XI)4<-P(A#?F#6QT]SN7E8SB)%&'Q6V$(+XE&*[E#[E[4)HD?2 +MV`3PN2KY'!%9N)?L.DT9HF0+XZ!"$M4@N9_=^:K]V>=7LK'VEDQ,9D6+-V28 +MM2S7X#::CKH1JZA:SBH<&VCE,_#D#J7_[Z8JZG]S9<ML!]"*K_7B=W094`Q^ +MAIO!+GL'-.Y\6=A%J;GYK.[?&2B@`4!E(<XZ3.K?3F#ZR1OSS\?6:8*52WJ- +MR1MJ6FZD3HC`"&%_8+A`;WE@Z\2,@NW]^)M^:AMWR2NC\7Z#S,7"RX:])86Q +MSMLX_!#'`OKBX$M@'J.:']B:U^)_(9<L>BJ-(C>MTA@_R0N0\?Q67-_<,KL_ +MNY9$H(2>(NN,JF?K?QPVH(U2JA8A3;$#OZRJF5PFY5(ASD7LR/A6^BV_$':. +M>U6<:3W6[K\]3,,TZE@GSOCO96G**FQDR(YQ%/+@=6OP/OLWHVZO:!SKR?H# +M,30E>//9$.P@`B@%C]UW.L_P#RWC'8R9E(?AY["^OF!CKR>])6G-G.'9HPJ@ +M&S5O#1+RH"'#"D1#I$>V;'!F)T1"`Z6+XQ@FUQ"X#*`PR,+U3H0\D8]"Z76Z +MDHUS<%Z5C&B$O3&A0/2F*>\SJV]!T-=?@0&V@UTVW!MG7O8*0;\M6A^/C\9[ +M6=*P_3NZP66QI]OIN&JQ!$RVQNMNIPY&_K(2?NE(S,.@A`\K#9<E)-OC-8VR +M`T7^E9;1G5Q8%*3R*&UJU6S?_<P'Z_@SQ!94_$X(3T(C!48ZQQX]1C7'WFQZ +MUN+:7T6^]"7Q:#36LB%'DN3`&]?I/;OJ%[?R/2JI$)U+;XUB\JL]2\]I6L&Q +M%G=$>^3D@P+)&)U8N2&2!AK77<:":P\K@^@0B+AN5T.['RZI_,J,V`(46<T& +M3$\CXV`?R-/P+H]J5N2I!Q8=E9!C&+C_"^QUABDAYXGM$6G9.6^0Z@:)G]23 +M0H&95;DU`Y@,R"LQ82==6\M2[5IJE_"T-,!/KCAG@DE#Q?.&Q&%NYH2NTR`8 +M/0H<!!I0X.@X?:;%5H>]KWHD/092D-^EK:XRH=/;4V?@;_O_6."1`Q.5(]UJ +M[T,.W\#?#9A<`_?0R;2,%4_`#7P8R]@6,=1$0S^+!FGMEF<<FKT;6$0)6+SZ +M)JS$\CA_+>5N50&"(Y(\Z%NMF"U3[HG'B1JN%>`H-!X8R,X,]N%[:/_OC*W] +MU+/R./6X62@7;Z9_0)R+CI*=QDOVZUH\AOFJ-3XW1<,TL!U>W02'-K6`@IB& +M%>:F-4*1"20MN0X<_="Q-EDDMK7$T]*S]YQC2)6V46`.L0N[A(U7?>0@&SN. +MYJ&[^MS!?]$A&EP+`6;2Z"GO_:N+$\!]?H#5'M&0>Q/A']'P>]:I`&R#JQ## +M*7&2V*_P\4X1W!F`;R0'G$7^*"W_X#7"Y*OYTQ=D>9;O*5HR_=;/IDYC,>TL +MPGFWNKKZ$^$*=</D#_A03PI@KNR),?M)8(R?&]K9C\?]33YW53SN5DU&1%A0 +M]`5+$AU;T^H&W:GWI+(LG_I3,A@6L#VZ@@[$5/I,H:L7,I9!^^O0S]X\;PB- +MG<U)@/_]/L#0.<57?;'IQ%O<1K<.7;!08U3+IXX``/>X#VE']OE%VHBX7\:/ +ME\`_86GCR/@_'L?!!ODO[7?^NB60LXNSPUC;;P#^^*[51`"8Y.V@Z3[IV\?- +M1A!VYJ$#'D[>J[?"!O_&W6,(BC%C[QL]U:K1.EJN,E3>?@X-P-L)DT'A"5T! +M+6;U'C*_(E=/]T%G>??FY=$<1EBG\H-7;#0K"#M`G3BRVAR&*>=4F!</)9)N +MJ/X0L\ZW>X](F8&`<VHPFTC^*KBR%A[9$CUNTJ$^S_.1,*I"!B@<:_-F1A'L +M6BJD#M"M^^&=DO8)O\04WUT_BE@AJ*!@K]5N$FFP8HMT,!N'Y;BV_EE8#F4D +M:`(Y2[!O5&:D1YS/(!Y[$9A@R!BY5;A&)2C#.N$V!KG@;LLEB4]!IY8"0N0M +M_'K[0OBV,N07G-&PY=:/46X$W)4'!EF$6G$=X0'7-B>6F7YZS15&8C_R@.M8 +M](^AS^;TD5)BGI:PC,5!D-!8H4M%>L-8\;8PT+QN"$XY3:?TJLMR+KOX)LA4 +M[U[IQFM,_+HPN3E^(*IC/FR8#7F&,@R_<.?DPBNB27?UE*-(#,\L:(N4R#`= +M-).[]]),\L:4%TO*JQE]_`"X(EU.OVKVB:+'W?`GE6_1]6RP0#3$B+;X/%2& +M(EQG`4"9*IB"A'5R)C^:66:`;J>3FZKN4Y9-^G4^2:UMC*"*-(5_M)OGE'&& +MDD?XD0U[35-9WQ)R0(:]&?**4^4WOU/K[6V=^,'+(79XPAA)7YJ@(Y:CO!XO +MOK`UG*_O<`2'C1,3819.Y[BXVD7+_)7`MY4N\>WWBIVK97Q,D:`=1(^QVH1\ +M`KS1'&][XLAOI(MW<GOK93<EY;7.D(U%S(IBCN_41V(^(&/=H,6+"T+#(*(A +M#+[,Z/<4V=@(;=MDQD5A8NT>^;R:CG.%G9M2]H-XI*WX(7]>3ZMSUHX\'O;7 +M=VMW'4[JW`OABEZ7?D'[2O/!IIW05LX\RH4LMTT9"1::NQ<4;\&@(CHQQ3HX +M#C>OWHXR%B>U9Q;R!F'SC="3A[+5[=S:'RX*<O+$]TF>@'EVQI&KMM/26\[1 +MXWG1M6DXG%,KF=4+$IIW5<R7XM/$3FQFDW(C01"7NG=?7AOY:,#^DYI-!/AO +M+[F9!?TDH^ERW63X)?ZWPC,'A%:LHD2>+6^[I,W.G]??0")72DMM:2VP`1LO +M_\X#]6=AFP_/TH_G62>=FH5*)Z<#?X4&D^75$MN582L0_[F0!B'Y'=7=5\4Z +MGP^Y_L-NZGGZW+98'U("UR2`%5'3YS]"-9-DGI\#D;>,L-6HSPFRX6?_9W[M +MZBJH@TWBPO3F!R5KJ<3A$7G-0[@0@?0\-AQ3HK@04J]H5H$^HVZ>AFK*N&.= +MDQ.W)L[D\;I6[4>$R-,&X:.^K1D6H0002T1@;RG7C!^*]DY^Q3;V5$5+!%7] +MMG11,_+R!?3BT$(:[5"V5`,-[V%&O]?5YH91UHREI@&':EM6,D?&"J_J*7GX +MU9M(AASEW![5CBMXXPL$AD0G$6H#ZTYB>@:!/4]B6DS57-=Z`&A$?-JC+S_D +MI^5]#FN4J@CQQ.5,[6B#SV#]/#2T:^%B$0.X.!3KM8C)9.Q6CUF@=TCA'$=D +M<$/`U@F&XKPV34QL#ZTS9$:.X@PNJJ0YPIDDY^RT)J4,`TCO&G<H*:36G\>2 +M(I*Z,Y7"FJ@'A(SP'BD3()9'KE,B:>TQ\H6^4^$9D`\J2QC%F97+0"QF;6S$ +M;-4&C`5Z<B?S1V_-2;1JU-FK>HD->L5Q_?-'=\^Y7Q;+FH6*T7&`X0@Y3'IO +M_;`#-"9%\06Z%G=F]EH+/N\SC\JIOMI%S9,<WMGLH#]'>PMV35&KT!WX,'=^ +M^^:2KELMO.9[%JWRC<I)O\MS^S0D@-2P]20_!&U>U@(#IOQ8K!<:'Z\FGAJ< +M3T3HS]`$?_GTC0<FVN\G.RND\M<9,D$6:G'[60?UUM4;3U#MA,@#HU!`9ELO +MLLS&_D9*P7MF(_+61!D'I%&S/K0+HEI/\9Q(904-DLDMY2^4Q_L-U?BHTVXE +M97T;7X%1_!;2P<)`4'\)L>>!V[EG'EG5#HMO10H*3P:50T6<+*%-Z#`F);21 +M6:\;.Q77IC'!2YZ9%$'VGB\2B@&_E&JHT,+V]E8&0R(NPVF-()3K<HT\3Q") +M3D70`UP00*^V2'[*&HP9>,WD0`_%=^7%/FO=I#?-L'?B/]+QRXFG*ITLQ#-" +M-UV7YYKB`*S,\GY#Z+;B!>+9O@*C"R?0/IO(:EF*0VXGO_[1*MS;U@F#8+TY +M06>N$--UKZ"Y:MF*3^L!!'LOBYFFO+O'_4]M0)%H3::HDM[JJ5;XD0?]\Q4H +M?3_@9O!X)]$5S4^L<-H_%85I6&^^HW$[)?O!1OTRP2*7:=RBF'A>/$4WZR7T +M2`E=,6H3S#P)"@0VAOK.]9QZ(SB)CX/_HAE(\DXTRA"7TCXPM\*%,=%@U<WH +M'8Q0PW1KZ?1(.%"-^XTEQ_=_!?=`X+W\V;SUY".!Z[A313B$="/$,5RTY"Y% +MZ-=EIY!X9=>/^=,K`1VK).G5FM#XD0IN$IE*/Z(S-P)O98:Y\&\6'/OI54,7 +MHN*9<X^\1TLZ^2@DF.&9#W$PC]RWJ"%T-M-#?G&YN[[E_B&]I=]-`'BZ=YD' +M99*1-NP-W+]/C:D*3W5XMN9Y6W8%:&Q..]P/#_0-<W-5[+ITU<$>`P3*I(Y= +MH&C2`0C'NQ/V%O@I'_'UCYQXZLPPW6J,0TFK&7#Q$0`JE!?0)H/'X=6FL.', +M;XIJ:2/O0AT8VUL@H2/%-)!_E:IOK*:EEH"-S"X)UO2ANK%:=\GYWX<45RY> +M.(T-<7)@AK:=5DES`5]][XQ4UM)#R#U9%<H)_ED;FX"`#J[?L-L#30B'7IHM +MD"KN!&COT&@TP$R;UJ>XB.Q=[",%[!Y2@)=!47?INPOYY(W1HL.\Y@UUM2P= +M;&ZJ\@U:CXA,?Z_NC9N(F^[#PM%^4F[H=OR@=ZJ7V^&8';7/)N'R8N*Y,B<F +M)($JAAOY@MZ(Z^:<>)BNA`Q3,DHX3BV-]=4W9[M`8?=`%8(Z%<<OL-,E8<P] +MD"/L'B(]X)>Q!9Z]M`X@K#?L%@_Q=5:9/7"CM6_]>GO@>K9T^$[CPB:(1QQS +M^"L1F1!IVE`S+LK(I@4?GKV0GXT*><6_AH$@?_.D!(BPMXWF\O)(GO@W0UO! +M6F@5\%NFY^KSS@Z@B4IK)N!`!CNNV(S_$I,>182FV13DN?$UO%P?!&6%\H@; +M*_RR>X]CH"45PWOG*)KF=KRY([S7-/A>2<.%$>^4MW3E<?_ZD9W,J8*G\I2Q +M4H=F('XTC&,8\S'+(S:^K0LW`@"!+Q>>,I-G3=&(0A@ELD`<_1V<L<N)RM&\ +M?^/=\E/^%3+E!3]S8A,8"6#7TZX0NZF.)_'M7Z75$/V(DSXPLS;&M.9<`A)Q +MF7N.B/K(.*/,PT]&I15H/5WZH2H%ZDKJ0H>^FVG'JG?I"B.TE2H-6&;V0MF; +MHG%OG+"OX7S?,@E=I5,XEN25[F?!$?B<K`<:,-]XU9"8*K=@+E\^!O2.A?E8 +MDQ#3CA+P7O`P,Y,/D:)?[N#4*J$(CK]N8'HL>*<Q"5?7\S!`CP+#."LU$8P< +M7MUT*#GAS^386&KG]9F^_H#,U1!$A]6QT6),OB/W>'``<!C75%GN38I7\?*- +MG,.5EF%J*.964E398K8=QQW0E3BN_L^S2=:1"^[<W'@6Q\K*T5M!^TB.>Q/0 +M4PS!/;[Z.;)^N)!Y.;+L"G$#F_SSA\*`2IFIY((<[5L;*6TPOLUAR^V`$!@@ +MU.J;L0FU4JG_S)72M_F9^O`K>2I\/R`T!-PVYJ'\6HVXD*(RHE6VT;<<Y[^5 +MA/K?,`RZR?'>6._]U!"`6M<;I,=:KY7T@]N`D,O91#@]P=G91'>@`&KH*$GW +M]AF?QCXD_&,^L+PD89.]=\;R_Z64?PF2,U<_3@P(XB$7IQODA(;&[9_"C%%E +M+EDF*#0F(AO7XF$FP-@TX@^0-!,;[-U/#FUW#`I0LSN++U:D!1=8396.X*T6 +M]U!_]*H`X(<@YRH<VU'OV;L*IO($9LFXU4FF5G;B3Y$=4)Y;%QHOC,\Q[GY) +M#9[KE/.66WY!3F8AMOX)[,B^K7GIRK%V/K4E9Y_",U1&QQPQY`D3/0M"QWS) +MC88&#$:C=0%;0'(B4,`T0I$O9:A^FW-;8%T6RHE_04%R''I."ARMY]2+*,95 +ML3%_H#SA&HU).9.,!?NI:+Q!F"'H(_TO)S>*QH/@H)YQN\+0[YPEZQ><3M$V +M&891]`F/US=/ADGU7OO]C4^KN`AM0?FMWF-[DS#)![TB;@-Q)<)-O>N&/(^_ +M&&ET4CI27?CBT.7$``\Z`F,:\!N7DPKH$^7J?[*&%[I-6-_@O>[_@),+`:A: +M4NE%<(R_TAM]1;.`W.Z)-?+SCGB;+8U'2%Q?HF<P@`*%%.%G>@#JA58*I=@Z +MM$RK=`?W?>\;)SQ?XXL3-&WS%071AK8=9S,SKOK?^TD60^@_&N3<Y+E<RRU: +MH\77PR"G.0ST@D781QE8T>T-N+#6QRIZ7ZW*[U+,=2NYD+_G(\Q3DHQ]\I4L +M1H!I!RQAQ<9#^:E"_+:ME,.L^H2'-UNU]9CX)@LCB-F_Z2&<_:\-U%'O?N_9 +M6E8J+@7G&&CK,!X[3?=OH?$1+ODE'DJZ#P`3/*X16*TPH<]:\(DA0/R.\5PD +MKK[8G./.C%$XGU`@+A8BN,_4)GDF09[ZN\5X%0;X0,GH<J+W_]>1@RY;=^/; +M=:Q*H%>\^TG:.GZ;>=RK))Y_:&[]$@M3!NDR6N>SY8"=0=M\QV:%".V5KD3$ +MCS&+?\?`6"W?1.5O):BF5#F^HD>][M4+E#UW,9%7\&\0[2,@.H<PY/NRN-,F +M"`70S@.;3;&Q`_\B@HY?5O&X/A\E3?&ZPF\E<(`URO`'B)%Z2=VJQUZR8K@B +MN^;&C]BW=&`_0RWV`EAL/X,HZ!ZB@A@B!H$>;<>"H!&.IXH(,MR31^U4:X<E +M9V!^YPGS>L&B.DAC+E2X6;!<=_8QE>IMX\.4^D:T_"K.CP#00(\L0+P2`N/@ +MI-%>@MKRMFL?M_G2`[K57@S,7,>C+9K]RJ?+?HQ?5]@)AOQL@T&ZG[/--VK- +MWGNNMZRB_&>3^27J@?+?27O<D?,5T\(3>Z;V<'K3+K'!5CUD`NK42494Q!T# +MHGM5?7/"K9P+!M^64).+1\_63)$&D</F(8W]#1A\#\Q4G+0;<7Q8,PY+]Z(> +MA``\,"SIN,K+_>'6J!B0F=EA%?9E79>K(2%5WF701V[>6FC<HX;!.DG2#DFS +M58J52$'^!)6_L<M%WZ9R"Y&=]=OJ:TL5;>)=8&3-)3+N7_VVJX-I%BNW!,DM +M)N>5P<1<R$3#+QG`(+A@'.%CW2#UOTE>^J7IO&/AO!GM(%,&QRSEJ'`+^^3: +MC#50*DP-0YG-ZMH/5>YSO>Y@3UYU(AU%'*;S1A;OIKM1&(6C99%&*!IH3=90 +M1=27<MLU$?H6VPRY2X1S_93:A/DD/<4]=%TJV:^2'7A">S*$G.DC`:&BOY!U +M_\-+!:,%F@@26Q>FYO$%[.YP8;YV>F1O&RNKLW9A?ESW$'<(PP)/^/LU'#'D +MTI6.<=_X52*3IHD%J.,@T4%#O"]RS3E95>"MNMV87("4*GBM9+5X[P9T;(#4 +M"1HEB_[P(ZY(H]3=#NQ%,F>\HCD(;!TEK3>;02)A9;YL]9/OF<^V%%<`']!- +M>+U0-J300&W)@]</1BIUYX#MZ"-Q0()P2LDC8"I,@DF!_JF-4;*7:8@N>^/8 +MA@ALG9]RP^1R/=532H1WPU['\;;4H^5#*SPGZJ$$0(<J*"4LQSO%&'<NJ_PV +M$)PTY6$RU3?](!\#^AI\Q(8QUQ,/P=_<+=_V<&3@]7W@EQ@H%!WEX=1C9OSS +M>X/$_[3J6>&KFH+)7G`<O.\M23*TLG!-J/D&$8T$HZ>GX&65._(TR@AS^^L= +M.CV=8Q6%LJB9A_PG];6HXCLJ9!MW\<K)JAI?'V:4R&`&[MGZ9HL(P'@#!@I5 +MR^\G=G_,UWUW+T"4=/:;.QY"M\:6<$^7@/NYPZ,5W'D::/.8`#W^H66Q5R&> +M/+VZYJ]#X+ML/@JG7=S)T2@O7R;D+&Y@6TJ`9>J>_FAK,N_^M5.>?YE_9VMS +M"VQI]^?;9,D2H_566X,TP*A]43?;2GZ[:)W[=&*#=1H6>R>D"_"6A_V:_"DY +M/Q_&IRPNCRW'L$WN&0T!``NB1@;'"$L00U@OZ[>^))J\C!!?'/`B"DBD;46, +M;1(_40$I&6H&EQ;H5TUWLDPIE.L/PO7)T-S)ZS];SM*,.:%:I0%+E"MD`8.X +M\@^`(,$7S?'^;4'M9Y2^-3E4Q!-<"&?5(;C<<COJS-+/P>KW`U5%LP@Q=!MK +M3@$#`Y!&S\3U>=*-.S\X2&"+D1ZX=V@S_)JF-U]G+IK2(,Y=_.<+H\O@@M.A +M5;R:LJ&IE'R]XFS<`-[VKWQZS5'?I9,U5BJBA,KAT6WDQ_5''CTS08%[E@0; +MX_`+8O^A`A01/V1A_M\<#"-798:/<H,?=0&3'#D9B;4,\Z^#L'3.,SNOQ1=^ +M#20&R21["T<13"AWSS0<P<`B'J1<"T:Y*Y"(?`;@V"SG-G4:3IK@8(Y8K#\P +M""NQ\P&[G2OCNF#8H>"$:WV_RF$_[&7CJDMTL#7/'=X\`I^3\IJ%BP;C")9G +MTMGE`)A%\VBVE%8O6",J$($<-<9Y+A+UL5<Y8+E`;X!"U>XIP8B9EF&^66K; +MCX4WN2LV<D=U8(!G+[_`DL]E>VQGU?+%D0!8,E_;DV`HE02%RXJ-Y+&XB8@Z +MN`F,2#6,$W03H"G`TP9[DY'T-]`C]':JVP'MT>X@I7V;'U\9(A=#*VB_%[DK +MZP8FF+SO(#.Z.`*&*;HKH59CC9C8@5$^+AC65^0K>?'4K'<D5/19'\`P5M(" +M#@^Q9L6.3^K%C461V)I2V>?L]`7;[-642(^\T=BOQZ=,D4^5$N.P>,,SZFW9 +MA/$9-+KEC!:/KL8/6;P/#5!%`F<U_M4$O>UH[&A6'2;?T_7,W(FOH0*K2)', +M"1GG#/[?8Y%0'>15M:I'BRCL(:F+1]./SO0ZK:;C^([JK]X<O7];2?/;V>XZ +MSS14Z%B#F9!C[_!N-:'#PMGRPL+D%B;5(7@X8A+!JQVDVTD[@N1<+/7>D:6F +MW_6P3FI32CQ"""3%3X\A'4QAQ%,T<?%@VGU?,D8%_?*6)195'3)Y7$/!";7Q +M((0DO_FIR0,-[/(,=5P-O/XA0.=KN,4='Z&55^KZTVWF9LVZD+^-1WI`0X<[ +M"N83TSMI7NX3HR^1!]^IB#SAC:,'WY/F(0/+P^#GO=H&ZXOHN?X@8X&&.@GJ +M03"^F/-`(B>[4*O]E?0-?]"I"J,$[_DH!&V=/MI-"UEM78,U00=IB6K<*EXT +M`RM2OCCJ*?);/^$,:7AST?S/$[:L>2E-67@[UYW9,,R7"5?F<W*&?W^W%L6] +M-+J*/]?;'<9K1!HLB1#II"_>_4LA*,-%P%X/DBQL>ZOV"@XJ1%"&)P06;N9& +MY]Y(6-S<5D_&005R*1B*T<O?$YQDOO-1MJS<VYTB<2*!ZV^AXGI(X&O`"HV% +M\+\XRYE[O1O3EGOVHOIEGE_)W\MUO-GM`7Y3C<8_R\[SPE$X_/R>H/Q<0/\T +MRV:EX&F2,56RHHKVD311.T([V@H;06@VEWQ%\%O!/8]&]`=W.U#(MZOB`8Z: +MS!WXTC?8A_0<799BO[9O[,`16G0Q68OXL@@'TC\CF460<`(`IZX\HE1E<\!" +M(T2!/K"ZK6HI6"]8_[;/(]D7LVRR[Q'3J3YJQ?954PZ`F`6!PEW'H\-^C3M, +M\:+7?BWVPUZ.P`H<5M,L(7P@/$JYK#-3O)`T1(8'<<B-RNT_TFUX:V&!`^B. +MRL2$4+_O:Z6;:9#TZ<@\T2.:CIZO3%7D,B4V$:&,(+J8.6\<R754KYIW]XH? +M3>_+C^.X6]JD@D[?E(1M1$NGN"MYVRF_;_=<MT(D(OYWF&77?)*QTE]CJ=G' +MN8>4+D4/B4>A^&/G*"?U?VB#JDZYDQOEYB1@LWK">I`<=11]-N7IL)C2J!N( +M1MZ,++,CQ$A.L>^3.5H1P#/2"X0EE7$L=VB2;ZV@>WBF%*NG@XS+I``Q;WXB +M`!`C(@'^K2$"\['>XO>;\(32M3B,E;RT,?$:'\2\M0H]YJNGCNS?<#FD<(FC +M$X"G1D@[Y@A->:1,]4E'SA/+KL/+NW*^`T8PG@@4XTXA\]`+D@*UD8O2^QNY +MY^:'8PT4@]CY?#I@U"!.&<YMK=EO@,)K-5$*92@F,&%]<S($31V@N9JJ8_D# +MGY\S,`.D57`IO0>MH[E*&UXZ>056UORL$,Z8U'7[1[1>KRB@!'SNKIJVX`:: +M-PUS[;6Q_8'R+0"K,8D7FF8<A06=KAA.L1;09:W\!W1.B4S*+C?ZUG<?YA3[ +M*LT57-+W/4+Y$K<D!R?7I>*4MH#.4N:,'C/8GLZ)RUCTZ_^^/\S>EV>P&N>X +MC.ASXYX8+IE$UI>KS7W]J$\#U#YUJ%9-R%:I\XO/;"X\=YGG%33*"6>T"-LI +M,631^"?#<SUW8JA$8NX=:T@5F_$T/SN0GL'T[Z24#4:OVM-(KI);8%>JI`@+ +M])B."B>U!GU0`DJGF12D.@7"8XA%3K\O5K(W%)S7C0RG:A42;=-!DA,XP^^' +MYE0ST2$4ODP02(E@"RO/#V"DR,ND88LBU-^FQMH$Q=:Z>W*(LL[K"RO[1HE] +M\&9BY:(=5G,D*.$&$7T[6<&''M4W!,!X9+[W4.<*5)(*%H%E`;5RW[;Q_CV7 +MSXT5(8J7A`3UGYCE@T8U&<O!#E'8G&5LG99:LGCN0R*EO+`LRDUOUUUU0AE- +MG*KO8'*+RS&$H3>;>,>C!>XV^7?#*F=;77-JUSNG2-@B*A@5..Z5PJ`AZ%S' +MI\T(%Q,0[VZ#A)=<*TT@I_*V5<Z(2.G8&*&\M47XEQXC_T4`_7*V3\+;+-QI +MU^U02P,$%``!`&,`C+`.15X[\;+I*@``K7(```0`"P!.15=3`9D'``$`044# +M70#&_:ZJX+UAQ>_U`MLH*UY(^W1[`S0"#F3;KHS%E_JTBO\G>B+ESZ;&:0-W +M^W(LUI\\7K'0SQ14EB0-L*\1)VF'F?/@KKN"VR+^RG"CB8Y<.*A(4<3#J#\W +M"<(36.A%";@0FW?L'H&+M68_NE4\)'T&5*]<$I9@$&F!V<1PM:$-$$Q".RS> +M06L$JC1PPS-2D12T+G[$"[B8EK>B'1ZK<@#/-AAGF5HRK7?WL61$,1,FGQ#! +M,"H/_I/J@P>7(TO=HYZOWI_E?3(HZV.-7`.D=RGRFQ+0G2H,CUVL('(!?2W4 +MC6]$K9BD+BH<07-&,FU?Q[>9E=IQ]AA/U^P"]?<<F,,.AU<+7;29=5\^3\_6 +MY'Q#^.)XP,JK2"KL2%(+_H;.B&0/?HU-C6#IU)ZPI_#M1'2RJ$#E(P]^-NYD +M4AUM7%JS]_-=X8`@U2N[5D"2>!6]T+K3T[I)W0``6!X^9-\&T9()'A7JP+[N +M1`3%89QM*@,N<SF>;4"F1MC?E*D#+._G;6B`29V&/%`C^=D/3!_AAWE/T]JE +M$6$W(XI>#1^QU2$<X7WL!'EL],0I;1644V2`HBL\34LO=UT&*WQ<55(E8)B7 +M+]&:KZ88LWW`ACP:Q6P9YX*[8&.?]T^?._<[:]4YGO*S(2@Q>%G$`961-JNF +M8"<K]@WBL%UI--,/1)*#LC0D;P]WT6L+@HA\"_:B`OGKQ^^39_5'C_V#'+Q[ +M>&XL%_YM!A:Q.IAM4"\_&"PL>*=$[H%ZY=?'1XL&3[*@ZGUR!J1(%7<$%,'W +MN@=!J!GGS0N,*EZ5YH63T#):K!"Y(+3?!53$RV?\+H2^*ZGE2TAE\Z:X0CL8 +M,4NMF.Z;*S0&T1+K+D5#/Q`CO++*?T0<M;L8=Z'WPW?>;]M$+5:?F*[MN*\@ +M"`],:7IG2OF<RYP1\VZK,RL9B9&+0(5NS-E[K</ELZ:(5W^,=YX6Z1=G$A)U +M6N15):;]A3D&43,(-/U?*]0?*<-T<S6DI9>'2`P0Z%@[@4*GVP'^L>_J]OKI +MB622M;RZX&_A7OXHB"</<E3">S*0?Z&1>#2)76Z=X5C'9`\1GM*'O;1#-%,7 +M=@W6/F>YPQ9+CWAAZ5U#[T)1T^.(])@'5<7&@GVP?2I'FO!56/M<PYYDC#)G +M'2AZ%L[&9H/,L.]\;2^S?WLK?6'/R[TI9;KQ3_W8[4=`7W(;E4DX]`8D'?PD +M\8CC61DJ0]RT84"=&>1I++?!C96/^97::DUG*>-/UC;B(N'].A@_!IV5#5MZ +MCI6WTB#F8T&7BH--9&K%IQ@+\K$_T`ZTG#OCHQ<;-```*YHC<+@!EPD_?N8_ +MJ`O2\D9#+9+Y?Z'1])JE(66S!G7A;7.6U*_5+^WM^<K+K#3NZG#I3_[U];OC +M[.2H!]8!&X,CO[E]SE=/?#=C<@<(R6`M5'O6G#"4K=,Z8P=8KZU";&%S6:!J +M?I_D^Z-')$@NY^"B0"E6HYNHJF2"\=Z.E7,%8BC>B7:^_6,E$SX*7[5M*'#J +MY6W@"$E`DUEPO^;'ORM)XB'SZQQ-JE$02_Z<S<^`@.!MN[,:F`6,WC-85U=E +M;N=[]T%T9#3%//J`LF??-R^YKOS\3H2@#AGBLB1'E\LH[-;7?)7-OULZ@\VB +M6F;YL#%C3/+X&BHR+&"AKCKZH4X6LT8C:Q%QV/F5!("#1<'LX&GE00ES-`KG +M)Y<\)8:L(6G0[KK[2+?M@[%NZG]=F.'SSE0=;00QN,K4OB=]=P5(3N+Z#I^B +M+DH"9=P^X`5]?3?(!48OHN,YBH^E;!!5XF`A`B.S)]_9[[&D-L4K"@]C9W"V +MJ7.A9P1[>5V!GQCC28(J>+Z!O,L>GSY*4:$Q%3\S5773'"R?3W@N'/=$7RSD +M!:<-^V70TVL#:LR<@[+UNQ\YB4+6/RQ=F5'AM^,1C*W11;6EZ8JXMM*0_WC" +M,FBGE@-ZDXG.WM40;'N+#6\CMSA-%K4NU^>6M,DXV#!/#</.EK"I#;-$N"5T +M!'GS6H+T2Z61[A*77)_#QF'ZE88#\?!)WV9E?Q^RZ%OA1S3<1N4Q>"P*3GS$ +M3#'MY=LMI[DQDCSZAWP;^3]894&(49L8;[B']*LP-,CSXKHLSUQ-LPNGFVY& +M:<:::A5"N#`E.@"!)-U]MOXXX&PD2N)6X>E(D92LG="<':P9_]*8%+7V0ND2 +M%8_TCY%P@-*O<2K*=*RX^141+EF'67L='>.1^^Z6.SX1%AUB,>GFW>&/K/06 +M*U1ZN<0KLVCV$V;.O5P'_T*[YB8C6\GQZD>0B[C04C^JBRA_8=FQ=D0T81[X +M<X"+)!1@(6<_9*>IV;,TL1M(Z9](UQ3MNX(A]1&`0(NVR)>70\54[8N/]W!M +M0(I!9NZ)C7]ULFV_W44%"32'43P!(_BRLS8UGLF[C.<#>@KFK9J7^0XFJRC_ +M0;F;^0#\0DNFQ/:]&Y,V_9C0T;9"6M`)37QW=27M2W9"Y7?GF1#I$$1V,,(N +MNFP120FM6AUA8>\:*F8(4XU2$T5T)!(71E0.L3!F;%^;:8V4Q02-J%5-4DNU +MI>O=>"`U_?$I:L3OIB,^C$&%68TY<-Z?X98GJ)%*NH?SS35[[\8=[#1L+!-; +M9EEK7HT[(O^@PO]_/.<C99K&PC7\<HQO4OW6C-OCW?ZW2=5$011B7=&HD\R_ +M7J=-YVC;1;&1:W%2W]1R/E$B:FQ?\7EIJ)B2+%-:L+`/DEYAZ^,EIW#;1'"< +M*-1M([18QGL93*5ET;NQAE<0_;6HB*)S$VUQ`U)@/<=I?RP6A`1C$56'-0*_ +MXJ4+B/&*4P!</50]I^";IF9"NU3?\1TT9&8ULR&:_'(IQJ>'E8A#.<&L8.P] +M#C79-'2:/1>\O$%N)?['/F5_BFCW<$6\SDE=IINI.(NNB_S%>^'L5[_@!E=7 +M-6W&G*CH60ZP!!7"O"WC5"Y?);F#"!5)JYF:6LJ):T_@G7HZL2`>!!2];4FV +M.C@Z.WSOE0C\/(FKL>99'DOW#SY4Q#&4)`!L[C7NLW-\L&3[(->J9I,-R%/K +MI0_SXN?K&5$4RSQ=[]2U(D.XY[0^LXD75Z&+S!ZD!/!"?^E6@"WRIN#3:28: +M,?Z5UXU^>Q?3MJ$V"3Z!@!`$1JQ+/76%5X[HG1YF7#2.E2C"T2?PML7Q'['2 +M)(46H6[H51F6(I6U"%FST?;9E32Z>#\\"<!$:D1"\P>N8-N<?KE.-7L5;?=9 +ME"?U&3!41<)U5]G-@[H<W[Y,TZ]X5BSU&KE8A\HYC`QS!V&GO2LW<<PD6S)1 +MCPE<6FF)0MHX,BM.'@:3@3CC9R4[5:WW^O[T](H`@UOK?R2_/.C)D$-:5IA, +M$_,"@S,\A(V)1ECJ#Q*AN-C<@C[%2N1,9V@U[M/8(VPW:H*`3TD'!H51/T6` +M?-(-]N4C40(%#JMR?O8?3$^P8<@,D;8[X;;];K]L6(06H7IP16Q&F.%?6O9$ +M^X$?_SLC)S[)MISXCO)2QI(9A255^?7$@!*?R:I7.76UX#L6KI]FG=JC7H.K +MG6'LL*-0&2.=2!D8K[21(<9B)Y"T=T<5TO]DY9N6H1AF#2;MOXI!MY.D%MK> +MA#[/SA]J1*624@W.>4N28O+WIMW@=@.J2$W-/H1QZ:1>[":'(9+]77DHZP/W +M?XC67&,#/8?J2/V4(CO&1L.F#C/C>)8,.:^;O;RB&1E&[::Q(Y[7^TLH(;4' +M`9N>396!I&'0VKIU@>^Y_S8ID_CGQU)$%SD8@QT'TJVR;\7BO-J&$S5J`Y#; +M3R#7"?<B)#ZA7S/G:IU>YS?W;0W']O?!;_KQA#="Q"P1DZ,*?UTL=:'F`!T8 +ME>.*[RZ%M*7]E`HMN?1_C'_>;1\'AGPKP!.+:!F,.F9J1EQVVF#]^.=$G!FY +MHW1O'U+^JFD:%G.&L+<A3H)>:?&FI1B5*A0##-T[B.G*@WP:LJ72VA`F3#$T +M:/%?2S<$-!L="*KTH@5T\K2;.-&J^EGA25RDHA4K$.="SG#&\E[DOC".YSA( +M\DI7L,??T=\C)5R'X6MB0L+L_/><N,&IY)=WF,O0@"?K`U[^?X7^8M1^LBG= +M,/_<G:'G#EY.^\220[9H%%'.GX*`$E>87"YWO5BR)^$47%T>R\4C'17*P!>C +M^^9L<Z/@IN4[RMBELH5IBLWDNP6GTZ^'F*'L_!Q5$N6\-?('6QWAZ57?W-%8 +MA_50M@UM%)6NX%]/S"TY!W:4PZP_@5H17"%K04=$!S/I^V&^A)7.*GCU98&4 +MO@"[030/LZ!<2'&@FMX=]AOMX:RB*AZ=^V]\?T`\\3:?8RS*',)!0QY$<4^T +M3DD$G&IWAIVR#E^P`B?4X#]<;J0L7YWS>JY;O@+,04XV(3L@4,\6N]B07Z]% +MIK;R--(:Z^TGXZ/6!@'BWZ$K<]"L+(ROR?]-LG\*]XB:#G@9F/6(ITBIYA"G +M85($OS*=;^XGX.S<ZDI*?*\"[3VE#W!7T\;0YO9+;?97IQ:U'PJ"!9FXD\JQ +MGBE7XZX*IC,H;1PS""B55QWPN-1S/`W:]6X[]R32*#XV%=[%U';CTWG'AI6] +M;AM:_0O)P7SY-%"JTZ`\";WJS2(2R.<*H4YLS2MBZ)L5WA"]KE&,ZQDI5<0J +M4@281].^0M\DA):$4,;%I(V3X,MEZ*[]#\"JT`&$IEL1=44H.%_<3).<,"NY +M(-#IC5FJO1>299*Q2[$_UA*_:U_X)Q5OYCP`1Y>?*45-H$'LKX^77)4K>$!* +MH,7)>"^5`GH';J?Y%H:H7=O;T(RBO&:<2<]I(V6IVZHTLSBPA1^X[5^J3,<3 +MRIPL6:.?`116-$!"$7(+HBBTCXKB`4R#.K*ZTP/CP"LB&1_3=?U67:MAHD,E +M/-R6<(114M7W,><JAKP]B$U2$HLSWU?W5*RH_M75^(T:0&O+C04.N4LU&+;E +M]QZ__;R#6WA^$$S3^^*GZ^-@X!/W^53'QL.=W23$6I>=9-;?$Q6AW6"2`,V) +M0>]KVQ[(%E$]TAXK<[COASA05%V,X1K7A#4:O:OK0I?JY67E#1L-F,"J]JG+ +MGPK0B4B4J5.D,1$&NXYLJ'VEE@51NY*+'0[()HP,ZFN5:$9-TU-&4<+?<J0' +M6E/O?8H--_>E#R%E>2>!DI[*#J:,/R/RT_^Q.Y/?VB,LYZ+M5&D"BO%4:N<U +MB6E.)A$R_9<IQA)U(I[5IDC6TX6GGV=9P'EI./%@@Q05R_VHH6WK?XII(3=, +MGJY2CR>HCD>*'S;LSK>4P*I`?+[I+ENXIDS7"VT4I7T.7_98VZ!&*8U;E$Y# +M@\F'8]4NKGB(K7#U+7O1!*@77&Y[B.TQ"A#;B,+.8%U@Z@?-U$?D>R\D5X-@ +M3ZB%0A&H\O0C/9\1#1#EO@N/ZU\4ZW1Q#O&%N1YAQTITUQ<\;ULXKD^&CUO- +MW%<$Y>Q&"=,KREBN@JF![H;J$C87!%!_A/J.2R#1R?LJ;9ITHU7L3MH>@@WF +M<HPD$&8?LH>TE2I8NUX@1K?_IW:$J3ADVS*2\TS^BF+G):L%W>46M!^B:]&, +M1"IB)*BF7,XX@K:[#6U*1#8UH$+K\&7A3F`=N'&L!U\L\QR0G3MPC!7'_//K +M]*'M:;KYIGUV6N]OM*:1.H!;:AGYGB`/TM0ASYM.WWAB!W4+Y\/:<+J<S[0Y +MM@1`GAE9S3.1RG7)+V-2ON'IJD^D6R`-F%5TW<AR)7D>?%=^<8>/#KG.I03O +MU:=C\D__6^9S=#'T.!!SA!CYF\&&$U[O-[XB+<_*W2B7NYBFR<F*P/C^@J3V +M])UDX1Q[;<_:>+J,AF\BK%I8QMR8*'LNH#_1#B!^,^_R'PTX?;3J81BI%(&5 +M&+QN3,O;?IN)H)G3"][V^M,=>6=@`XLU)C-EQ*%(NH!UW$))P^5@JOQY(`QY +M?42;;J1EH,JI;4,$U63FY=GB87I@9>@T5G-.#09!\R;9T9$<\J/7EFD+!2S: +M2DD%?4L<.7^,:!YU'&:D))$A0_`*W]V<J6?(OW^':`='5O9_S+71?'_3!<&J +MV/83^B"6YTAG\&,?7)^T^9/=%`9Z=M4@_O`21R[HY0++N%%RKS+P;4Z&/6\X +MD`/:3$M+XS1IBW#!]2"T^E'&"UUQ)RBISR']ZNB(K,UE:V7O,X)E`*KU\$C[ +M=>MD;\+2&'H37Q-&$P-T/E=Y.O7Q>J$N9FS`:9OY>2\4IX-"9CDX09?%CR9D +M]E_?^[RIYRZ1LE_.&N-UQ[&'%628`Z@]-0#HT23,&+O46(CM(9RA9B?$':?2 +M(4K6#<>Z=_`E\:R\_6?&"$B71-\.5G@*R7N0S]0Q'L-8MF"O1JWZ[A;SL\U) +M@*TW#?>A7HW#MZIZ*+[3#'PXF\1+\_2U86L^7KS";)M]L(-_"RT;@F!2/^BW +M8-%[8]O?5%U-IF$6;?]ADL'^;WQMQ?7X4F4(17A6"`_C3>I5=9DBYMQ``:.9 +MH:)YQ=W]CM4-5@H]\_,H('.!,X,V3CTIP.W0AC6"`^8?'A&[-@CQ#?#@<C?E +M,1G)J",W`+DRR5^KV>;=SSN';1*_'&8U>+&NQ9+)9H!9=P/Y[W+=H6`5+YM- +MNW2<JTMB5B]07UT&$QJ;;SLM[ANSN;D[,BX/6V_HF&0Q/"S*4L6-(D0$K)]@ +MZE8RM[VMFX2J&]45VK'"D2_RA4V<%(NN1!63LH>:V4<?=*G!_EG!(O55/E+I +M@CA=2H'?1+RI>FJLC97P`75.S;V@1A)G8VF<C=A&:!\]Z"R$QWB/11OG;.3O +MC0*=Q.KTY_.I6O\FX6T+J0]8\X?K&]+LPG,CJ4$EQ'(X'S#=S$L<C(BV6<]D +MFSG@>M(W0"CVQN4`1*8-R.-2ER)F&OB:_S2@UW!Y>;^7(:M)Z=XR_TMN[TB\ +M%'(E/HNMD'"3_IMXW5/YWP7L*B_K)Y?RJN!1;3/],$N*A)-4->NT8?GCC?J6 +M:N(_#)4(;VT;8&P;OT&8'!4Z8[MG%1,/:YO!SX(_L/B2)RVM]KK=U#$'&BMG +M4&QY6K\?WMPM2::C33@H+DBJ?7JL"/@[ZH@\&]./JQ+8"L1MM"!%0WG$VTVR +MC3W*J6@MH;>U0K\Y9PLG'AVE>A*CG-=9@I3_%<8NYQ9DP6;9J7F^C30W=O>. +M:>!)?![]V<COGS480<^A?G#NJ;FK$#O\6<GVCBT\ERA$7KT:Q5NU18)@I06) +M_Y_XP]+87;E@W0S5CK%MYM4AOGKD<UUQ?,B2S"'/A&/-)MS31?FQXSY]FK(X +M\NK&QW3,EIL^.+?^&A*CJ2W2'?+G0!4P>#\3(VL,3G,Z&[:BE?%:M:'64X/M +MD)GK71#]@X?.U%#)AB!-3E5"7?<^.I>-98)RM;'2L$%Z#B<"6>>CV"1%*^+5 +MMC.3\A?62^O1E^D(K<#](;[FIQFLR=+8/I`95MA0RN98/Q58T)^\2<Y58#XY +MN:!2+P0-++OJ@,IO]D<!N:W%D^&.,2U/+E\,[)"D4KE6#IY77#*#2E!&DVQ$ +M)ULRV9]/=!4CLT>,2-Q@`^V`,<;6-V9+1R87E;EDMT+CYWQU=].)K^7X-"3< +M;KKC2JKQC:&2,M3<<EDU3CBV"MYBF8HBGW+8U+$]SX_`T"35&@>H(S"-7\`- +MAHVO&Z0-QDR?$8Q9Z'ZZS&18`",N/>CYK,Q,,U3F/T,8*B2H4V:O%K'LX4`K +M^'3;.1X@`9Q#HTK)^$U<@?)%G7[\75.0X>^;H8&N)OL.OEE/%(%KG<+S7HB3 +M3`>7!',P[(G(P3?/E@G0BA6:@:)>Z"[[9;7A"@^_G"+HJ?%<#:D,JI$HUX;H +MU1.-[/U2[X^>QG!=U.-UIFDZJ7XVQA;PDV3)B@#5PXM!<QE0'[460"SCJD_, +ML0F&(#_F;P0F,#T.[`>5E3MR-5>H#U+,K3_T0(+5ZZ:*Y,$^@<72%\3Q=>C8 +MG[T<)BBW7B%Q\XL.OO4,NE2%NZ)_VLH</O)]SMM[.UW9LRYE"43G+0R-2H+1 +MJ9YDCUZ9+B'A3/M"B@?':.]DO!]P5@N-A`-9M+:8%_L_D#[%&7P%?]`06*1. +M/*V_/L[>PE)0?R>I/+6%/K!K'N1&%/6H$IMK6JQ);+SJ,YZ$J))I-CRN@`./ +M;'FCW#>4=*>.)(4NF8&(%H)+BUX4*BA?RNGA7O"05E*NP:#9X(VU&8KU+[_8 +MLIYE)T%];Y-`#OS[+Z&!@\!>A=Z^21*>]A4V[;Z9<!S'U?2,ON^M^5EJ/@E& +M5)R!C`S^VQ-KB,7V!\*6[T=Q=,29K74\TMB52.3!:8Z!5C/IO%KH_+8U5TT3 +M^`2&K;H`KCM'M(L8$^#8DUYI55D11>Z:_O'T&^!2[D?7N^!9/_NNWCS[W%Y= +M*K[3O:1KE<S5&]<^*HG6U?4\:R3F'``AU,5</MK#VF,&<0%M78_?T)6F$>P` +MX?,5HP4RSD2THK?D$'$:LJ?Y%Z;(&Y`M8^<%PKA$P!,PL1O;M1)*FPUZ:61R +M3$0BRD9(I!_.JH^PLQ35AJ<N&FW7YUGY\G//U*`YNJE7&&ZK96OA(RX1*H\9 +MK,`^J%@1]AQ;`KVQP`[NP*H]7WR@ME2,"=1+][D,$\5RY+XEK3`BF/ULM:49 +M]&*2F<M60`,6PU),[426CD?IR#K?MI4`-"6G6*GB9'XE]"ZD@TP>*N+C[WX" +M>\06FJ\B]%BJIWF"X&%-1JH)[P(FJ,1?@1,<AR-4E+1T_K7,]#0"\`)O'4FR +M97KYY+J3^WG+AIJJS%VA$6V!D/:17N%P-'2'?+62JECA>$<V)?)**]AG\UUQ +M@TD;E6,`1(9#,IZ%Y'I/FH;H&MVZ5H?Z4CX<5_]B>N'FOG.83F[<2ZCRR$\C +M!%<U&Z5YH0-EF),9"Z?&V=N7O/KMBDR,$&B`"7"$!3"B/*9-LRLM>S9%5RM5 +M.#L9`XG,P/!Y$2?#G9L9OI"#>0F$R!_>9%^%_$$D9:IOR2,U]-'HP/!W96GT +M3MTRG3=5X4?R5:H?P^?Q3"\P#(==C%"\Q952?3''LYP<$8EN&$*G,QR0.S;? +M4O5LARHZ9%[BH4:Z&2C?5;$N=%%SPOA2?B3H.$OO$2([[W*T#:_#GUQ/?OY! +MEO+F@\SL:+M_^I1:*%;)G3!XLWT/_K<WJZ&UMERHW@8N->*I>]W^ZQ`2AFEP +M(6MNR2'4?^XF]"0MHY2\_QZ4T2:3LL5C.#KQ/$`GR%>\'<5^KL6RI4?MVJ/+ +MZXY"!=O[_NLQ#-X2A:'X'`NL\Q#7-D,)@9=8_9:RHIL<..I1J9^W`4F%%I10 +M[3T+(<*9.<I,E>A6`ZK8'!QM\QZ:B,U8R68]@XB-&CO^'BI3".!A<Y\6U$T9 +M4/\P7$WY;2*_Q-\GKG'E[U7%PFR#>FA0`VD\F%V2"X*%1TJ@E[7P>:?"TUIB +M1##S95!N7C7K2($LNPH].;'E9#:XOU602-$USMP$G?")7Y$"SQ5'S!E\KWI6 +M<$--YQ$,&UD,Y3K??K<!"V.\^!+/,R61F>!;U(U).)GTF9(H-/]E!PB%Q.?G +MDXUH<^,)DJ.!N6Z6AG1IL>!5]T-N;H*"BD7`MU7%N)%C=M?,V!\C`->AK/.9 +M_+F>!%6U)8\711I]*C_L\.>0(<GFGA\I'E8WW=%GP'7`Z1II^=WN]FT^MO_# +MJ\;PK^,?!)$</7SY*"LJ@)V^[9"B;;$(,$V7>%1;[B!G>ZSTEA_@%B>^@<_8 +M4LTRZ".ANN,N1YOY1!*\AD?CCW21-9:Z3RLF9G,:9[M,,CX?3C@-P?TL$?FK +MKFV07UWNC;E49V^OST"*K@Q2P<^=!"J'A0)@!\G_YACJ/H@![+@1L56I15#Q +MX)"7.1\O#]/%(O\N@_#`!=Q^[FH(7TL\[U"T..L>6-LN\J>_<F3L$B^+X\]X +MV`W<ORZ3_3TH3-PW-8P*G65XZ0CVG$#C7!&R<57K[5Y5JAF0MWJ"VLF&_VL/ +MM%L"_79AZ?A?P#E+<"'8>N/A"[.<Z\&@#VSX2*S'O+A_PRNM=FG:R<:H`56O +M^!Y3A8JM"GH6*_'^Q\!T7FZCTY/CLL`VVI>Q?)TMUD8NC8)D6X/11]QXBW'@ +ME%?!7`,$+38"?VGW%()Q:GJ043M&\>OU$P1OE]&*H0B.X;K%L/A](+T;93"P +M1&U5KC_[+E<&H425IA%9]"7/@$%*.RMB#[7650E+Y@1S$$@MY7,9X=8V\QZ$ +M+&3:YPV""(LPQR;#G%]E>-5$/:$[0_WL*<U24@%0_+?Z;/["N\@,'HC@,$R? +M0%9]I]L(XK[8[K2+\C6%1J(VKPZ1-W+>5R3&!R?4Z01KM="FN?245E_IUHNQ +MM1"P`P]0X.K/F:MG#9<<`.??]AKG"F&&O7E]:^E482F0A<-,![-H3>:7J74N +M;#GS#ZV-:;-YGOKU8X%=#,@]KG6399V:@X`<0QZ]N,[_=_0"X[]8)V+[8<ZW +MN'6O2P)9"2N0?Q[]$J\8.Z]7Q15SY>@PEA0SH4%:<ZTNJ9[!O2B6CPKI/6F_ +MYQ21%[M(0VB/%\X4K?8HN6Z>4@72HK);:T<M'>1Z_AXI=%)\DIIA=W`0(0GH +M_O9*NN:*N$F58M`FB+OY1ZAY7U!48W&HP\.GD:@MOS,+05NS^="&8>3>M=^' +M0*M#HFAWK^"%G'I->/UC"V:B=V09O(CM,BQDZ-DB&$HQ#%HU[6=1^E@B'Z&9 +MYMJ+5D?\=5QH+9&B<,I#0;<X]$5=:TS>2S,E@DB*S3-/<63M7+-(/J^6D\(> +MNN^/(P#/<97E?TLP/XDG1I6K(B/^C7@92?4T&=+?Y#_5)#YP8+M"X_:?':B_ +MNL'E*M&>0$#X*I!HEG-%'MQ;<A<\^4[.MD<[/=79?XF55OPHE"_C:+HS9LA# +M6VS#Y-:RI]J!,8+X+_'Z0GPJK,SYF;^E]WD6L]$T.&#LO4O"U7$2[6F`#/+K +MNNVLD#:25"%ET]0QX?C.7UC*Z!N\W*KK*/_7RI$HX4%W1B)R;.`X0!#&UKNM +MCE:.NJ;9#Y*-84(W0?()Y*A$OAJ(_T@@,,(L$'#AE=6M]$:"]AK]Y>^>"#U( +M4S9IGFH`A7N`;JD318^+-^9>3YG3/GJ4*K<[3IJ&"?VNI!'N2T#MNS:\MY+8 +MVL'B),G0*.3.;+9V;_(GE,RA%$,LP-M[[WAB$1<4)XT'EE5M1,IO#5V7A0R* +MXH`0,*:_-4#"(H!))ABU4C5+,'T>`TL^*^]X_A#AR(?DPK6&0MW/&G;+80'' +MKF<>L;6%D@JE5CZM?V:>M;M,TIWNVT]@4W<@UK;PML)U%73I\;J3-S&H;=). +MG[;"-7'"1(S!`SSWVI%&C2VBJ&G;;=/@DM`<CX:1?I[X"5[8U:3%[/#U)G&J +M`*=TNU00QB7T_ACB<22@H%ON3$73^MV=N(0;JE_/LL04)]&U,!D%SL$3R['@ +M$7\:.>$;9]5B$2@3AE2G/SFS8/%HZ'P=+QJ4YGR2P5PJ**KD/I[G]XQ&6)/Y +M]F0E\0#(C1`)#79AB4.UD_2Z8%)5QQAL2MH4_9N0OP-EB`0<!#]B@M%O?SR" +MJ+`F>L+$_$4R0\82I/Y($.F/*TG<:>__UK'3Y9]&M1LRIR+_5]@M&1`,\4)+ +MVR.]+.MWFQ'_WBL^4T7DAN<5E:SX"HPQ#Q&.-HC(P.[Z%5`&JOH^$N$@J9W2 +MD@%9OW[)I['MWO$D)!9(Q2C)389<N,JX&3/IXUT<"?TFAN+]]%NFA[C`%I&! +MU'`?5X83O&'8L!L5_/*Q)5`Y2X,7,_6WJ"U.W!PJ<LI,I(5-5DO]D3DQ3CX) +M;XUA;M+NCHZ>%/DVZSZOIV/VJYW.2Y^:@R9]TL(E)>%I,)+?SEK><HF$.'>3 +MCGQX9_YMX1R,_@>PD9%>(.O6AJ5P#W?[619[MKT!GAOBB*,3)67_56H-/IKH +MZQQ)P8UQSX(/"Y&#'%/&[/4^=#Q%M6O!J>1Q.+"1S6(G)?_R)/\&%H<8^'`O +M9:!Z"440CK;RZ($L,BYMM'Q_"3*9%JQGVU("<`Q/6&FM0@1!+U%K?(@R::*Y +M*BL0%M.U/KO=<F?S4X?"DCU[?,`4==3/?RRX:^+GL?.&T<^G3UV[Q`^-6G[6 +MBD<X*-(.\+$<%D_[AZ);(F7I[+*8.5C60P-7;3-S#P<)O)5Z>F_V;N5A+K'X +MWC[%AQ:^Q9OP&S!12,?H,@4JKK]T=W`=_7]P8V"D-^K_F`]?6F!X'VEZY?^Y +M#/]XX=>-8*>_P'A8VK6*+;&*_66<0C?+F6\U2OJ!OJQO<[()E!Q_&/:@R/++ +MYRW#M,,6OO1XCA2]<DAL7QZ,'7*&+^1YH,`?=RU?&/F*A(2)X.BJWJ:YD:-V +M9TVVQHAV(^TB'FQOWA@\`*4JG0"5X)D!S,:JLX:';*IP>#A1@TLW!I*HI)U? +M1W/E/;1Z6'G%.14EXG"6'':>R(XB<+)HM\JZ(3ZO,/\#8=I^%.>QC+)F*=7V +M*3-V2A#D%:L2O/VMHA8-/^+:JRM9]6B.%BF)--9J2D.F\I!4!DV$+]JG8>?E +MC8\%C3IY#3]V^@N(8S!Q.,E[!=0,<*I\3;FXZA`G)@Z#6<7)7G]KV.)?;7L3 +M/&_9IIW;PVC%9@E".N?4;]/G>)H(V*HD!X^9QGJ";"'`D@8&V+Z^@GA.PX-= +M/?9*-H7T:TG;3!E(P4NP:>4SC9G7-JM=N/<4XLZA^P'E?&\`TU$8/SW:!"[G +M(//`OWX,VWIM/H*,IW'+PD-T&[?_$FZ+H]B6=;'"Y32D\%':L\&3@H7=&@1; +M'-L5VNYQ#CP\C@_'=%$#:W+LI[[#':EX__M0V8MV5<N1Z/@TVQMAA"3C[=;^ +M:BANUI!>U#(?Y<MTVO<_N&[JO>.:&-7J8C"%%1):>Y)A@B]3E[;N&MU8$HT[ +MAT/BX&*\E:=?B\?SFIW0&L_D=YF7*F8!^7CI,92%9L*`.GGV38E/K>CB,"GR +M9;C`+`\;,Z=&-8#U(*I^I5>*;)2<:8FL2)"CZM,YJX,FX!AV>I3(,L%5Q11* +MEB3]KT9/0[!A<RVYU=><4&->][>RSZ">WG_;H6"<#<)W&Z\,'4=BJ&1[,N), +M90]PDQ*1@Q$K9#"-;;J,1F._62!&[47)](JKE-JWM7$2SCF[`[[M&W<%D(/J +M28#7P5[UJDZZB:U\;]\)I#I@U(7(6T3&=5C52]YHV!*:B9RN,'I$%_@P,0AM +MY,T["B;SIRAI`DA-7`I)@:0LDHV&6V$A56QN&>-"%#N>46:$9SQU&Y68<#%R +MWJMA2'I#QT.8DXQ7MMY8]WL6JUT4T"!"%F<)ZT"R+*A33S0*O%/^5?1\VECN +M)C[_!?!B7*P).>0$=':[:1686A\#ZFR#KIB.WQP8%5E5\\>.I8A'O3.<75IY +M44A]U):=MCPZ3.P9L*<<,QSJ:?6C`,YX*4/_=*,H,#[H8D?PC`J=.]R,[$2; +M>/$!Z66,PC/2=))O+DB\'X**^-*B,%PC$WWQ<S(7E]]=T+%BTQ464.R:<:U$ +MH/7:7%W$[>+^(GEM,)O^\+QID3:9G^\DICN^8%-2IF53G95!T5`\MG[A$GVN +M9,X3^6G*N<WAL,+<!VJ-`=Q$$OZ`2&C6J;?:0**,A[9..FHN7RI\>'=/(`/O +M%"%HZY\+IRDC.:)SA><0)#>0741\HEQZAXKCA/[$@%F7"=W:@FPOSD/=A`WQ +MUNEO03F.Q[U(I@J/"Y^\$F$X.<S<4NC!OL2L?+Y!3/%8(.)AWL$A`[K=.C9I +M#"`C,<QQYL$6@+KA7<"L\2D,O^&_.4U>2L1B)W.0;.#/'VRI+5N_D=R1\U_Q +MQD*!.1)<:Q*04;'B0XX-JKOZ!"#3T(8.RSJ]83`JS8"+1[F[V7R@4O_29A.C +MSDK#\'J-]_6OP8ETLCKKRT#(M=_](CV<XNSL^9<&+`\2U\=W<THJRHH>*`WR +M=LAM:]WPL4DQ0S\2@J*=07GAH!,@B6\*/GYT[$R^Y.W]8^_6'`R$G!8^]XN? +MHA*JJ?5>(D?K+?,RO^+2.`S[!W6N.?V1+'FS(DD^$NYV9ALI`J!R-<CZF]0M +M*N3/O#]CYC\-OT\[KE,1$*RFE"YSSQB=0,"3=$^X.@Y*]4)DHEIV_BYN9L[I +ML4>.5?V,41X7)!XTDK5'"?EB1S8A7&__2!@,B&^EQ>1(H3R9!_ULZI+2=Z8( +MH[F^>!]OV^<+TP[/#830Q?U.4IMJ\JWLP<$$:-QOUKHN_,)C[R]ML%ZLQ_D@ +M>#5-NU*0(GS&;`<KTJ/"PN1(W=FT6SY<Q=:Y[%MB$=K-FTZ8!^FY&3.E_"Z0 +M(,W0`N++DO*H84N\[RN,'X5!-M$]C(IYT"M9:OFH\AH0,#'21LLAX5">?):Q +M?TT(';MMB<,D)JW"PUVG8+K5).8L=U[(MR9>V)G5<,W.$.?#2!A,5(NK\9:' +MUO]`>DJ%9U""\?H+_]MD34%C)[MR>:U-MT(HY!8&/.SD).O.?3HF)TC1"K7S +MG_-CX;&O)96C$3WY/-@SL7'A,3R&"/4/LER="IU\)$GGQ<U+>W?B"&R\5%.T +M*(V=FI1\-[Z_+H-L;MAX)(K[.O_>77)-(F5R:P,F9_)'6^E%'7W*ETS^""<B +M+3^;K(`S0AZ6H7F"'VIV>/WRO6Y@#+H;#!98`ES3M0Q'9>T`<2`&=L;81`_W +M0[VE6."?0N9AW??!,D(SM793>MGBZUX94-*Q0J^+L/!4*^#?RJ.CY_\R&B3* +MB"!-_[5/NLI*L4!IO1N*(\TU6-R@K@?=$<02?N>EJ"*[7.9"07,NR'4'.`&P +MX7%K%-/]$=*HJB1(*%7%M7UCM=9*X1&(5[#G'OW054LXE9*V^$%R(3=^1=.7 +M[VAT'%HOK!4_S06C@(.ZL],^M7N\LOT:!5B,(^+*<%[[9CTY@R9JS[SZ_WM` +M3)WMB+1T?5!+`P04``$`8P",L`Y%NY!-AJL*``"B&@``!@`+`%)%041-10&9 +M!P`!`$%%`UT`UGEB'26CO7-XW(6S0R5R:M$?6P%#-4#49UR!$?1BQQ`9FV\X +MCF0\G*(?%H,W\[#G>3X15:CSR,4.&CV(Y.,@=B57*C31YOU;35RZPO@=VJ>F +M+=CP;,J`C*<-V5;Z_%;*S;GX7C!8-21U6XN)>$H`]AM/,.95<*LML_`5ML$B +MS'DX35/MU<O7ABN.K'%(\SZK![UD%/X4LHZ?+W%H[NK?R&%SF]DYU'J&::^L +M;)+A?5D:N#^$VCE4\7U+'(D&V@1;O!*?'PR6@6L.Q)#\/(C`Z2MZ#-MF<1C] +M27U>$:9_^6\#,2M>6&3TSB=IDNUPS$\A47+P'$1NCB!6<P(XR)T[%?<!=/+X +M(?-(U8]W@YN)T]$V@G^KVF>WK'Z[U+0TV;',,`]V[&">#1F"`[&1(45YE`N) +M=W!@GMUBSMG8691$GIN=`,,5)RGUDNW!]([HS;TU4&DG2J2+".TG*PD"@Y\W +M%H$_,R7?-50SM)1H5#U+&-6CT$;KPT7UQ,_B7'$GZCY1YG,Q(([<5"#T<#3; +MO-'L$"8BM^3?TC$XRFK4X6)VB'NDGWTL^8A3CW/KC*9M([0?'I=L['OZ*[M+ +MK#-YZ.^).4R3Q0>P(.'0M-AJ@=KWBRIKB'OF=\BL>\Y(.EDAM9`"1/_P"']; +MDH<R0@L"^25OP(B+\QIP8).IL:$U;)OSGG%0"RJ,(%W_A5Z2@:2,SF%MSR&2 +MW'TPIF&[N(75>-H&@'F\+4.I2N=,39MC8L'&XVHU$Q^*[9WX<9B^<^UZI+V2 +M(=`(^&*]=<!I]57)8[7132+?Q?=W??<FC+6G10@E0=QL'@BRW*7_;RQX0\;X +MR+\E<*>BI8"OEH"I;;&HI2^CK^%QF\Y<?EQ5F<;3P/7'8N;R31XTB%_H<6-? +MI)02[<)NAGG_RG[?6_C,0VN7\]5?'!F$')_%:?=`H'B7Y>(9VU,+S=B`P+8? +M\$D)_KO"S"5<QL4A#KNNA\BR%YY$JG5GZ\I#&]ATQ4AAHAS4>89EO2NQ415] +M"4V%!AG)502-F"]H&V2?E4G:MBS6VAG8_[,9<W-]3[QCORF!X/!2(P<,@(-[ +MS5D_.8IB%%6_UZ)L4SF/EJ71P(E,)+B,?W3?5R+1,*.=R/><OQ.:IV%_/WPZ +MPO/E3)[PFF-,SN9MBUZ`MG07X`NAZN?KXH4.LI!5DK`N\IRV&^Y>S[PY71%/ +M*?*>[FF?L?'B,>8L>CD%(O5D;BY[C42HLJ^F&3N./RH-R&6,LL\IR)H?9TZ[ +MD]9!KO<S.W3#H8$NU^M#A`/*;*^*BS5(/I<+,SC)MS!8H#H`R+HSA6.&7NQC +MUH+D>U>#VTN1P'\IO?4Y^^WE)?Q&?<2/A?]Q+TN(A>`M0RM!.?#+_L>A62>% +MOR_%_72NHP8IOK(MZ8SO>BROJR`4IQZ`FY0J7X!-97M#,`/W9"A>XUQ9,8XR +M30QF(,)&C1_.JW`7+(L>H'>RX!(N?9-::%\V7]O&UT5"I^"\7SB_4;2`C)N/ +MZ<%N%W..;)UR"'=74_Z**TSF7W=I)A9LA(><5>$TXR)AB;1^T(1+%&\,I!?C +M6GF,64`PE=L=@?H8.$\\<">1Y,SHXS%6JU([U=1-,/H%$QK#?2>.5HP;NL+[ +MV=HYAE=^$0=5PMIVZ"/J>""0.^L(DGU$T[["CV[&CL-\+PO%#B(&+@X26H\W +M<K-5C#]*VE&,IC$RXT:%S_+FQIY<7@HWMF3Y'V='U]U$#4,89RLI%01(M<+0 +MWTQCCX2,Z='U<+;.['%+L?9=NA4_\&"@P,:7;U$]G.IJZA?LJ;D(L<JQV[NC +M+IUUHC?+1\\#=+#SWV4`?9H-3=X3'*+/PNQ6J@G;%(XZC$P5KK&K228B&0B$ +M;T4X-T,UZ?B`V1NN!NK-S)3=[!U!MJ`!KEH%>LNY`YH%P"R*EL_+4:RVG<S5 +M]E&F/-!J\>C/QE52%I!N47&@F$/@I?JQI.UB&I,FXKEA?4X@YCCMN$1V"G`5 +M[[U3$AI,8V2B(I!+,LT)NE/@23;/LCS^!T..SX;?`*?,HV&B*1&`I"S#$!"F +M$B@P@Q`79PV%&)P:1V@8O#LD+\,@5\'&(1U<ZS'0.-]^*%M/.Y(X8;2[YGO> +M*?L-M=)DTL@<[;V?P%9A*%#BTN_P`M^J24QG#M)BC*TD;[`:R5KR!W9\.SAZ +MXH',Z#&T$@^A#Z1W#MQ1.KPH-=]WD2+1T*`W[Z[5)9?!E[5_?(5RW-YF:6;X +MPBYTF1!2-*P5E[J3NJ&K(.R+54&<W*I.4J<,+DL)9;+Y,(RA&J5T2X5!7'(@ +MY2C$($EO:.HS/7BA.U+YY+Y^QC&J=?W`-8@=O1Z.`D0\R7[XRF"F7$S=WNP= +M,X\0-%L667-,#YH\W@+F^E?7)GMS_#3R'TO0X&;K\JPC&9E:X$N$*<E6I%+F +M=JC61%@9$"QFJQ.A%8H5Y=3QIFG&P_MTT,S$:69XO\F@5*SLWW('53/<8HS8 +M\086""L"9QBJU#SK<79,14B:S!/$4ZB[*`\@K!.#BS^@6NO*S!M6]&O>W-'B +M9MK<P=WBP&[?HD4JJ_GO+9(A86[;0^='&%P9^0G2%;V=[;8.VV</')#4.N4A +MU'W+[;1H0R"=84/N"H%""&14?Y^]Z\**;J>]AN']=QZ6#AC<)#!+T"*5M,`? +M4Q^W`.TB(%24P,F'"T4!=4OM+KU]BX9@3J.!&/KP5J']:]U+KK!.I.DN3X2F +M&WSR;53XJ\89'?G_W!LXH`>B=<Q`8_"SWB:OR3ID5;?%(O*B"MJ[9I_X!I,@ +M:?M+:V;-KW,@7HTSE@RTRB8=57%3BS0;W3.&Z-#5G#'0L"Y+`Q.'$_;"F,]; +M,<:C#\H+I$1\[M^@<=H![/T52V)<SU]DD\*LS8^?5_BV"%7J;XH(;\)-T[9C +MQ(3AQD5R%4TA3ZWX(UZ5C03)2=8]XU+<'D)OH55VQ.9II??+,^A%T/(&&7CB +M'-EI>7Y'?P"?7>?W)4DM;'UEQ-`%+=?#R`7%VSD6YDF.,[K*X'MG%HGE(B:R +M%.S9]W=WE4C>/NBVKG0P;^4C)T]#A&DGOW*AZ9F1SNI[2)'O-,)V53A&X56# +MCH0Q\M*+CL91N:'M?Q>V/@E%=#+FL[QXQ;6)'C7QAOOQ^O')K^XG5*H1@C^. +MXA0RB<2Z1+R-YQ&U];]]JE&*,51D3()%9.YGW>B?6XUK8`/X6U5EY/E=(^8& +MNR42G7DB'[#1BT!T;2U$"AOIVH4-:\^7$_)F1OW:6SF*2PJX:H1K!=R5$$6C +M@5[?\.(LIG(]<MB6`36W#U3#740"7DBN"C\0#2]@QQOGY):"TKM"F;C<W@6` +M&%="WK;\'-FW'M`8)ZG.+&)HUN]$!?S-J3E7`[OJ9HABN(J5H9",!'V_H0IB +M#."M/97=8'EE4'LX>8FQ/XPU6>]L;K$7?$%0"Z'+=OMP*6,BKD*,(X[QZBM] +M:8#P[]/[<W1`VH3D]LF<ERANE5>0/:L0&XBAC;L<PXG,F(N#8,O!*L67C9#G +MBQ<5D.5C;O::R5@U\H!VK4`U;>\,!KIR2;=-,2[FL<NWC'SE8>71X#$V:H<= +MYP/E,W=XY,RO7"#_I^*-VWX3\V<O8T,<[>!A-R(M^GG"D6VHH0$\HRX5&M,+ +M].?`#M*J/W%7EA9WT#^$[DKF'RP*M3H:?_G3?[67/WQW=NBHA]/085!+`0(4 +M`!0``0!C`*>+#D5-F]+T`A4``)M_```(`"\```````$`(`````````!C;VYF +M:6<N:`H`(````````0`8``"9/"T/N,\!`*%E,R&>W`$`F3PM#[C/`0&9!P`! +M`$%%`UT`4$L!`A0`%``!`&,`^*XC1</GIX8_&P$`:SH6``@`+P```````0`@ +M````,Q4``$UA:V5F:6QE"@`@```````!`!@``%*JNNO'SP&PW60S(9[<`0!2 +MJKKKQ\\!`9D'``$`044#70!02P$"%``4``$`8P",L`Y%7COQLNDJ``"M<@`` +M!``O```````!`"````"C,`$`3D574PH`(````````0`8``"L]ITUN,\!P`1E +M,R&>W`$`K/:=-;C/`0&9!P`!`$%%`UT`4$L!`A0`%``!`&,`C+`.1;N038:K +M"@``HAH```8`+P```````0`@````N5L!`%)%041-10H`(````````0`8``"L +M]ITUN,\!\'EE,R&>W`$`K/:=-;C/`0&9!P`!`$%%`UT`4$L%!@`````$``0` +*C@$``)-F`0`````` +` +end diff --git a/libarchive/test/test_read_format_zip_winzip_aes_large.c b/libarchive/test/test_read_format_zip_winzip_aes_large.c index 4f52bb911147..e24b69a032ad 100644 --- a/libarchive/test/test_read_format_zip_winzip_aes_large.c +++ b/libarchive/test/test_read_format_zip_winzip_aes_large.c @@ -25,114 +25,37 @@ */ #include "test.h" -DEFINE_TEST(test_read_format_zip_winzip_aes256_large) +#define FILE_COUNT 4 + +static const char *FILE_NAMES[FILE_COUNT] = { "Makefile", "NEWS", "README", "config.h" }; +static const size_t FILE_SIZE[FILE_COUNT] = { 1456747, 29357, 6818, 32667 }; + +static void +test_file_with_bad_password(struct archive *a, int file_id, __LA_MODE_T file_permissions) { - const char *refname = "test_read_format_zip_winzip_aes256_large.zip"; struct archive_entry *ae; - struct archive *a; char buff[512]; - - /* Check if running system has cryptographic functionality. */ - assert((a = archive_write_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); - if (ARCHIVE_OK != archive_write_set_options(a, - "zip:encryption=aes256")) { - skipping("This system does not have cryptographic library"); - archive_write_free(a); - return; - } - archive_write_free(a); - - - extract_reference_file(refname); - - /* - * Extract a zip file without password. - */ - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_filename(a, refname, 10240)); - - assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, - archive_read_has_encrypted_entries(a)); - - /* Verify encrypted file "Makefile" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("Makefile", archive_entry_pathname(ae)); - assertEqualInt(1456747, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); - - /* Verify encrypted file "NEWS" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("NEWS", archive_entry_pathname(ae)); - assertEqualInt(29357, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); - - /* Verify encrypted file "README" */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("README", archive_entry_pathname(ae)); - assertEqualInt(6818, archive_entry_size(ae)); + assertEqualInt((AE_IFREG | file_permissions), archive_entry_mode(ae)); + assertEqualString(FILE_NAMES[file_id], archive_entry_pathname(ae)); + assertEqualInt(FILE_SIZE[file_id], archive_entry_size(ae)); assertEqualInt(1, archive_entry_is_data_encrypted(ae)); assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); +} - /* Verify encrypted file "config.h" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("config.h", archive_entry_pathname(ae)); - assertEqualInt(32667, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, buff, sizeof(buff))); - - assertEqualInt(4, archive_file_count(a)); - - /* End of archive. */ - assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - - /* Verify archive format. */ - assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); - assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); - - /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - - - /* - * Extract a zip file with password. - */ - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_add_passphrase(a, "password")); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_filename(a, refname, 10240)); - - assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, - archive_read_has_encrypted_entries(a)); +static void +test_file_with_good_password(struct archive *a, int file_id, __LA_MODE_T file_permissions) +{ + struct archive_entry *ae; + char buff[512]; - /* Verify encrypted file "Makefile" */ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("Makefile", archive_entry_pathname(ae)); - assertEqualInt(1456747, archive_entry_size(ae)); + assertEqualInt((AE_IFREG | file_permissions), archive_entry_mode(ae)); + assertEqualString(FILE_NAMES[file_id], archive_entry_pathname(ae)); + assertEqualInt(FILE_SIZE[file_id], archive_entry_size(ae)); assertEqualInt(1, archive_entry_is_data_encrypted(ae)); assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); @@ -140,67 +63,42 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large) assertEqualInt(512, archive_read_data(a, buff, sizeof(buff))); } else { assertEqualInt(ARCHIVE_FAILED, - archive_read_data(a, buff, sizeof(buff))); + archive_read_data(a, buff, sizeof(buff))); assertEqualString(archive_error_string(a), - "Unsupported ZIP compression method (8: deflation)"); + "Unsupported ZIP compression method (8: deflation)"); assert(archive_errno(a) != 0); } +} - /* Verify encrypted file "NEWS" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("NEWS", archive_entry_pathname(ae)); - assertEqualInt(29357, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - if (archive_zlib_version() != NULL) { - assertEqualInt(512, archive_read_data(a, buff, sizeof(buff))); - } else { - assertEqualInt(ARCHIVE_FAILED, - archive_read_data(a, buff, sizeof(buff))); - assertEqualString(archive_error_string(a), - "Unsupported ZIP compression method (8: deflation)"); - assert(archive_errno(a) != 0); - } +static void +test_archive(const char *refname, const char *password, int good_password, const int file_order[FILE_COUNT], __LA_MODE_T file_permissions) +{ + struct archive *a; + struct archive_entry *ae; - /* Verify encrypted file "README" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("README", archive_entry_pathname(ae)); - assertEqualInt(6818, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - if (archive_zlib_version() != NULL) { - assertEqualInt(512, archive_read_data(a, buff, sizeof(buff))); - } else { - assertEqualInt(ARCHIVE_FAILED, - archive_read_data(a, buff, sizeof(buff))); - assertEqualString(archive_error_string(a), - "Unsupported ZIP compression method (8: deflation)"); - assert(archive_errno(a) != 0); + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + if (password != NULL) { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_add_passphrase(a, password)); } + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); - /* Verify encrypted file "config.h" */ - assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); - assertEqualInt((AE_IFREG | 0644), archive_entry_mode(ae)); - assertEqualString("config.h", archive_entry_pathname(ae)); - assertEqualInt(32667, archive_entry_size(ae)); - assertEqualInt(1, archive_entry_is_data_encrypted(ae)); - assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); - assertEqualIntA(a, 1, archive_read_has_encrypted_entries(a)); - if (archive_zlib_version() != NULL) { - assertEqualInt(512, archive_read_data(a, buff, sizeof(buff))); - } else { - assertEqualInt(ARCHIVE_FAILED, - archive_read_data(a, buff, sizeof(buff))); - assertEqualString(archive_error_string(a), - "Unsupported ZIP compression method (8: deflation)"); - assert(archive_errno(a) != 0); + assertEqualIntA(a, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW, + archive_read_has_encrypted_entries(a)); + + /* Verify encrypted files */ + for(int i = 0; i < FILE_COUNT; ++i) { + if (good_password) { + test_file_with_good_password(a, file_order[i], file_permissions); + } else { + test_file_with_bad_password(a, file_order[i], file_permissions); + } } - - assertEqualInt(4, archive_file_count(a)); + + assertEqualInt(FILE_COUNT, archive_file_count(a)); /* End of archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); @@ -210,7 +108,85 @@ DEFINE_TEST(test_read_format_zip_winzip_aes256_large) assertEqualIntA(a, ARCHIVE_FORMAT_ZIP, archive_format(a)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } +static void +test_winzip_aes_large_with_file_order(const char *refname, const char *compression_name, __LA_MODE_T file_permissions, const int file_order[FILE_COUNT]) +{ + struct archive *a; + + /* Check if running system has cryptographic functionality. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + if (ARCHIVE_OK != archive_write_set_options(a, + "zip:encryption=aes256")) { + skipping("This system does not have cryptographic library"); + archive_write_free(a); + return; + } + + /* Check if running system supports compression format used */ + if (compression_name && ARCHIVE_OK != archive_write_set_options(a, compression_name)) { + skipping("%s is not supported on this platform", compression_name); + archive_write_free(a); + return; + } + + archive_write_free(a); + + extract_reference_file(refname); + + /* Extract a zip file without password. */ + test_archive(refname, NULL, 0, file_order, file_permissions); + + /* Extract a zip file with bad password. */ + test_archive(refname, "not_the_password", 0, file_order, file_permissions); + + /* Extract a zip file with good password. */ + test_archive(refname, "password", 1, file_order, file_permissions); +} + +static void +test_winzip_aes_large(const char *refname, const char *compression_name) +{ + int file_order[FILE_COUNT] = { 0, 1, 2, 3 }; + test_winzip_aes_large_with_file_order(refname, compression_name, ((__LA_MODE_T)0644), file_order); +} + + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large) +{ + // Deflate is always supported, no need to test for it + test_winzip_aes_large("test_read_format_zip_winzip_aes256_large.zip", NULL); +} + + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large_bzip2) +{ + test_winzip_aes_large("test_read_format_zip_winzip_aes256_large_bzip2.zip", "zip:compression=bzip2"); +} + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large_lzma) +{ + test_winzip_aes_large("test_read_format_zip_winzip_aes256_large_lzma.zip", "zip:compression=lzma"); +} + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large_ppmd) +{ + test_winzip_aes_large("test_read_format_zip_winzip_aes256_large_ppmd.zip", NULL); +} + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large_xz) +{ + test_winzip_aes_large("test_read_format_zip_winzip_aes256_large_xz.zip", "zip:compression=xz"); +} + +DEFINE_TEST(test_read_format_zip_winzip_aes256_large_zstd) +{ + int file_order[FILE_COUNT] = { 3, 0, 1, 2 }; + test_winzip_aes_large_with_file_order("test_read_format_zip_winzip_aes256_large_zstd.zip", + "zip:compression=zstd", ((__LA_MODE_T)0664), file_order); +} diff --git a/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c b/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c index e9549fef8e7d..8bb9fb834bcb 100644 --- a/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c +++ b/libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.c @@ -53,6 +53,6 @@ DEFINE_TEST(test_read_format_zip_with_invalid_traditional_eocd) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(p); } diff --git a/libarchive/test/test_read_format_zip_zip64.c b/libarchive/test/test_read_format_zip_zip64.c index 51968b71addb..6c94c1e8200b 100644 --- a/libarchive/test/test_read_format_zip_zip64.c +++ b/libarchive/test/test_read_format_zip_zip64.c @@ -47,7 +47,7 @@ verify_file0_seek(struct archive *a) #endif assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } static void @@ -76,7 +76,7 @@ verify_file0_stream(struct archive *a, int size_known) #endif assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } DEFINE_TEST(test_read_format_zip_zip64a) diff --git a/libarchive/test/test_read_format_zip_zipx_encrypted.c b/libarchive/test/test_read_format_zip_zipx_encrypted.c new file mode 100644 index 000000000000..e27848ce4bc1 --- /dev/null +++ b/libarchive/test/test_read_format_zip_zipx_encrypted.c @@ -0,0 +1,182 @@ +/*- + * Copyright (c) 2026 GeorgH93 + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" + +static const char *password = "test_password_zipx"; + +/* 512 bytes of test data — large enough to exercise decompression. */ +static const char file_data[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz\n" + "The quick brown fox jumps over the lazy dog. Pack my box with five\n" + "dozen liquor jugs. How vexingly quick daft zebras jump! Bright\n" + "vixens jump; dozy fowl quack. Jackdaws love my big sphinx of\n" + "quartz. The five boxing wizards jump quickly. Amazingly few\n" + "discotheques provide jukeboxes. Crazy Frederick bought many very\n" + "exquisite opal jewels. We promptly judged antique ivory buckles\n" + "for the next prize. Sixty zippers were quickly picked from the bag.\n"; + +static void +validate_entry_read(struct archive *a, const char* msg) +{ + struct archive_entry *ae; + size_t total_read; + ssize_t r; + char readbuf[1024]; + + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("encrypted_file.txt", archive_entry_pathname(ae)); + assertEqualInt((int)(sizeof(file_data) - 1), + archive_entry_size(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + + total_read = 0; + for (;;) { + r = archive_read_data(a, readbuf, sizeof(readbuf)); + if (r <= 0) { + if (r < 0) { + failure(msg, (int) r, archive_error_string(a)); + assertEqualInt(r > 0, 1); + } + break; + } + assertEqualMem(readbuf, file_data + total_read, (size_t)r); + total_read += (size_t)r; + } + assertEqualInt((int)total_read, (int)(sizeof(file_data) - 1)); +} + +static void +test_encrypted_zipx(const char *compression_name) +{ + struct archive *a; + struct archive_entry *ae; + size_t used; + size_t buffsize = 1000000; + char *buff; + char readbuf[1024]; + + buff = malloc(buffsize); + assert(buff != NULL); + + /* ---- Write encrypted zipx archive ---- */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + + if (ARCHIVE_OK != archive_write_set_options(a, + "zip:encryption=aes256")) { + skipping("This system does not have cryptographic library"); + archive_write_free(a); + free(buff); + return; + } + + if (ARCHIVE_OK != archive_write_set_options(a, compression_name)) { + skipping("%s is not supported on this platform", compression_name); + archive_write_free(a); + free(buff); + return; + } + + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_passphrase(a, password)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "zip:experimental")); + assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_mtime(ae, 1, 0); + archive_entry_copy_pathname(ae, "encrypted_file.txt"); + archive_entry_set_mode(ae, AE_IFREG | 0644); + archive_entry_set_size(ae, sizeof(file_data) - 1); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + assertEqualInt(sizeof(file_data) - 1, archive_write_data(a, file_data, sizeof(file_data) - 1)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* ---- Read back without password — should fail ---- */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString("encrypted_file.txt", archive_entry_pathname(ae)); + assertEqualInt(1, archive_entry_is_data_encrypted(ae)); + assertEqualInt(0, archive_entry_is_metadata_encrypted(ae)); + assertEqualInt(ARCHIVE_FAILED, archive_read_data(a, readbuf, sizeof(readbuf))); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* ---- Read back with correct password ---- */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_add_passphrase(a, password)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + validate_entry_read(a, "archive_read_data returned %d: %s"); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + /* ---- Seeking reader with correct password ---- */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_add_passphrase(a, password)); + assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, buff, used, 7)); + + validate_entry_read(a, "seek: archive_read_data returned %d: %s"); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} + +DEFINE_TEST(test_read_format_zip_deflate_encrypted) +{ + test_encrypted_zipx("zip:compression=deflate"); +} + +DEFINE_TEST(test_read_format_zip_zipx_bzip2_encrypted) +{ + test_encrypted_zipx("zip:compression=bzip2"); +} + +DEFINE_TEST(test_read_format_zip_zipx_lzma_encrypted) +{ + test_encrypted_zipx("zip:compression=lzma"); +} + +DEFINE_TEST(test_read_format_zip_zipx_xz_encrypted) +{ + test_encrypted_zipx("zip:compression=xz"); +} + +DEFINE_TEST(test_read_format_zip_zipx_zstd_encrypted) +{ + test_encrypted_zipx("zip:compression=zstd"); +} diff --git a/libarchive/test/test_read_format_zip_zipx_lzma_oom.c b/libarchive/test/test_read_format_zip_zipx_lzma_oom.c new file mode 100644 index 000000000000..9867fd2abc90 --- /dev/null +++ b/libarchive/test/test_read_format_zip_zipx_lzma_oom.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * A ZIPX entry whose LZMA properties encode a 0xFFFFFFFF-byte dictionary + * previously caused libarchive to attempt a ~4 GiB allocation because + * lzma_alone_decoder() was called with an unlimited memory limit. + * The fix passes a 64 MiB limit; the decoder must then return + * LZMA_MEMLIMIT_ERROR, which libarchive must report as ENOMEM. + */ +DEFINE_TEST(test_read_format_zip_zipx_lzma_oom) +{ + const char *refname = "test_read_format_zip_zipx_lzma_oom.zipx"; + struct archive *a; + struct archive_entry *ae; + char buf[64]; + + extract_reference_file(refname); + + assert((a = archive_read_new()) != NULL); + if (ARCHIVE_OK != archive_read_support_filter_lzma(a)) { + skipping("lzma reading not fully supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_filename(a, refname, 10240)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + + /* + * Data extraction must fail gracefully with ENOMEM rather than + * attempting a multi-gigabyte allocation. + */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_read_data(a, buf, sizeof(buf))); + assertEqualInt(ENOMEM, archive_errno(a)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_read_format_zip_zipx_lzma_oom.zipx.uu b/libarchive/test/test_read_format_zip_zipx_lzma_oom.zipx.uu new file mode 100644 index 000000000000..8de72af03008 --- /dev/null +++ b/libarchive/test/test_read_format_zip_zipx_lzma_oom.zipx.uu @@ -0,0 +1,4 @@ +begin 644 test_read_format_zip_zipx_lzma_oom.zipx +G4$L#!!0````.````````````"0``````````````"10%`%W_____ +` +end diff --git a/libarchive/test/test_read_pax_empty_val_no_nl.c b/libarchive/test/test_read_pax_empty_val_no_nl.c index f985488754fd..a271e9ee5e63 100644 --- a/libarchive/test/test_read_pax_empty_val_no_nl.c +++ b/libarchive/test/test_read_pax_empty_val_no_nl.c @@ -60,6 +60,6 @@ DEFINE_TEST(test_read_pax_empty_val_no_nl) assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_pax_xattr_rht_security_selinux.c b/libarchive/test/test_read_pax_xattr_rht_security_selinux.c index 609e8d03bf7b..7f526ebfd4de 100644 --- a/libarchive/test/test_read_pax_xattr_rht_security_selinux.c +++ b/libarchive/test/test_read_pax_xattr_rht_security_selinux.c @@ -57,6 +57,6 @@ DEFINE_TEST(test_read_pax_xattr_rht_security_selinux) assertEqualInt((int)xsize, strlen(string)); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_pax_xattr_schily.c b/libarchive/test/test_read_pax_xattr_schily.c index 6b7dc471f043..7dfc9e7bb5a9 100644 --- a/libarchive/test/test_read_pax_xattr_schily.c +++ b/libarchive/test/test_read_pax_xattr_schily.c @@ -65,6 +65,6 @@ DEFINE_TEST(test_read_pax_xattr_schily) assertEqualMem(xval, array, 12); /* Close the archive. */ - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_read_set_format.c b/libarchive/test/test_read_set_format.c index 2ea39045201f..0b656b1682f5 100644 --- a/libarchive/test/test_read_set_format.c +++ b/libarchive/test/test_read_set_format.c @@ -148,7 +148,7 @@ DEFINE_TEST(test_read_append_filter) assertEqualInt(1, archive_file_count(a)); assertEqualInt(archive_filter_code(a, 0), ARCHIVE_COMPRESSION_GZIP); assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK,archive_read_free(a)); } @@ -211,6 +211,174 @@ DEFINE_TEST(test_read_append_grzip_filter) archive_read_free(a); } +DEFINE_TEST(test_read_append_compress_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_COMPRESS); + assertEqualIntA(a, ARCHIVE_OK, r); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + +DEFINE_TEST(test_read_append_bzip2_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_BZIP2); + if (r != ARCHIVE_OK && archive_bzlib_version() == NULL && !canBzip2()) { + skipping("bzip2 tests require bzlib or working bzip2 command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canBzip2()) + assertEqualString(archive_error_string(a), "Using external bzip2 program"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_lrzip_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_LRZIP); + if (r != ARCHIVE_OK && !canLrzip()) { + skipping("lrzip tests require working lrzip command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canLrzip()) + assertEqualString(archive_error_string(a), "Using external lrzip program for lrzip decompression"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_lz4_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_LZ4); + if (r != ARCHIVE_OK && archive_liblz4_version() == NULL && !canLz4()) { + skipping("lz4 tests require liblz4 or working lz4 command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canLz4()) + assertEqualString(archive_error_string(a), "Using external lz4 program"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_lzip_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_LZIP); + if (r != ARCHIVE_OK && archive_liblzma_version() == NULL && !canLzip()) { + skipping("lzip tests require liblzma or working lzip command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canLzip()) + assertEqualString(archive_error_string(a), "Using external lzip program for lzip decompression"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_lzma_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_LZMA); + if (r != ARCHIVE_OK && archive_liblzma_version() == NULL && !canLzma()) { + skipping("lzma tests require liblzma or working lzma command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canLzma()) + assertEqualString(archive_error_string(a), "Using external lzma program for lzma decompression"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_zstd_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_ZSTD); + if (r != ARCHIVE_OK && archive_libzstd_version() == NULL && !canZstd()) { + skipping("zstd tests require libzstd or working zstd command"); + archive_read_free(a); + return; + } + if (r == ARCHIVE_WARN && canZstd()) + assertEqualString(archive_error_string(a), "Using external zstd program for zstd decompression"); + else + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_rpm_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_RPM); + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_uu_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_UU); + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + +DEFINE_TEST(test_read_append_none_filter) +{ + struct archive *a; + int r; + + assert((a = archive_read_new()) != NULL); + assertA(0 == archive_read_set_format(a, ARCHIVE_FORMAT_TAR)); + r = archive_read_append_filter(a, ARCHIVE_FILTER_NONE); + assertEqualIntA(a, ARCHIVE_OK, r); + archive_read_free(a); +} + DEFINE_TEST(test_read_append_filter_program) { struct archive_entry *ae; diff --git a/libarchive/test/test_sparse_basic.c b/libarchive/test/test_sparse_basic.c index 93710cb64033..d4405ddae48e 100644 --- a/libarchive/test/test_sparse_basic.c +++ b/libarchive/test/test_sparse_basic.c @@ -695,3 +695,29 @@ DEFINE_TEST(test_fully_sparse_files) assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(cwd); } + +DEFINE_TEST(test_sparse_iterator) +{ + struct archive_entry *entry; + int64_t offset, length; + int count; + + entry = archive_entry_new(); + archive_entry_set_pathname(entry, "testfile"); + archive_entry_set_mode(entry, 0100644); + archive_entry_set_size(entry, 1024); + + /* Add one sparse block covering the entire file */ + archive_entry_sparse_add_entry(entry, 0, 1024); + + /* Should remove the only block covering the entire file */ + archive_entry_sparse_reset(entry); + + count = 0; + while (archive_entry_sparse_next(entry, &offset, &length) == ARCHIVE_OK) + count++; + assertEqualInt(0, count); + assertEqualInt(0, archive_entry_sparse_count(entry)); + + archive_entry_free(entry); +} diff --git a/libarchive/test/test_write_disk_appledouble.c b/libarchive/test/test_write_disk_appledouble.c index 8de6c8b50413..f4e4bb8af96d 100644 --- a/libarchive/test/test_write_disk_appledouble.c +++ b/libarchive/test/test_write_disk_appledouble.c @@ -151,7 +151,7 @@ DEFINE_TEST(test_write_disk_appledouble) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file3. */ assertEqualInt(0, stat("file3", &st)); @@ -210,7 +210,7 @@ DEFINE_TEST(test_write_disk_appledouble) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file3. */ assertEqualInt(0, stat("file3", &st)); @@ -296,7 +296,7 @@ DEFINE_TEST(test_write_disk_appledouble_zip) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test test_file */ assertEqualInt(0, stat("apple_double_dir/test_file", &st)); diff --git a/libarchive/test/test_write_disk_hfs_compression.c b/libarchive/test/test_write_disk_hfs_compression.c index 026e41533628..1df38ad83fa4 100644 --- a/libarchive/test/test_write_disk_hfs_compression.c +++ b/libarchive/test/test_write_disk_hfs_compression.c @@ -146,7 +146,7 @@ DEFINE_TEST(test_write_disk_hfs_compression) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file1. */ assertEqualInt(0, stat("file1", &st)); @@ -229,7 +229,7 @@ DEFINE_TEST(test_write_disk_hfs_compression) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file1. */ assertEqualInt(0, stat("file1", &st)); diff --git a/libarchive/test/test_write_disk_mac_metadata.c b/libarchive/test/test_write_disk_mac_metadata.c index f9cfd9b3fd7c..8d5a31d0fdde 100644 --- a/libarchive/test/test_write_disk_mac_metadata.c +++ b/libarchive/test/test_write_disk_mac_metadata.c @@ -144,7 +144,7 @@ DEFINE_TEST(test_write_disk_mac_metadata) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file3. */ assertEqualInt(0, stat("file3", &st)); @@ -195,7 +195,7 @@ DEFINE_TEST(test_write_disk_mac_metadata) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file3. */ assertEqualInt(0, stat("file3", &st)); diff --git a/libarchive/test/test_write_disk_no_hfs_compression.c b/libarchive/test/test_write_disk_no_hfs_compression.c index 58ad187574c1..2ddcf742b33d 100644 --- a/libarchive/test/test_write_disk_no_hfs_compression.c +++ b/libarchive/test/test_write_disk_no_hfs_compression.c @@ -120,7 +120,7 @@ DEFINE_TEST(test_write_disk_no_hfs_compression) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file1. */ assertEqualInt(0, stat("file1", &st)); @@ -190,7 +190,7 @@ DEFINE_TEST(test_write_disk_no_hfs_compression) assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); - assertEqualIntA(ad, ARCHIVE_OK, archive_write_free(ad)); + assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); /* Test file1. */ assertEqualInt(0, stat("file1", &st)); diff --git a/libarchive/test/test_write_disk_secure745.c b/libarchive/test/test_write_disk_secure745.c index 7b908ccc8905..570a8356a9f2 100644 --- a/libarchive/test/test_write_disk_secure745.c +++ b/libarchive/test/test_write_disk_secure745.c @@ -72,7 +72,7 @@ DEFINE_TEST(test_write_disk_secure745) /* Permission of target dir should not have changed. */ assertFileMode("../target", 0700); - assert(0 == archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); archive_write_free(a); #endif } diff --git a/libarchive/test/test_write_disk_secure_noabsolutepaths.c b/libarchive/test/test_write_disk_secure_noabsolutepaths.c index b66b6bea4423..235686894765 100644 --- a/libarchive/test/test_write_disk_secure_noabsolutepaths.c +++ b/libarchive/test/test_write_disk_secure_noabsolutepaths.c @@ -85,4 +85,5 @@ DEFINE_TEST(test_write_disk_secure_noabsolutepaths) assertEqualInt(ARCHIVE_OK, archive_write_free(ad)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(temp_absolute_file_name); } diff --git a/libarchive/test/test_write_filter_b64encode.c b/libarchive/test/test_write_filter_b64encode.c index d7c4763b1cdc..d8abed976de4 100644 --- a/libarchive/test/test_write_filter_b64encode.c +++ b/libarchive/test/test_write_filter_b64encode.c @@ -147,13 +147,13 @@ DEFINE_TEST(test_write_filter_b64encode) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -161,7 +161,7 @@ DEFINE_TEST(test_write_filter_b64encode) assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_b64encode(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/libarchive/test/test_write_filter_bzip2.c b/libarchive/test/test_write_filter_bzip2.c index d7ed95e2c7ff..1fc19c19d454 100644 --- a/libarchive/test/test_write_filter_bzip2.c +++ b/libarchive/test/test_write_filter_bzip2.c @@ -241,7 +241,7 @@ DEFINE_TEST(test_write_filter_bzip2) else assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_bzip2(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -252,7 +252,7 @@ DEFINE_TEST(test_write_filter_bzip2) else assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_bzip2(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -265,7 +265,7 @@ DEFINE_TEST(test_write_filter_bzip2) archive_write_add_filter_bzip2(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/libarchive/test/test_write_filter_gzip.c b/libarchive/test/test_write_filter_gzip.c index a6681d7618b1..31cd486dc1cf 100644 --- a/libarchive/test/test_write_filter_gzip.c +++ b/libarchive/test/test_write_filter_gzip.c @@ -40,7 +40,7 @@ DEFINE_TEST(test_write_filter_gzip) size_t buffsize, datasize; unsigned char *rbuff; char path[16]; - size_t used1, used2; + size_t used1, used2, used3; int i, r, use_prog = 0; buffsize = 2000000; @@ -218,7 +218,7 @@ DEFINE_TEST(test_write_filter_gzip) assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a, NULL, "compression-level", "1")); assertEqualIntA(a, ARCHIVE_OK, - archive_write_open_memory(a, buff, buffsize, &used2)); + archive_write_open_memory(a, buff, buffsize, &used3)); for (i = 0; i < 100; i++) { snprintf(path, sizeof(path), "file%03d", i); assert((ae = archive_entry_new()) != NULL); @@ -234,10 +234,13 @@ DEFINE_TEST(test_write_filter_gzip) assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); - /* Level 1 really does result in larger data. */ - failure("Compression-level=1 wrote %d bytes; default wrote %d bytes", - (int)used2, (int)used1); - assert(used2 > used1); + /* Level 1 really does result in larger data than level 9. + * We can't compare levels 1 and 6 because those produce identical + * results on Ubuntu s390x, since Ubuntu configures both levels to + * use DFLTCC hardware compression. */ + failure("Compression-level=1 wrote %d bytes; compression-level=9 wrote %d bytes", + (int)used3, (int)used2); + assert(used3 > used2); /* Basic gzip header tests */ rbuff = (unsigned char *)buff; @@ -255,7 +258,7 @@ DEFINE_TEST(test_write_filter_gzip) skipping("gzip reading not fully supported on this platform"); } else { assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_memory(a, buff, used2)); + archive_read_open_memory(a, buff, used3)); for (i = 0; i < 100; i++) { snprintf(path, sizeof(path), "file%03d", i); if (!assertEqualInt(ARCHIVE_OK, @@ -280,14 +283,14 @@ DEFINE_TEST(test_write_filter_gzip) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_gzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_gzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -295,7 +298,7 @@ DEFINE_TEST(test_write_filter_gzip) assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_gzip(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/libarchive/test/test_write_filter_lrzip.c b/libarchive/test/test_write_filter_lrzip.c index 8da7ae39af5d..187b2c07baa1 100644 --- a/libarchive/test/test_write_filter_lrzip.c +++ b/libarchive/test/test_write_filter_lrzip.c @@ -106,13 +106,13 @@ DEFINE_TEST(test_write_filter_lrzip) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lrzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lrzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -120,7 +120,7 @@ DEFINE_TEST(test_write_filter_lrzip) assertEqualIntA(a, ARCHIVE_WARN, archive_write_add_filter_lrzip(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/libarchive/test/test_write_filter_lz4.c b/libarchive/test/test_write_filter_lz4.c index 74a910b53530..12417b6034a3 100644 --- a/libarchive/test/test_write_filter_lz4.c +++ b/libarchive/test/test_write_filter_lz4.c @@ -100,6 +100,8 @@ DEFINE_TEST(test_write_filter_lz4) skipping("Can't verify lz4 writing by reading back;" " lz4 reading not fully supported on this platform"); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + free(data); + free(buff); return; } @@ -247,14 +249,14 @@ DEFINE_TEST(test_write_filter_lz4) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_lz4(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_lz4(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -263,7 +265,7 @@ DEFINE_TEST(test_write_filter_lz4) archive_write_add_filter_lz4(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/libarchive/test/test_write_filter_lzip.c b/libarchive/test/test_write_filter_lzip.c index 631fd96bd5ce..199775a2bd5e 100644 --- a/libarchive/test/test_write_filter_lzip.c +++ b/libarchive/test/test_write_filter_lzip.c @@ -230,20 +230,20 @@ DEFINE_TEST(test_write_filter_lzip) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzip(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/libarchive/test/test_write_filter_lzma.c b/libarchive/test/test_write_filter_lzma.c index 9bb2d8eb7943..9e32735ec071 100644 --- a/libarchive/test/test_write_filter_lzma.c +++ b/libarchive/test/test_write_filter_lzma.c @@ -55,7 +55,7 @@ DEFINE_TEST(test_write_filter_lzma) memset(data, 0, datasize); /* - * Write a 100 files and read them all back. + * Write 100 files and read them all back. */ assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); @@ -129,43 +129,53 @@ DEFINE_TEST(test_write_filter_lzma) archive_write_set_filter_option(a, NULL, "compression-level", "99")); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a, NULL, "compression-level", "9")); - assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - for (i = 0; i < 100; i++) { - snprintf(path, sizeof(path), "file%03d", i); - assert((ae = archive_entry_new()) != NULL); - archive_entry_copy_pathname(ae, path); - archive_entry_set_size(ae, datasize); - archive_entry_set_filetype(ae, AE_IFREG); - assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); - assertA(datasize == (size_t)archive_write_data(a, data, datasize)); - archive_entry_free(ae); - } - assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualInt(ARCHIVE_OK, archive_write_free(a)); - - - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - r = archive_read_support_filter_lzma(a); - if (r == ARCHIVE_WARN) { - skipping("lzma reading not fully supported on this platform"); + r = archive_write_open_memory(a, buff, buffsize, &used2); + if (r == ARCHIVE_FATAL && archive_errno(a) == ENOMEM) { + skipping("Not enough memory available"); + archive_write_free(a); } else { - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_all(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_memory(a, buff, used2)); + assertEqualIntA(a, ARCHIVE_OK, r); for (i = 0; i < 100; i++) { snprintf(path, sizeof(path), "file%03d", i); - failure("Trying to read %s", path); - if (!assertEqualIntA(a, ARCHIVE_OK, - archive_read_next_header(a, &ae))) - break; - assertEqualString(path, archive_entry_pathname(ae)); - assertEqualInt((int)datasize, archive_entry_size(ae)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, ae)); + assertA(datasize == + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); } - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + r = archive_read_support_filter_lzma(a); + if (r == ARCHIVE_WARN) { + skipping("lzma reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + snprintf(path, sizeof(path), "file%03d", i); + failure("Trying to read %s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, + archive_entry_pathname(ae)); + assertEqualInt((int)datasize, + archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* * Repeat again, with much lower compression. @@ -234,20 +244,20 @@ DEFINE_TEST(test_write_filter_lzma) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_lzma(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/libarchive/test/test_write_filter_lzop.c b/libarchive/test/test_write_filter_lzop.c index 8b74d224dced..f825a126b659 100644 --- a/libarchive/test/test_write_filter_lzop.c +++ b/libarchive/test/test_write_filter_lzop.c @@ -239,14 +239,14 @@ DEFINE_TEST(test_write_filter_lzop) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_lzop(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, (use_prog)?ARCHIVE_WARN:ARCHIVE_OK, archive_write_add_filter_lzop(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -255,7 +255,7 @@ DEFINE_TEST(test_write_filter_lzop) archive_write_add_filter_lzop(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/libarchive/test/test_write_filter_uuencode.c b/libarchive/test/test_write_filter_uuencode.c index fbd0520880fe..3ab0ffa573a1 100644 --- a/libarchive/test/test_write_filter_uuencode.c +++ b/libarchive/test/test_write_filter_uuencode.c @@ -147,13 +147,13 @@ DEFINE_TEST(test_write_filter_uuencode) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); @@ -161,7 +161,7 @@ DEFINE_TEST(test_write_filter_uuencode) assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_uuencode(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/libarchive/test/test_write_filter_xz.c b/libarchive/test/test_write_filter_xz.c index 6baa0473b8e2..6ccfe4e81fb8 100644 --- a/libarchive/test/test_write_filter_xz.c +++ b/libarchive/test/test_write_filter_xz.c @@ -129,50 +129,61 @@ DEFINE_TEST(test_write_filter_xz) archive_write_set_filter_option(a, NULL, "compression-level", "99")); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_filter_option(a, NULL, "compression-level", "9")); - assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - for (i = 0; i < 100; i++) { - snprintf(path, sizeof(path), "file%03d", i); - assert((ae = archive_entry_new()) != NULL); - archive_entry_copy_pathname(ae, path); - archive_entry_set_size(ae, datasize); - archive_entry_set_filetype(ae, AE_IFREG); - assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); - assertA(datasize == (size_t)archive_write_data(a, data, datasize)); - archive_entry_free(ae); - } - assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualInt(ARCHIVE_OK, archive_write_free(a)); - - /* Curiously, this test fails; the test data above compresses - * better at default compression than at level 9. */ - /* - failure("compression-level=9 wrote %d bytes, default wrote %d bytes", - (int)used2, (int)used1); - assert(used2 < used1); - */ - - assert((a = archive_read_new()) != NULL); - assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); - r = archive_read_support_filter_xz(a); - if (r == ARCHIVE_WARN) { - skipping("xz reading not fully supported on this platform"); + r = archive_write_open_memory(a, buff, buffsize, &used2); + if (r == ARCHIVE_FATAL && archive_errno(a) == ENOMEM) { + skipping("Not enough memory available"); + archive_write_free(a); } else { - assertEqualIntA(a, ARCHIVE_OK, - archive_read_support_filter_all(a)); - assertEqualIntA(a, ARCHIVE_OK, - archive_read_open_memory(a, buff, used2)); + assertEqualIntA(a, ARCHIVE_OK, r); for (i = 0; i < 100; i++) { snprintf(path, sizeof(path), "file%03d", i); - failure("Trying to read %s", path); - if (!assertEqualIntA(a, ARCHIVE_OK, - archive_read_next_header(a, &ae))) - break; - assertEqualString(path, archive_entry_pathname(ae)); - assertEqualInt((int)datasize, archive_entry_size(ae)); + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, path); + archive_entry_set_size(ae, datasize); + archive_entry_set_filetype(ae, AE_IFREG); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, ae)); + assertA(datasize == + (size_t)archive_write_data(a, data, datasize)); + archive_entry_free(ae); } - assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Curiously, this test fails; the test data above compresses + * better at default compression than at level 9. */ + /* + failure("compression-level=9 wrote %d bytes, default wrote %d bytes", + (int)used2, (int)used1); + assert(used2 < used1); + */ + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_format_all(a)); + r = archive_read_support_filter_xz(a); + if (r == ARCHIVE_WARN) { + skipping("xz reading not fully supported on this platform"); + } else { + assertEqualIntA(a, ARCHIVE_OK, + archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used2)); + for (i = 0; i < 100; i++) { + snprintf(path, sizeof(path), "file%03d", i); + failure("Trying to read %s", path); + if (!assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &ae))) + break; + assertEqualString(path, + archive_entry_pathname(ae)); + assertEqualInt((int)datasize, + archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + } + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } - assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* * Repeat again, with much lower compression. @@ -240,20 +251,20 @@ DEFINE_TEST(test_write_filter_xz) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_xz(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/libarchive/test/test_write_filter_zstd.c b/libarchive/test/test_write_filter_zstd.c index 41451ca86251..360d89d02b30 100644 --- a/libarchive/test/test_write_filter_zstd.c +++ b/libarchive/test/test_write_filter_zstd.c @@ -340,20 +340,20 @@ DEFINE_TEST(test_write_filter_zstd) assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_write_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2)); - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* diff --git a/libarchive/test/test_write_format_7zip.c b/libarchive/test/test_write_format_7zip.c index 4b69cff40474..ef5b40906d16 100644 --- a/libarchive/test/test_write_format_7zip.c +++ b/libarchive/test/test_write_format_7zip.c @@ -181,7 +181,7 @@ test_basic(const char *compression_type) assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Verify the initial header. */ @@ -310,7 +310,7 @@ test_basic(const char *compression_type) assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); @@ -425,7 +425,7 @@ test_basic2(const char *compression_type) assertEqualIntA(a, 0, archive_write_data(a, "12345678", 9)); /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Verify the initial header. */ @@ -517,7 +517,7 @@ test_basic2(const char *compression_type) assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); diff --git a/libarchive/test/test_write_format_7zip_empty.c b/libarchive/test/test_write_format_7zip_empty.c index 817009f4355b..13fa9857fa2b 100644 --- a/libarchive/test/test_write_format_7zip_empty.c +++ b/libarchive/test/test_write_format_7zip_empty.c @@ -46,7 +46,7 @@ DEFINE_TEST(test_write_format_7zip_empty_archive) archive_write_open_memory(a, buff, buffsize, &used)); /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Verify the archive file size. */ @@ -105,7 +105,7 @@ test_only_empty_file(void) archive_entry_free(ae); /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Verify the archive file size. */ @@ -148,7 +148,7 @@ test_only_empty_file(void) assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); @@ -224,7 +224,7 @@ test_only_empty_files(void) archive_entry_free(ae); /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Verify the initial header. */ @@ -284,7 +284,7 @@ test_only_empty_files(void) assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); diff --git a/libarchive/test/test_write_format_7zip_large.c b/libarchive/test/test_write_format_7zip_large.c index 307b1f13cdd0..9bd92f30d8c1 100644 --- a/libarchive/test/test_write_format_7zip_large.c +++ b/libarchive/test/test_write_format_7zip_large.c @@ -126,7 +126,7 @@ test_large(const char *compression_type) assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0)); assertEqualIntA(a, ARCHIVE_FORMAT_7ZIP, archive_format(a)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); diff --git a/libarchive/test/test_write_format_gnutar.c b/libarchive/test/test_write_format_gnutar.c index ce963f43b66d..213efe3a6086 100644 --- a/libarchive/test/test_write_format_gnutar.c +++ b/libarchive/test/test_write_format_gnutar.c @@ -199,7 +199,7 @@ DEFINE_TEST(test_write_format_gnutar) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* * Some basic verification of the low-level format. @@ -274,7 +274,7 @@ DEFINE_TEST(test_write_format_gnutar) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/libarchive/test/test_write_format_gnutar_filenames.c b/libarchive/test/test_write_format_gnutar_filenames.c index aae5a2a6f787..b220bad535dd 100644 --- a/libarchive/test/test_write_format_gnutar_filenames.c +++ b/libarchive/test/test_write_format_gnutar_filenames.c @@ -68,7 +68,7 @@ DEFINE_TEST(test_write_format_gnutar_filenames) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, template)); assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Read back and verify the filename. */ @@ -81,7 +81,7 @@ DEFINE_TEST(test_write_format_gnutar_filenames) assertEqualString(filename, archive_entry_pathname(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } archive_entry_free(template); @@ -127,7 +127,7 @@ DEFINE_TEST(test_write_format_gnutar_linknames) assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, template)); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* Read back and verify the filename. */ @@ -141,7 +141,7 @@ DEFINE_TEST(test_write_format_gnutar_linknames) assertEqualString(filename, archive_entry_symlink(ae)); assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } archive_entry_free(template); diff --git a/libarchive/test/test_write_format_iso9660.c b/libarchive/test/test_write_format_iso9660.c index 7b455794c5de..288cc03fcf33 100644 --- a/libarchive/test/test_write_format_iso9660.c +++ b/libarchive/test/test_write_format_iso9660.c @@ -154,7 +154,7 @@ DEFINE_TEST(test_write_format_iso9660) archive_entry_set_birthtime(ae, 3, 30); archive_entry_set_ctime(ae, 4, 40); archive_entry_set_mtime(ae, 5, 50); - archive_entry_copy_pathname(ae, "dir0/dir1/file1"); + archive_entry_copy_pathname(ae, "dir0/../../dir0/dir1/file1"); archive_entry_set_mode(ae, AE_IFREG | 0755); archive_entry_set_size(ae, 8); archive_entry_set_nlink(ae, 1); @@ -170,7 +170,7 @@ DEFINE_TEST(test_write_format_iso9660) archive_entry_set_birthtime(ae, 3, 30); archive_entry_set_ctime(ae, 4, 40); archive_entry_set_mtime(ae, 5, 50); - archive_entry_copy_pathname(ae, "dir0/dir1/file2"); + archive_entry_copy_pathname(ae, "dir0/..//dir0/dir1/file2"); archive_entry_set_mode(ae, AE_IFREG | 0755); archive_entry_set_size(ae, 8); archive_entry_set_nlink(ae, 1); @@ -195,7 +195,7 @@ DEFINE_TEST(test_write_format_iso9660) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* * ----------------------------------------------------------- @@ -502,7 +502,7 @@ DEFINE_TEST(test_write_format_iso9660) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* * ----------------------------------------------------------- @@ -790,7 +790,7 @@ DEFINE_TEST(test_write_format_iso9660) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); /* * ----------------------------------------------------------- @@ -1103,7 +1103,7 @@ DEFINE_TEST(test_write_format_iso9660) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/libarchive/test/test_write_format_iso9660_boot.c b/libarchive/test/test_write_format_iso9660_boot.c index 433f633091f7..a1cb650db237 100644 --- a/libarchive/test/test_write_format_iso9660_boot.c +++ b/libarchive/test/test_write_format_iso9660_boot.c @@ -130,7 +130,7 @@ _test_write_format_iso9660_boot(int write_info_tbl) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert(used == 2048 * 38); /* Check System Area. */ @@ -263,7 +263,7 @@ _test_write_format_iso9660_boot(int write_info_tbl) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/libarchive/test/test_write_format_iso9660_bugs.c b/libarchive/test/test_write_format_iso9660_bugs.c new file mode 100644 index 000000000000..24f4d3734e63 --- /dev/null +++ b/libarchive/test/test_write_format_iso9660_bugs.c @@ -0,0 +1,305 @@ +/*- + * Copyright (c) 2025 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +#include "test_fuzz_consumer.h" + +#include <stdlib.h> + +/* + * Replay a fuzzer binary through the ISO9660 writer, matching the protocol + * in fuzzers/custom/fuzz_writer_iso9660.cc. + */ +static void +replay_iso9660_writer(const char *refname) +{ + FILE *f; + uint8_t raw[32768]; + size_t rawsize; + struct fuzz_consumer consumer; + uint8_t opts1, opts2, num_entries; + struct archive *a; + struct archive_entry *entry; + size_t used; + void *out_buf; + int i; + + extract_reference_file(refname); + f = fopen(refname, "rb"); + if (!assert(f != NULL)) + return; + rawsize = fread(raw, 1, sizeof(raw), f); + fclose(f); + if (!assert(rawsize >= 6)) + return; + + fuzz_consumer_init(&consumer, raw, rawsize); + opts1 = fuzz_consume_byte(&consumer); + opts2 = fuzz_consume_byte(&consumer); + num_entries = (fuzz_consume_byte(&consumer) % 6) + 1; + + a = archive_write_new(); + if (!assert(a != NULL)) + return; + + archive_write_set_format_iso9660(a); + + if (opts1 & 0x01) + archive_write_set_options(a, "iso9660:rockridge"); + if (opts1 & 0x02) + archive_write_set_options(a, "iso9660:joliet"); + if (opts1 & 0x04) + archive_write_set_options(a, "iso9660:iso-level=3"); + if (opts1 & 0x08) + archive_write_set_options(a, "iso9660:iso-level=4"); + if (opts1 & 0x10) + archive_write_set_options(a, "iso9660:allow-vernum"); + if (opts1 & 0x20) + archive_write_set_options(a, "iso9660:allow-period"); + if (opts1 & 0x40) + archive_write_set_options(a, "iso9660:allow-lowercase"); + if (opts1 & 0x80) + archive_write_set_options(a, "iso9660:allow-multidot"); + + if (opts2 & 0x02) + archive_write_set_options(a, + "iso9660:publisher=FuzzPublisher"); + if (opts2 & 0x04) + archive_write_set_options(a, + "iso9660:volume-id=FUZZISO"); + + out_buf = malloc(4 * 1024 * 1024); + if (!assert(out_buf != NULL)) { + archive_write_free(a); + return; + } + if (archive_write_open_memory(a, out_buf, 4 * 1024 * 1024, &used) + != ARCHIVE_OK) { + archive_write_free(a); + free(out_buf); + return; + } + + entry = archive_entry_new(); + if (!assert(entry != NULL)) { + archive_write_free(a); + free(out_buf); + return; + } + + for (i = 0; i < num_entries && fuzz_consumer_remaining(&consumer) > 2; + i++) { + const char *name; + uint8_t ftype; + uint32_t file_size = 0; + + archive_entry_clear(entry); + + name = fuzz_consume_string(&consumer, 128); + if (name[0] == '\0') + name = "FILE.TXT"; + archive_entry_set_pathname(entry, name); + + ftype = fuzz_consume_byte(&consumer) % 4; + switch (ftype) { + case 0: + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_perm(entry, 0644); + break; + case 1: + archive_entry_set_filetype(entry, AE_IFDIR); + archive_entry_set_perm(entry, 0755); + break; + case 2: + archive_entry_set_filetype(entry, AE_IFLNK); + archive_entry_set_perm(entry, 0777); + archive_entry_set_symlink(entry, + fuzz_consume_string(&consumer, 64)); + break; + case 3: + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_perm(entry, 0755); + break; + } + + archive_entry_set_uid(entry, 1000); + archive_entry_set_gid(entry, 1000); + archive_entry_set_mtime(entry, + 1700000000 + fuzz_consume_u16(&consumer), 0); + archive_entry_set_uname(entry, "user"); + archive_entry_set_gname(entry, "group"); + + if (ftype == 0 || ftype == 3) { + file_size = fuzz_consume_u16(&consumer) % 2048; + archive_entry_set_size(entry, file_size); + } + + if (archive_write_header(a, entry) != ARCHIVE_OK) + continue; + + if (file_size > 0 && + fuzz_consumer_remaining(&consumer) > 0) { + size_t to_write = file_size; + uint8_t data[2048]; + if (to_write > fuzz_consumer_remaining(&consumer)) + to_write = + fuzz_consumer_remaining(&consumer); + fuzz_consume_bytes(&consumer, data, to_write); + archive_write_data(a, data, to_write); + } + } + + archive_entry_free(entry); + /* Close triggers path table construction; must not crash. */ + archive_write_close(a); + archive_write_free(a); + free(out_buf); +} + +DEFINE_TEST(test_write_format_iso9660_null_deref) +{ + replay_iso9660_writer("test_write_format_iso9660_null_deref.bin"); +} + +DEFINE_TEST(test_write_format_iso9660_underflow) +{ + replay_iso9660_writer("test_write_format_iso9660_underflow.bin"); +} + +DEFINE_TEST(test_write_format_iso9660_joliet_overflow) +{ + replay_iso9660_writer("test_write_format_iso9660_joliet_overflow.bin"); +} + +DEFINE_TEST(test_write_format_iso9660_duplicate_identifier_truncation) +{ + const char *names[2]; + struct archive *a; + struct archive_entry *entry; + char name1[66], name2[66]; + unsigned char *buff; + size_t buffsize = 190 * 2048; + size_t i, used = 0; + + /* These names collide after default Joliet identifier truncation. */ + memset(name1, 'A', sizeof(name1)); + memset(name2, 'A', sizeof(name2)); + name1[0] = name2[0] = '.'; + name1[64] = 'X'; + name2[64] = 'Y'; + name1[65] = name2[65] = '\0'; + names[0] = name1; + names[1] = name2; + + buff = malloc(buffsize); + assert(buff != NULL); + if (buff == NULL) + return; + + assert((a = archive_write_new()) != NULL); + if (a == NULL) { + free(buff); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_iso9660(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_set_bytes_in_last_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + for (i = 0; i < 2; i++) { + entry = archive_entry_new(); + if (!assert(entry != NULL)) + break; + archive_entry_copy_pathname(entry, names[i]); + archive_entry_set_mode(entry, AE_IFREG | 0644); + archive_entry_set_size(entry, 0); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_header(a, entry)); + archive_entry_free(entry); + } + failure("ISO9660 writer should resolve duplicate Joliet identifiers " + "after truncation"); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); +} + + +DEFINE_TEST(test_write_format_iso9660_symlink) +{ + const size_t buffsize = 512 * 1024; + unsigned char *buff; + size_t used = 0; + char name[1024]; + struct archive *a; + struct archive_entry *ae; + + assert((buff = malloc(buffsize)) != NULL); + for (size_t i = 0; i + 1 < sizeof(name); i++) { + /* Write the archive */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_iso9660(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + assert((ae = archive_entry_new()) != NULL); + name[i] = 'A'; + name[i + 1] = '\0'; + archive_entry_copy_pathname(ae, name); + archive_entry_set_filetype(ae, AE_IFLNK); + archive_entry_set_symlink(ae, "B"); + archive_entry_set_size(ae, 0); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Read the archive back */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used)); + + /* First entry: the root directory '.' */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualStringA(a, ".", archive_entry_pathname(ae)); + assertEqualIntA(a, AE_IFDIR, archive_entry_filetype(ae)); + + /* Second entry: the symbolic link */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualStringA(a, name, archive_entry_pathname(ae)); + assertEqualIntA(a, AE_IFLNK, archive_entry_filetype(ae)); + assertEqualStringA(a, "B", archive_entry_symlink(ae)); + assertEqualIntA(a, 0, archive_entry_size(ae)); + + /* End of archive */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + } + free(buff); +} diff --git a/libarchive/test/test_write_format_iso9660_empty.c b/libarchive/test/test_write_format_iso9660_empty.c index 55c6c3c7e567..3c1fa60bdc8c 100644 --- a/libarchive/test/test_write_format_iso9660_empty.c +++ b/libarchive/test/test_write_format_iso9660_empty.c @@ -131,7 +131,7 @@ DEFINE_TEST(test_write_format_iso9660_empty) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert(used == 2048 * 181); /* Check System Area. */ @@ -198,7 +198,7 @@ DEFINE_TEST(test_write_format_iso9660_empty) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/libarchive/test/test_write_format_iso9660_filename.c b/libarchive/test/test_write_format_iso9660_filename.c index ca617c3a94d8..675ca2849734 100644 --- a/libarchive/test/test_write_format_iso9660_filename.c +++ b/libarchive/test/test_write_format_iso9660_filename.c @@ -194,7 +194,7 @@ verify(unsigned char *buff, size_t used, enum vtype type, struct fns *fns) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } static int @@ -297,7 +297,7 @@ create_iso_image(unsigned char *buff, size_t buffsize, size_t *used, /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); return (fcnt); } diff --git a/libarchive/test/test_write_format_iso9660_joliet_id.c b/libarchive/test/test_write_format_iso9660_joliet_id.c new file mode 100644 index 000000000000..eb5906fb1c7f --- /dev/null +++ b/libarchive/test/test_write_format_iso9660_joliet_id.c @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +/* + * Check that joliet identifier creation avoids naming collision. + */ + +DEFINE_TEST(test_write_format_iso9660_joliet_id) +{ + struct archive *a; + struct archive_entry *ae; + unsigned char *buff; + size_t buffsize = 190 * 2048; + size_t used; + + buff = malloc(buffsize); + assert(buff != NULL); + if (buff == NULL) + return; + + /* ISO9660 format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_iso9660(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a, 1)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + /* Add ":" entry. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, ":"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Add "_" entry. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "_"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Read ISO image. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* + * Read Root Directory + * Root Directory entry must be in ISO image. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_ctime(ae)); + assertEqualInt(archive_entry_atime(ae), archive_entry_mtime(ae)); + assertEqualString(".", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read ":" entry. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString(":", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Read "_" entry. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("_", archive_entry_pathname(ae)); + assert((S_IFDIR | 0555) == archive_entry_mode(ae)); + assertEqualInt(2048, archive_entry_size(ae)); + + /* + * Verify the end of the archive. + */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + + free(buff); +} diff --git a/libarchive/test/test_write_format_iso9660_joliet_overflow.bin.uu b/libarchive/test/test_write_format_iso9660_joliet_overflow.bin.uu new file mode 100644 index 000000000000..5e83566660cf --- /dev/null +++ b/libarchive/test/test_write_format_iso9660_joliet_overflow.bin.uu @@ -0,0 +1,4 @@ +begin 644 test_write_format_iso9660_joliet_overflow.bin +/_0"!_P`O_X$&@8$O<X&! +` +end diff --git a/libarchive/test/test_write_format_iso9660_null_deref.bin.uu b/libarchive/test/test_write_format_iso9660_null_deref.bin.uu new file mode 100644 index 000000000000..991301f30b60 --- /dev/null +++ b/libarchive/test/test_write_format_iso9660_null_deref.bin.uu @@ -0,0 +1,5 @@ +begin 644 test_write_format_iso9660_null_deref.bin +M00`O02\O+S%`'2\O22\O22\O24=.3U)Z0"\R+R<O+TDO+T4O24=.3U)Z0"\R +,+R<O+TDO+T4O,2]% +` +end diff --git a/libarchive/test/test_write_format_iso9660_rockridge.c b/libarchive/test/test_write_format_iso9660_rockridge.c new file mode 100644 index 000000000000..db07231ea284 --- /dev/null +++ b/libarchive/test/test_write_format_iso9660_rockridge.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_write_format_iso9660_rockridge) +{ + struct archive *a; + struct archive_entry *ae; + unsigned char *buff; + size_t buffsize = 128 * 2048; + size_t used; + + buff = malloc(buffsize); + assert(buff != NULL); + if (buff == NULL) + return; + + /* ISO9660 format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == archive_write_set_format_iso9660(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a, 1)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 1)); + assertA(0 == archive_write_open_memory(a, buff, buffsize, &used)); + + /* Add a file with a depth of 16. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_atime(ae, 2, 0); + archive_entry_set_ctime(ae, 4, 0); + archive_entry_set_mtime(ae, 5, 0); + archive_entry_copy_pathname(ae, "1/2/3/4/5/6/7/8/9/A/B/C/D/E/F"); + archive_entry_set_mode(ae, S_IFDIR | 0755); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* XXX - Known to fail currently. */ + assertEqualIntA(a, ARCHIVE_FATAL, archive_write_close(a)); + + /* Close out the archive. */ + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + free(buff); +} diff --git a/libarchive/test/test_write_format_iso9660_underflow.bin.uu b/libarchive/test/test_write_format_iso9660_underflow.bin.uu new file mode 100644 index 000000000000..0a29dde2674c --- /dev/null +++ b/libarchive/test/test_write_format_iso9660_underflow.bin.uu @@ -0,0 +1,5 @@ +begin 644 test_write_format_iso9660_underflow.bin +MN;FYN;FYN;FYN;FYN;FYN;FYN;FYN;FYN;FYN;FYN;FYN;FYN;FYN;FYN;FY +FN;FY02Z^+BXN+RXN+R])1TY/4BXN+BXN+BXL+B])1TY/+H,N+@`` +` +end diff --git a/libarchive/test/test_write_format_iso9660_zisofs.c b/libarchive/test/test_write_format_iso9660_zisofs.c index 2140ed8c3181..f0173c441aa3 100644 --- a/libarchive/test/test_write_format_iso9660_zisofs.c +++ b/libarchive/test/test_write_format_iso9660_zisofs.c @@ -186,7 +186,7 @@ test_write_format_iso9660_zisofs_1(void) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); failure("The ISO image size should be 71680 bytes."); assertEqualInt(used, 2048 * 35); @@ -318,7 +318,7 @@ test_write_format_iso9660_zisofs_1(void) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } @@ -433,7 +433,7 @@ test_write_format_iso9660_zisofs_2(void) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); failure("The ISO image size should be 110592 bytes."); assertEqualInt(used, 2048 * 54); @@ -567,7 +567,7 @@ test_write_format_iso9660_zisofs_2(void) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } @@ -656,7 +656,7 @@ test_write_format_iso9660_zisofs_3(void) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); failure("The ISO image size should be 81920 bytes."); assertEqualInt(used, 2048 * 40); @@ -815,7 +815,7 @@ test_write_format_iso9660_zisofs_3(void) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/libarchive/test/test_write_format_mtree.c b/libarchive/test/test_write_format_mtree.c index ed065f9c1340..907e291f2f55 100644 --- a/libarchive/test/test_write_format_mtree.c +++ b/libarchive/test/test_write_format_mtree.c @@ -109,7 +109,7 @@ test_write_format_mtree_sub(int use_set, int dironly) assertEqualInt(ARCHIVE_OK, archive_write_free(a)); if (use_set) { - const char *p; + char *p; buff[used] = '\0'; assert(NULL != (p = strstr(buff, "\n/set "))); @@ -197,7 +197,7 @@ test_write_format_mtree_sub2(int use_set, int dironly) assertEqualInt(ARCHIVE_OK, archive_write_free(a)); if (use_set) { - const char *p; + char *p; buff[used] = '\0'; assert(NULL != (p = strstr(buff, "\n/set "))); diff --git a/libarchive/test/test_write_format_mtree_absolute.c b/libarchive/test/test_write_format_mtree_absolute.c new file mode 100644 index 000000000000..d53cca362ae0 --- /dev/null +++ b/libarchive/test/test_write_format_mtree_absolute.c @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" + +static char buff[4096]; +static struct { + const char *path; + mode_t mode; + int nlink; + time_t mtime; + uid_t uid; + gid_t gid; +} entries[] = { + { ".", S_IFDIR | 0755, 3, 1231975636, 1001, 1001 }, + { "./COPYING", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./Makefile", S_IFREG | 0644, 1, 1233041050, 1001, 1001 }, + { "./NEWS", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./PROJECTS", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./README", S_IFREG | 0644, 1, 1231975636, 1001, 1001 }, + { "./subdir", S_IFDIR | 0755, 3, 1233504586, 1001, 1001 }, + { "./subdir/README", S_IFREG | 0664, 1, 1231975636, 1002, 1001 }, + { "./subdir/config", S_IFREG | 0664, 1, 1232266273, 1003, 1003 }, + { "./subdir2", S_IFDIR | 0755, 3, 1233504586, 1001, 1001 }, + { "./subdir3", S_IFDIR | 0755, 3, 1233504586, 1001, 1001 }, + { "./subdir3/mtree", S_IFREG | 0664, 2, 1232266273, 1003, 1003 }, + { NULL, 0, 0, 0, 0, 0 } +}; + +static const char image [] = { +"#mtree\n" +". time=1231975636.0 mode=755 gid=1001 uid=1001 type=dir\n" +"./COPYING time=1231975636.0 mode=644 gid=1001 uid=1001 type=file size=8\n" +"./Makefile time=1233041050.0 mode=644 gid=1001 uid=1001 type=file size=8\n" +"./NEWS time=1231975636.0 mode=644 gid=1001 uid=1001 type=file size=8\n" +"./PROJECTS time=1231975636.0 mode=644 gid=1001 uid=1001 type=file size=8\n" +"./README time=1231975636.0 mode=644 gid=1001 uid=1001 type=file size=8\n" +"./subdir time=1233504586.0 mode=755 gid=1001 uid=1001 type=dir\n" +"./subdir/README time=1231975636.0 mode=664 gid=1001 uid=1002 type=file size=8\n" +"./subdir/config time=1232266273.0 mode=664 gid=1003 uid=1003 type=file size=8\n" +"./subdir2 time=1233504586.0 mode=755 gid=1001 uid=1001 type=dir\n" +"./subdir3 time=1233504586.0 mode=755 gid=1001 uid=1001 type=dir\n" +"./subdir3/mtree nlink=2 time=1232266273.0 mode=664 gid=1003 uid=1003 type=file size=8\n" +}; + +DEFINE_TEST(test_write_format_mtree_absolute) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + int i; + + /* Create a mtree format archive. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff) - 1, &used)); + + /* Write entries */ + for (i = 0; entries[i].path != NULL; i++) { + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_nlink(ae, entries[i].nlink); + assertEqualInt(entries[i].nlink, archive_entry_nlink(ae)); + archive_entry_set_mtime(ae, entries[i].mtime, 0); + assertEqualInt(entries[i].mtime, archive_entry_mtime(ae)); + archive_entry_set_mode(ae, entries[i].mode); + assertEqualInt(entries[i].mode, archive_entry_mode(ae)); + archive_entry_set_uid(ae, entries[i].uid); + assertEqualInt(entries[i].uid, archive_entry_uid(ae)); + archive_entry_set_gid(ae, entries[i].gid); + assertEqualInt(entries[i].gid, archive_entry_gid(ae)); + archive_entry_copy_pathname(ae, entries[i].path); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + archive_entry_set_size(ae, 8); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + assertEqualIntA(a, 8, + archive_write_data(a, "Hello012", 15)); + archive_entry_free(ae); + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + buff[used] = '\0'; + assertEqualString(buff, image); + + /* + * Read the data and check it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Read entries */ + for (i = 0; entries[i].path != NULL; i++) { + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualInt(entries[i].mtime, archive_entry_mtime(ae)); + assertEqualInt(entries[i].mode, archive_entry_mode(ae)); + assertEqualInt(entries[i].uid, archive_entry_uid(ae)); + assertEqualInt(entries[i].gid, archive_entry_gid(ae)); + assertEqualString(entries[i].path, + archive_entry_pathname(ae)); + if ((entries[i].mode & AE_IFMT) != S_IFDIR) + assertEqualInt(8, archive_entry_size(ae)); + } + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_write_format_mtree_dotdot.c b/libarchive/test/test_write_format_mtree_dotdot.c new file mode 100644 index 000000000000..731b11434cb3 --- /dev/null +++ b/libarchive/test/test_write_format_mtree_dotdot.c @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +static char buff[4096]; + +DEFINE_TEST(test_write_format_mtree_dotdot) +{ + struct archive_entry *ae; + struct archive* a; + size_t used; + + /* Create an mtree format archive. */ + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); + + /* Write "./dir0/dir1" directory. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "./dir0/dir1"); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Write "dir0/../../dir0/dir1/file1" file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir0/../../dir0/dir1/file1"); + archive_entry_set_size(ae, 0); + archive_entry_set_mode(ae, AE_IFREG | 0644); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Write "dir0/..//dir0/dir1/file2" file. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "dir0/..//dir0/dir1/file2"); + archive_entry_set_size(ae, 0); + archive_entry_set_mode(ae, AE_IFREG | 0644); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Read the data and check it. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); + + /* Read "./dir0/dir1" directory. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("The path should be just \"./dir0/dir1\""); + assertEqualString(archive_entry_pathname(ae), "./dir0/dir1"); + assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755); + + /* Read "./dir0/dir1/file1" file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("The path should be just \"./dir0/dir1/file1\""); + assertEqualString(archive_entry_pathname(ae), "./dir0/dir1/file1"); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + + /* Read "./dir0/dir1/file2" file. */ + assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + failure("The path should be just \"./dir0/dir1/file2\""); + assertEqualString(archive_entry_pathname(ae), "./dir0/dir1/file2"); + assertEqualInt(archive_entry_size(ae), 0); + assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + diff --git a/libarchive/test/test_write_format_mtree_null_deref.bin.uu b/libarchive/test/test_write_format_mtree_null_deref.bin.uu new file mode 100644 index 000000000000..20588d313371 --- /dev/null +++ b/libarchive/test/test_write_format_mtree_null_deref.bin.uu @@ -0,0 +1,4 @@ +begin 644 test_write_format_mtree_null_deref.bin +&IRXN`$"W +` +end diff --git a/libarchive/test/test_write_format_mtree_null_deref.c b/libarchive/test/test_write_format_mtree_null_deref.c new file mode 100644 index 000000000000..843bfb5d7f7f --- /dev/null +++ b/libarchive/test/test_write_format_mtree_null_deref.c @@ -0,0 +1,233 @@ +/*- + * Copyright (c) 2025 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +#include "test_fuzz_consumer.h" + +#include <stdlib.h> + +/* + * Replay a fuzzer binary through the MTREE writer, matching the protocol + * in fuzzers/custom/fuzz_writer_mtree.cc. + */ +DEFINE_TEST(test_write_format_mtree_null_deref) +{ + const char *refname = "test_write_format_mtree_null_deref.bin"; + FILE *f; + uint8_t raw[16384]; + size_t rawsize; + struct fuzz_consumer consumer; + uint8_t opts, num_entries; + struct archive *a; + struct archive_entry *entry; + size_t used; + void *out_buf; + int i; + + extract_reference_file(refname); + f = fopen(refname, "rb"); + if (!assert(f != NULL)) + return; + rawsize = fread(raw, 1, sizeof(raw), f); + fclose(f); + if (!assert(rawsize >= 4)) + return; + + fuzz_consumer_init(&consumer, raw, rawsize); + opts = fuzz_consume_byte(&consumer); + num_entries = (fuzz_consume_byte(&consumer) % 8) + 1; + + a = archive_write_new(); + if (!assert(a != NULL)) + return; + + if (opts & 0x01) + archive_write_set_format_mtree_classic(a); + else + archive_write_set_format_mtree(a); + + if (opts & 0x02) + archive_write_set_options(a, "mtree:all"); + if (opts & 0x04) + archive_write_set_options(a, "mtree:use-set"); + if (opts & 0x08) + archive_write_set_options(a, "mtree:indent"); + if (opts & 0x10) + archive_write_set_options(a, "mtree:dironly"); + + out_buf = malloc(256 * 1024); + if (!assert(out_buf != NULL)) { + archive_write_free(a); + return; + } + if (archive_write_open_memory(a, out_buf, 256 * 1024, &used) + != ARCHIVE_OK) { + archive_write_free(a); + free(out_buf); + return; + } + + entry = archive_entry_new(); + if (!assert(entry != NULL)) { + archive_write_free(a); + free(out_buf); + return; + } + + for (i = 0; i < num_entries && fuzz_consumer_remaining(&consumer) > 2; + i++) { + const char *name; + uint8_t ftype; + uint32_t file_size = 0; + + archive_entry_clear(entry); + + name = fuzz_consume_string(&consumer, 128); + if (name[0] == '\0') + name = "file.txt"; + archive_entry_set_pathname(entry, name); + + ftype = fuzz_consume_byte(&consumer) % 5; + switch (ftype) { + case 0: + archive_entry_set_filetype(entry, AE_IFREG); + archive_entry_set_perm(entry, 0644); + break; + case 1: + archive_entry_set_filetype(entry, AE_IFDIR); + archive_entry_set_perm(entry, 0755); + break; + case 2: + archive_entry_set_filetype(entry, AE_IFLNK); + archive_entry_set_perm(entry, 0777); + archive_entry_set_symlink(entry, + fuzz_consume_string(&consumer, 64)); + break; + case 3: + archive_entry_set_filetype(entry, AE_IFBLK); + archive_entry_set_perm(entry, 0600); + archive_entry_set_rdev(entry, + fuzz_consume_u16(&consumer)); + break; + case 4: + archive_entry_set_filetype(entry, AE_IFIFO); + archive_entry_set_perm(entry, 0644); + break; + } + + archive_entry_set_uid(entry, fuzz_consume_byte(&consumer)); + archive_entry_set_gid(entry, fuzz_consume_byte(&consumer)); + archive_entry_set_mtime(entry, + 1700000000 + fuzz_consume_u16(&consumer), 0); + archive_entry_set_uname(entry, "user"); + archive_entry_set_gname(entry, "group"); + + if (fuzz_consumer_remaining(&consumer) > 1 && + (fuzz_consume_byte(&consumer) & 0x01)) + archive_entry_copy_fflags_text(entry, "uappnd,uchg"); + + if (ftype == 0) { + file_size = fuzz_consume_byte(&consumer) % 128; + archive_entry_set_size(entry, file_size); + } + + if (archive_write_header(a, entry) != ARCHIVE_OK) + continue; + + if (file_size > 0 && fuzz_consumer_remaining(&consumer) > 0) { + size_t to_write = file_size; + uint8_t data[128]; + if (to_write > fuzz_consumer_remaining(&consumer)) + to_write = fuzz_consumer_remaining(&consumer); + fuzz_consume_bytes(&consumer, data, to_write); + archive_write_data(a, data, to_write); + } + } + + archive_entry_free(entry); + /* Close triggers tree traversal; must not crash. */ + archive_write_close(a); + archive_write_free(a); + free(out_buf); +} + +DEFINE_TEST(test_write_format_mtree_no_set_symlink) +{ + struct archive *a; + size_t buffsize = 4096; + char *buff; + size_t used; + assert((buff = malloc(buffsize)) != NULL); + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + struct archive_entry *ae; + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "./badlink"), + archive_entry_set_filetype(ae, AE_IFLNK); + archive_entry_set_perm(ae, 0777); + /* archive_entry_set_symlink(ae, "target"); (omitted) */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); +} + +DEFINE_TEST(test_write_format_mtree_reg_dot_root) +{ + struct archive *a; + size_t buffsize = 4096; + char *buff; + size_t used; + assert((buff = malloc(buffsize)) != NULL); + assert((a = archive_write_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, buffsize, &used)); + + struct archive_entry *ae; + /* Entry 1: "." with filetype AE_IFREG (not AE_IFDIR). */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "."), + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_perm(ae, 0644); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Entry 2: any child path. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "./foo"), + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_perm(ae, 0644); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(buff); +} diff --git a/libarchive/test/test_write_format_mtree_preset_digests.c b/libarchive/test/test_write_format_mtree_preset_digests.c index bb8ddf49431b..43a7e14e97ed 100644 --- a/libarchive/test/test_write_format_mtree_preset_digests.c +++ b/libarchive/test/test_write_format_mtree_preset_digests.c @@ -99,10 +99,9 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -131,7 +130,7 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); } DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_empty_data) @@ -190,10 +189,9 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -222,7 +220,7 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); } DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_non_empty_data) @@ -282,10 +280,9 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_non_empty_data) archive_write_data(a, data, 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -314,7 +311,7 @@ DEFINE_TEST(test_write_format_mtree_digests_no_digests_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); } DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_no_data) @@ -373,10 +370,9 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -403,7 +399,7 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support MD5"); return; @@ -467,10 +463,9 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -503,7 +498,7 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support MD5"); return; @@ -567,10 +562,9 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -603,7 +597,7 @@ DEFINE_TEST(test_write_format_mtree_digests_md5_digest_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support MD5"); return; @@ -664,10 +658,9 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -694,7 +687,7 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support RMD160"); return; @@ -758,10 +751,9 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -794,7 +786,7 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support RMD160"); return; @@ -858,10 +850,9 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -894,7 +885,7 @@ DEFINE_TEST(test_write_format_mtree_digests_rmd160_digest_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support RMD160"); return; @@ -957,10 +948,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -987,7 +977,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA1"); return; @@ -1051,10 +1041,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -1087,7 +1076,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA1"); return; @@ -1151,10 +1140,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -1187,7 +1175,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha1_digest_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA1"); return; @@ -1252,10 +1240,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -1282,7 +1269,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA256"); return; @@ -1348,10 +1335,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -1384,7 +1370,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA256"); return; @@ -1450,10 +1436,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -1486,7 +1471,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha256_digest_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA256"); return; @@ -1552,10 +1537,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -1582,7 +1566,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_no_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA384"); return; @@ -1649,10 +1633,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -1685,7 +1668,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA384"); return; @@ -1752,10 +1735,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -1788,7 +1770,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha384_digest_set_non_empty_data) #ifdef ARCHIVE_HAS_SHA512 assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); #endif - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA384"); return; @@ -1856,10 +1838,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_no_data) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -1887,7 +1868,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_no_data) assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA512"); return; @@ -1956,10 +1937,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_empty_data) archive_write_data(a, "", 0); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -1993,7 +1973,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_empty_data) assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA512"); return; @@ -2062,10 +2042,9 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_non_empty_data) archive_write_data(a, "abcd", 4); archive_entry_free(entry); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); assert((a = archive_read_new()) != NULL); - assert((entry = archive_entry_new()) != NULL); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); @@ -2099,7 +2078,7 @@ DEFINE_TEST(test_write_format_mtree_digests_sha512_digest_set_non_empty_data) assert(memcmp(archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA512), ed.sha512, sizeof(ed.sha512)) == 0); - archive_entry_free(entry); + archive_read_free(a); #else skipping("This platform does not support SHA512"); return; diff --git a/libarchive/test/test_write_format_pax.c b/libarchive/test/test_write_format_pax.c index 625a3742c044..a84fb8250521 100644 --- a/libarchive/test/test_write_format_pax.c +++ b/libarchive/test/test_write_format_pax.c @@ -133,7 +133,7 @@ DEFINE_TEST(test_write_format_pax) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* * @@ -248,7 +248,7 @@ DEFINE_TEST(test_write_format_pax) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } diff --git a/libarchive/test/test_write_format_tar_empty_dirname.c b/libarchive/test/test_write_format_tar_empty_dirname.c new file mode 100644 index 000000000000..7536078799f1 --- /dev/null +++ b/libarchive/test/test_write_format_tar_empty_dirname.c @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +static void +test_format(int (*set_format)(struct archive *)) +{ + struct archive *a; + struct archive_entry *entry; + char buff[2048]; + size_t used; + + /* Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + assertA(0 == set_format(a)); + assertA(0 == archive_write_add_filter_none(a)); + assertA(0 == archive_write_set_bytes_per_block(a, 512)); + assertA(0 == archive_write_set_bytes_in_last_block(a, 512)); + assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Write directory with empty wide character name */ + assert((entry = archive_entry_new()) != NULL); + archive_entry_copy_pathname_w(entry, L""); + archive_entry_set_mode(entry, S_IFDIR | 0755); + archive_entry_set_uid(entry, 0); + archive_entry_set_gid(entry, 0); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry)); + + /* Close out the archive. */ + archive_entry_free(entry); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_open_memory(a, buff, used)); + assertEqualIntA(a, ARCHIVE_OK, + archive_read_next_header(a, &entry)); + assertEqualString("", archive_entry_pathname(entry)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_next_header(a, &entry)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + +} + +DEFINE_TEST(test_write_format_tar_empty_dirname) +{ + test_format(archive_write_set_format_gnutar); + test_format(archive_write_set_format_pax); + test_format(archive_write_set_format_ustar); + test_format(archive_write_set_format_v7tar); +} diff --git a/libarchive/test/test_write_format_xar.c b/libarchive/test/test_write_format_xar.c index a3e2577de964..495400a34f92 100644 --- a/libarchive/test/test_write_format_xar.c +++ b/libarchive/test/test_write_format_xar.c @@ -44,14 +44,14 @@ test_xar(const char *option) assert((a = archive_write_new()) != NULL); if (archive_write_set_format_xar(a) != ARCHIVE_OK) { skipping("xar is not supported on this platform"); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); return; } assertA(0 == archive_write_add_filter_none(a)); if (option != NULL && archive_write_set_options(a, option) != ARCHIVE_OK) { skipping("option `%s` is not supported on this platform", option); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); return; } @@ -93,13 +93,13 @@ test_xar(const char *option) archive_entry_free(ae); /* - * "dir/file3" has a bunch of attributes and 8 bytes of data. + * "dir/file" has a bunch of attributes and 8 bytes of data. */ assert((ae = archive_entry_new()) != NULL); archive_entry_set_atime(ae, 2, 20); archive_entry_set_ctime(ae, 4, 40); archive_entry_set_mtime(ae, 5, 50); - archive_entry_copy_pathname(ae, "dir/file"); + archive_entry_copy_pathname(ae, "dir/../../dir/file"); archive_entry_set_mode(ae, AE_IFREG | 0755); archive_entry_set_size(ae, 8); assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); @@ -113,7 +113,7 @@ test_xar(const char *option) archive_entry_set_atime(ae, 2, 20); archive_entry_set_ctime(ae, 4, 40); archive_entry_set_mtime(ae, 5, 50); - archive_entry_copy_pathname(ae, "dir/dir2/file4"); + archive_entry_copy_pathname(ae, "dir/..//dir/dir2/file4"); archive_entry_copy_hardlink(ae, "file"); archive_entry_set_mode(ae, AE_IFREG | 0755); archive_entry_set_nlink(ae, 2); @@ -170,7 +170,7 @@ test_xar(const char *option) /* Close out the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); /* * @@ -298,7 +298,7 @@ test_xar(const char *option) */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); free(buff); } @@ -351,3 +351,32 @@ DEFINE_TEST(test_write_format_xar) test_xar("compression=xz,compression-level=1"); test_xar("compression=xz,compression-level=9"); } + +DEFINE_TEST(test_write_format_xar_entry_trunc) +{ + struct archive *a; + struct archive_entry *ae; + unsigned char buff[1024]; + size_t used = 0; + + assert((a = archive_write_new()) != NULL); + if (archive_write_set_format_xar(a) != ARCHIVE_OK) { + skipping("xar is not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, "foo"); + archive_entry_set_mode(ae, S_IFREG | 0644); + archive_entry_set_size(ae, 1028); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 3, archive_write_data(a, "foo", 3)); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} diff --git a/libarchive/test/test_write_format_xar_bugs.c b/libarchive/test/test_write_format_xar_bugs.c new file mode 100644 index 000000000000..2b446b679075 --- /dev/null +++ b/libarchive/test/test_write_format_xar_bugs.c @@ -0,0 +1,170 @@ +/*- + * Copyright (c) 2025 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" +#include "test_fuzz_consumer.h" + +#include <stdlib.h> + +/* + * Replay a fuzzer binary through the XAR writer, matching the protocol + * in fuzzers/custom/fuzz_writer_xar.cc. + */ +static void +replay_xar_writer(const char *refname) +{ + FILE *f; + uint8_t raw[16384]; + size_t rawsize; + struct fuzz_consumer consumer; + uint8_t opts, num_entries; + struct archive *a; + struct archive_entry *entry; + size_t used; + char *out_buf; + int i; + + extract_reference_file(refname); + f = fopen(refname, "rb"); + if (!assert(f != NULL)) + return; + rawsize = fread(raw, 1, sizeof(raw), f); + fclose(f); + if (!assert(rawsize >= 6)) + return; + + fuzz_consumer_init(&consumer, raw, rawsize); + opts = fuzz_consume_byte(&consumer); + num_entries = (fuzz_consume_byte(&consumer) % 5) + 1; + + a = archive_write_new(); + if (!assert(a != NULL)) + return; + + archive_write_set_format_xar(a); + archive_write_add_filter_none(a); + + if (opts & 0x01) + archive_write_set_options(a, "xar:compression=gzip"); + if (opts & 0x02) + archive_write_set_options(a, "xar:compression=bzip2"); + if (opts & 0x04) + archive_write_set_options(a, "xar:checksum=sha1"); + if (opts & 0x08) + archive_write_set_options(a, "xar:checksum=md5"); + + out_buf = (char *)malloc(512 * 1024); + if (!assert(out_buf != NULL)) { + archive_write_free(a); + return; + } + if (archive_write_open_memory(a, out_buf, 512 * 1024, &used) + != ARCHIVE_OK) { + archive_write_free(a); + free(out_buf); + return; + } + + entry = archive_entry_new(); + if (!assert(entry != NULL)) { + archive_write_free(a); + free(out_buf); + return; + } + + for (i = 0; i < num_entries && fuzz_consumer_remaining(&consumer) > 4; + i++) { + const char *path; + uint8_t ftype; + uint16_t raw_mode; + int64_t file_size = 0; + + archive_entry_clear(entry); + + path = fuzz_consume_string(&consumer, 200); + if (path[0] == '\0') + path = "file.txt"; + archive_entry_set_pathname(entry, path); + + ftype = fuzz_consume_byte(&consumer) % 4; + raw_mode = fuzz_consume_u16(&consumer) & 07777; + switch (ftype) { + case 0: archive_entry_set_filetype(entry, AE_IFREG); break; + case 1: archive_entry_set_filetype(entry, AE_IFDIR); break; + case 2: archive_entry_set_filetype(entry, AE_IFLNK); break; + default: archive_entry_set_filetype(entry, AE_IFCHR); break; + } + archive_entry_set_perm(entry, raw_mode); + + archive_entry_set_uname(entry, + fuzz_consume_string(&consumer, 32)); + archive_entry_set_gname(entry, + fuzz_consume_string(&consumer, 32)); + archive_entry_set_uid(entry, fuzz_consume_u32(&consumer)); + archive_entry_set_gid(entry, fuzz_consume_u32(&consumer)); + archive_entry_set_mtime(entry, + fuzz_consume_i64(&consumer), fuzz_consume_u32(&consumer)); + archive_entry_set_atime(entry, + fuzz_consume_i64(&consumer), 0); + archive_entry_set_ctime(entry, + fuzz_consume_i64(&consumer), 0); + + if (ftype == 0) { + file_size = fuzz_consume_byte(&consumer) % 200; + archive_entry_set_size(entry, file_size); + } + + if (ftype == 2) + archive_entry_set_symlink(entry, + fuzz_consume_string(&consumer, 64)); + + if (archive_write_header(a, entry) == ARCHIVE_OK + && file_size > 0) { + size_t write_len = (size_t)file_size; + if (write_len > fuzz_consumer_remaining(&consumer)) + write_len = fuzz_consumer_remaining(&consumer); + if (write_len > 0) { + uint8_t file_data[200]; + fuzz_consume_bytes(&consumer, file_data, + write_len); + archive_write_data(a, file_data, write_len); + } + } + } + + archive_entry_free(entry); + archive_write_close(a); + archive_write_free(a); + free(out_buf); +} + +DEFINE_TEST(test_write_format_xar_strcpy_overlap) +{ + replay_xar_writer("test_write_format_xar_strcpy_overlap.bin"); +} + +DEFINE_TEST(test_write_format_xar_underflow) +{ + replay_xar_writer("test_write_format_xar_underflow.bin"); +} diff --git a/libarchive/test/test_write_format_xar_empty.c b/libarchive/test/test_write_format_xar_empty.c index b3ba6994e9c9..c774c8d4c929 100644 --- a/libarchive/test/test_write_format_xar_empty.c +++ b/libarchive/test/test_write_format_xar_empty.c @@ -41,7 +41,7 @@ DEFINE_TEST(test_write_format_xar_empty) assert((a = archive_write_new()) != NULL); if (archive_write_set_format_xar(a) != ARCHIVE_OK) { skipping("xar is not supported on this platform"); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); return; } assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); diff --git a/libarchive/test/test_write_format_xar_fflags.c b/libarchive/test/test_write_format_xar_fflags.c new file mode 100644 index 000000000000..e176f379e5d3 --- /dev/null +++ b/libarchive/test/test_write_format_xar_fflags.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2026 Tobias Stoeckmann + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "test.h" + +DEFINE_TEST(test_write_format_xar_fflags) +{ + struct archive *a; + struct archive_entry *ae; + char buff[4096]; + size_t used; + + /* Xar format: Create a new archive in memory. */ + assert((a = archive_write_new()) != NULL); + if (archive_write_set_format_xar(a) != ARCHIVE_OK) { + skipping("xar is not supported on this platform"); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + return; + } + assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_per_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1)); + assertEqualIntA(a, ARCHIVE_OK, + archive_write_open_memory(a, buff, sizeof(buff), &used)); + + /* Add "file" entry. */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "file"); + archive_entry_set_mode(ae, S_IFREG | 0644); + archive_entry_set_size(ae, 0); + archive_entry_copy_fflags_text(ae, "sappnd,sappnd,sappnd,very_long_name_but_unknown"); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + /* Close out the archive. */ + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* + * Now, read the data back. + */ + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, 0, archive_read_support_format_all(a)); + assertEqualIntA(a, 0, archive_read_support_filter_all(a)); + assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used)); + + /* Read "file". */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualString("file", archive_entry_pathname(ae)); + assert((AE_IFREG | 0644) == archive_entry_mode(ae)); + assertEqualInt(0, archive_entry_size(ae)); + + /* Verify the end of the archive. */ + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} diff --git a/libarchive/test/test_write_format_xar_strcpy_overlap.bin.uu b/libarchive/test/test_write_format_xar_strcpy_overlap.bin.uu new file mode 100644 index 000000000000..59850557cee0 --- /dev/null +++ b/libarchive/test/test_write_format_xar_strcpy_overlap.bin.uu @@ -0,0 +1,6 @@ +begin 644 test_write_format_xar_strcpy_overlap.bin +M=&EI9/____\L261I+&1I+"\N+B\L9"UF+&8L+(0M:2YT9C8L+RXN+R\N+B]T +M+(0M9C8L+RXN+R\N+F8L9BPLA"UF9$G_-BPO+B[__XLN+R\N+B]T+(0M9C8L +.+RXN+R\N:2XO/2]T=/\` +` +end diff --git a/libarchive/test/test_write_format_xar_underflow.bin.uu b/libarchive/test/test_write_format_xar_underflow.bin.uu new file mode 100644 index 000000000000..4f15b5505423 --- /dev/null +++ b/libarchive/test/test_write_format_xar_underflow.bin.uu @@ -0,0 +1,6 @@ +begin 644 test_write_format_xar_underflow.bin +M=&EI9/____\L261I+&1I+"\N+B\L9"UF+&8L+(0M:2YT9C8L+RXN+R\N+B]T +M+(0M9C8L+RXN+R\N+F8L9BPLA"UF9$G_-BPO+B[__XLN+R\N+B]T+(0M9C8L +.+RXN+R\N:2XO/2]T=/\` +` +end diff --git a/libarchive/test/test_write_format_zip.c b/libarchive/test/test_write_format_zip.c index 583c78c3ace4..569b54da5e22 100644 --- a/libarchive/test/test_write_format_zip.c +++ b/libarchive/test/test_write_format_zip.c @@ -262,7 +262,7 @@ write_contents(struct archive *a) /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); } @@ -550,7 +550,7 @@ verify_contents(struct archive *a, int seeking, int content) /* Verify the end of the archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/test/test_write_format_zip_compression_lzmaxz.c b/libarchive/test/test_write_format_zip_compression_lzmaxz.c index c5bb2d659a04..f627b1930a1b 100644 --- a/libarchive/test/test_write_format_zip_compression_lzmaxz.c +++ b/libarchive/test/test_write_format_zip_compression_lzmaxz.c @@ -23,9 +23,10 @@ static const short folder_gid = 40; static time_t now; -static void verify_write_lzma(struct archive *a) +static int verify_write_lzma(struct archive *a) { struct archive_entry *entry; + int r; /* Write entries. */ @@ -38,7 +39,13 @@ static void verify_write_lzma(struct archive *a) archive_entry_set_gid(entry, file_gid); archive_entry_set_mtime(entry, now, 0); archive_entry_set_atime(entry, now + 3, 0); - assertEqualIntA(a, 0, archive_write_header(a, entry)); + r = archive_write_header(a, entry); + if (r == ARCHIVE_FATAL && archive_errno(a) == ENOMEM) { + archive_entry_free(entry); + archive_free(a); + return -1; + } + assertEqualIntA(a, ARCHIVE_OK, r); assertEqualIntA(a, sizeof(file_data1), archive_write_data(a, file_data1, sizeof(file_data1))); assertEqualIntA(a, sizeof(file_data2), archive_write_data(a, file_data2, sizeof(file_data2))); archive_entry_free(entry); @@ -54,6 +61,8 @@ static void verify_write_lzma(struct archive *a) archive_entry_set_ctime(entry, now + 5, 0); assertEqualIntA(a, 0, archive_write_header(a, entry)); archive_entry_free(entry); + + return 0; } static void verify_xz_lzma(const char *buff, size_t used, uint16_t id, @@ -361,7 +370,10 @@ DEFINE_TEST(test_write_format_zip_compression_lzmaxz) assertEqualIntA(a, ARCHIVE_OK, archive_write_set_bytes_in_last_block(a, 1)); assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used)); - verify_write_lzma(a); + if (verify_write_lzma(a) < 0) { + skipping("Not enough memory available"); + return; + } /* Close the archive. */ assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); diff --git a/libarchive/test/test_write_format_zip_empty_pathname.c b/libarchive/test/test_write_format_zip_empty_pathname.c new file mode 100644 index 000000000000..423616f4e9ab --- /dev/null +++ b/libarchive/test/test_write_format_zip_empty_pathname.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" + +/* + * An empty pathname must be rejected (ARCHIVE_FAILED) by the ZIP writer. + * + * write_path() used bitwise & instead of logical && when checking whether + * to append a trailing slash for directory entries. Because & does not + * short-circuit, path[strlen(path)-1] was evaluated even when the entry + * was not a directory — and when the path is empty, strlen(path)-1 wraps + * to SIZE_MAX, producing a one-byte OOB read before the heap buffer. + */ +DEFINE_TEST(test_write_format_zip_empty_pathname) +{ + struct archive *a; + struct archive_entry *ae; + char buf[4096]; + size_t used; + + /* Regular file with empty pathname */ + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buf, sizeof(buf), &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, ""); + archive_entry_set_mode(ae, AE_IFREG | 0644); + archive_entry_set_size(ae, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + + /* Directory entry with empty pathname */ + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buf, sizeof(buf), &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, ""); + archive_entry_set_mode(ae, AE_IFDIR | 0755); + archive_entry_set_size(ae, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); +} diff --git a/libarchive/test/test_write_format_zip_long_pathname.c b/libarchive/test/test_write_format_zip_long_pathname.c new file mode 100644 index 000000000000..579505decd3e --- /dev/null +++ b/libarchive/test/test_write_format_zip_long_pathname.c @@ -0,0 +1,114 @@ +/*- + * Copyright (c) 2026 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "test.h" + +/* + * ZIP stores the filename length in a 16-bit field, so the maximum is + * 65535 bytes. A pathname of 65536 bytes or more must be rejected + * (ARCHIVE_FAILED) rather than silently truncated in the header and + * written past the end of the central-directory segment buffer. + */ +DEFINE_TEST(test_write_format_zip_long_pathname) +{ + struct archive *a; + struct archive_entry *ae; + char *pathname; + char *buf; + size_t used; + /* Enough room for a valid ZIP with a 65535-byte filename. */ + const size_t bufsize = 256 * 1024; + + buf = malloc(bufsize); + assert(buf != NULL); + + /* 65535-byte pathname: exactly the ZIP maximum — must succeed. */ + pathname = malloc(65536); + assert(pathname != NULL); + memset(pathname, 'a', 65535); + pathname[65535] = '\0'; + + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buf, bufsize, &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, pathname); + archive_entry_set_mode(ae, AE_IFREG | 0644); + archive_entry_set_size(ae, 0); + assertEqualInt(ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(pathname); + + /* 65536-byte pathname: one byte over the ZIP limit — must be rejected. */ + pathname = malloc(65537); + assert(pathname != NULL); + memset(pathname, 'a', 65536); + pathname[65536] = '\0'; + + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buf, bufsize, &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, pathname); + archive_entry_set_mode(ae, AE_IFREG | 0644); + archive_entry_set_size(ae, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(pathname); + + /* 131072-byte pathname: the OOB-write size from the bug report. */ + pathname = malloc(131073); + assert(pathname != NULL); + memset(pathname, 'a', 131072); + pathname[131072] = '\0'; + + assert((a = archive_write_new()) != NULL); + assertEqualInt(ARCHIVE_OK, archive_write_set_format_zip(a)); + assertEqualInt(ARCHIVE_OK, + archive_write_open_memory(a, buf, bufsize, &used)); + + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, pathname); + archive_entry_set_mode(ae, AE_IFREG | 0644); + archive_entry_set_size(ae, 0); + assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae)); + archive_entry_free(ae); + + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); + free(pathname); + + free(buf); +} diff --git a/libarchive/test/test_write_format_zip_windows_path.c b/libarchive/test/test_write_format_zip_windows_path.c index c8be48293638..ffef2a907799 100644 --- a/libarchive/test/test_write_format_zip_windows_path.c +++ b/libarchive/test/test_write_format_zip_windows_path.c @@ -60,7 +60,7 @@ test_with_hdrcharset(const char *charset) archive_entry_free(ae); assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); dumpfile("constructed.zip", buff, used); /* @@ -88,6 +88,7 @@ test_with_hdrcharset(const char *charset) assertEqualInt(2, expected_found); failure("should not find unexpected path in anywhere (charset=%s)", charset); assertEqualInt(0, unexpected_found); + free(buff); } DEFINE_TEST(test_write_format_zip_windows_path) diff --git a/libarchive/test/test_write_format_zip_zip64.c b/libarchive/test/test_write_format_zip_zip64.c index 259cdc47d3ae..04d120651e97 100644 --- a/libarchive/test/test_write_format_zip_zip64.c +++ b/libarchive/test/test_write_format_zip_zip64.c @@ -51,7 +51,7 @@ verify_zip_filesize(uint64_t size, int expected) archive_entry_free(ae); /* Don't actually write 4GB! ;-) */ - assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a)); + assertEqualInt(ARCHIVE_OK, archive_write_free(a)); } DEFINE_TEST(test_write_format_zip_zip64_oversize) diff --git a/libarchive/test/test_write_read_format_zip.c b/libarchive/test/test_write_read_format_zip.c index 828b092c7b3f..1be282f67354 100644 --- a/libarchive/test/test_write_read_format_zip.c +++ b/libarchive/test/test_write_read_format_zip.c @@ -259,7 +259,7 @@ write_contents(struct archive *a) /* Close out the archive. */ - assertEqualInt(ARCHIVE_OK, archive_write_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); assertEqualInt(ARCHIVE_OK, archive_write_free(a)); } @@ -568,7 +568,7 @@ verify_contents(struct archive *a, int seeking, int improved_streaming) /* Verify the end of the archive. */ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); - assertEqualInt(ARCHIVE_OK, archive_read_close(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); assertEqualInt(ARCHIVE_OK, archive_read_free(a)); } diff --git a/libarchive/xxhash.c b/libarchive/xxhash.c index beacd2391221..37dc6ffd679a 100644 --- a/libarchive/xxhash.c +++ b/libarchive/xxhash.c @@ -361,6 +361,8 @@ static void* XXH32_init (U32 seed) { void* state = XXH_malloc (sizeof(struct XXH_state32_t)); + if (state == NULL) + return NULL; XXH32_resetState(state, seed); return state; } diff --git a/libarchive_fe/lafe_fnmatch.c b/libarchive_fe/lafe_fnmatch.c new file mode 100644 index 000000000000..be10fa5b8288 --- /dev/null +++ b/libarchive_fe/lafe_fnmatch.c @@ -0,0 +1,317 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Copyright (c) 2011 The FreeBSD Foundation + * + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "lafe_platform.h" + +#ifndef HAVE_FNMATCH +/* + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. + * Compares a filename or pathname to a pattern. + */ + +/* + * Some notes on multibyte character support: + * 1. Patterns with illegal byte sequences match nothing. + * 2. Illegal byte sequences in the "string" argument are handled by treating + * them as single-byte characters with a value of the first byte of the + * sequence cast to wchar_t. + * 3. Multibyte conversion state objects (mbstate_t) are passed around and + * used for most, but not all, conversions. Further work will be required + * to support state-dependent encodings. + */ + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#ifdef HAVE_WCHAR_H +#include <wchar.h> +#endif +#ifdef HAVE_WCTYPE_H +#include <wctype.h> +#endif + +#include "lafe_fnmatch.h" + +#define EOS '\0' + +#define RANGE_MATCH 1 +#define RANGE_NOMATCH 0 +#define RANGE_ERROR (-1) + +static int rangematch(const char *, wchar_t, int, const char **, mbstate_t *); +static int fnmatch1(const char *, const char *, const char *, int, mbstate_t, + mbstate_t); + +int +fnmatch(const char *pattern, const char *string, int flags) +{ + static const mbstate_t initial; + + return (fnmatch1(pattern, string, string, flags, initial, initial)); +} + +static int +fnmatch1(const char *pattern, const char *string, const char *stringstart, + int flags, mbstate_t patmbs, mbstate_t strmbs) +{ + const char *bt_pattern, *bt_string; + mbstate_t bt_patmbs, bt_strmbs; + const char *newp; + char c; + wchar_t pc, sc; + size_t pclen, sclen; + + bt_pattern = bt_string = NULL; + for (;;) { + pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs); + if (pclen == (size_t)-1 || pclen == (size_t)-2) + return (FNM_NOMATCH); + pattern += pclen; + sclen = mbrtowc(&sc, string, MB_LEN_MAX, &strmbs); + if (sclen == (size_t)-1 || sclen == (size_t)-2) { + sc = (unsigned char)*string; + sclen = 1; + memset(&strmbs, 0, sizeof(strmbs)); + } + switch (pc) { + case EOS: + if ((flags & FNM_LEADING_DIR) && sc == '/') + return (0); + if (sc == EOS) + return (0); + goto backtrack; + case '?': + if (sc == EOS) + return (FNM_NOMATCH); + if (sc == '/' && (flags & FNM_PATHNAME)) + goto backtrack; + if (sc == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + goto backtrack; + string += sclen; + break; + case '*': + c = *pattern; + /* Collapse multiple stars. */ + while (c == '*') + c = *++pattern; + + if (sc == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + goto backtrack; + + /* Optimize for pattern with * at end or before /. */ + if (c == EOS) + if (flags & FNM_PATHNAME) + return ((flags & FNM_LEADING_DIR) || + strchr(string, '/') == NULL ? + 0 : FNM_NOMATCH); + else + return (0); + else if (c == '/' && flags & FNM_PATHNAME) { + if ((string = strchr(string, '/')) == NULL) + return (FNM_NOMATCH); + break; + } + + /* + * First try the shortest match for the '*' that + * could work. We can forget any earlier '*' since + * there is no way having it match more characters + * can help us, given that we are already here. + */ + bt_pattern = pattern, bt_patmbs = patmbs; + bt_string = string, bt_strmbs = strmbs; + break; + case '[': + if (sc == EOS) + return (FNM_NOMATCH); + if (sc == '/' && (flags & FNM_PATHNAME)) + goto backtrack; + if (sc == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + goto backtrack; + + switch (rangematch(pattern, sc, flags, &newp, + &patmbs)) { + case RANGE_ERROR: + goto norm; + case RANGE_MATCH: + pattern = newp; + break; + case RANGE_NOMATCH: + goto backtrack; + } + string += sclen; + break; + case '\\': + if (!(flags & FNM_NOESCAPE)) { + pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, + &patmbs); + if (pclen == 0 || pclen == (size_t)-1 || + pclen == (size_t)-2) + return (FNM_NOMATCH); + pattern += pclen; + } + /* FALLTHROUGH */ + default: + norm: + string += sclen; + if (pc == sc) + ; + else if ((flags & FNM_CASEFOLD) && + (towlower(pc) == towlower(sc))) + ; + else { + backtrack: + /* + * If we have a mismatch (other than hitting + * the end of the string), go back to the last + * '*' seen and have it match one additional + * character. + */ + if (bt_pattern == NULL) + return (FNM_NOMATCH); + sclen = mbrtowc(&sc, bt_string, MB_LEN_MAX, + &bt_strmbs); + if (sclen == (size_t)-1 || + sclen == (size_t)-2) { + sc = (unsigned char)*bt_string; + sclen = 1; + memset(&bt_strmbs, 0, + sizeof(bt_strmbs)); + } + if (sc == EOS) + return (FNM_NOMATCH); + if (sc == '/' && flags & FNM_PATHNAME) + return (FNM_NOMATCH); + bt_string += sclen; + pattern = bt_pattern, patmbs = bt_patmbs; + string = bt_string, strmbs = bt_strmbs; + } + break; + } + } + /* NOTREACHED */ +} + +static int +rangematch(const char *pattern, wchar_t test, int flags, const char **newp, + mbstate_t *patmbs) +{ + int negate, ok; + wchar_t s1[2], s2[2], t[2]; + size_t pclen; + const char *origpat; + + s1[1] = L'\0'; + s2[1] = L'\0'; + + t[0] = test; + t[1] = L'\0'; + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin (conklin@ngai.kaleida.com) + */ + if ((negate = (*pattern == '!' || *pattern == '^'))) + ++pattern; + + if (flags & FNM_CASEFOLD) + t[0] = towlower(t[0]); + + /* + * A right bracket shall lose its special meaning and represent + * itself in a bracket expression if it occurs first in the list. + * -- POSIX.2 2.8.3.2 + */ + ok = 0; + origpat = pattern; + for (;;) { + if (*pattern == ']' && pattern > origpat) { + pattern++; + break; + } else if (*pattern == '\0') { + return (RANGE_ERROR); + } else if (*pattern == '/' && (flags & FNM_PATHNAME)) { + return (RANGE_NOMATCH); + } else if (*pattern == '\\' && !(flags & FNM_NOESCAPE)) + pattern++; + pclen = mbrtowc(s1, pattern, MB_LEN_MAX, patmbs); + if (pclen == (size_t)-1 || pclen == (size_t)-2) + return (RANGE_NOMATCH); + pattern += pclen; + + if (flags & FNM_CASEFOLD) + s1[0] = towlower(s1[0]); + + if (*pattern == '-' && *(pattern + 1) != EOS && + *(pattern + 1) != ']') { + if (*++pattern == '\\' && !(flags & FNM_NOESCAPE)) + if (*pattern != EOS) + pattern++; + pclen = mbrtowc(s2, pattern, MB_LEN_MAX, patmbs); + if (pclen == (size_t)-1 || pclen == (size_t)-2) + return (RANGE_NOMATCH); + pattern += pclen; + if (s2[0] == EOS) + return (RANGE_ERROR); + + if (flags & FNM_CASEFOLD) + s2[0] = towlower(s2[0]); + + if (wcscoll(s1, t) && wcscoll(t, s2) <= 0) + ok = 1; + } else if (s1[0] == t[0]) + ok = 1; + } + + *newp = pattern; + return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH); +} +#endif diff --git a/libarchive_fe/lafe_fnmatch.h b/libarchive_fe/lafe_fnmatch.h new file mode 100644 index 000000000000..e599056a7f1a --- /dev/null +++ b/libarchive_fe/lafe_fnmatch.h @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef LAFE_FNMATCH_H_INCLUDED +#define LAFE_FNMATCH_H_INCLUDED + +#include "lafe_platform.h" + +#ifndef HAVE_FNMATCH + +#define FNM_NOMATCH 1 /* Match failed. */ + +#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ +#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ +#define FNM_PERIOD 0x04 /* Period must be matched by period. */ + +#define FNM_NOSYS (-1) /* Reserved. */ + +#define FNM_LEADING_DIR 0x08 /* Ignore /<tail> after Imatch. */ +#define FNM_CASEFOLD 0x10 /* Case insensitive search. */ +#define FNM_IGNORECASE FNM_CASEFOLD +#define FNM_FILE_NAME FNM_PATHNAME + +int fnmatch(const char *pattern, const char *string, int flags); +#endif /* !HAVE_FNMATCH */ + +#endif /* !LAFE_FNMATCH_H_INCLUDED */ diff --git a/tar/bsdtar.h b/tar/bsdtar.h index 782d36d6f756..692b800bf811 100644 --- a/tar/bsdtar.h +++ b/tar/bsdtar.h @@ -67,7 +67,7 @@ struct bsdtar { /* Miscellaneous state information */ int argc; char **argv; - const char *argument; + char *argument; size_t gs_width; /* For 'list_item' in read.c */ size_t u_width; /* for 'list_item' in read.c */ uid_t user_uid; /* UID running this program */ diff --git a/tar/read.c b/tar/read.c index 4acbf6b2a9dc..57ae5200cf0d 100644 --- a/tar/read.c +++ b/tar/read.c @@ -234,9 +234,14 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer) for (;;) { /* Support --fast-read option */ const char *p; - if ((bsdtar->flags & OPTFLAG_FAST_READ) && - archive_match_path_unmatched_inclusions(bsdtar->matching) == 0) - break; + + if (bsdtar->flags & OPTFLAG_FAST_READ) { + r = archive_match_path_unmatched_inclusions(bsdtar->matching); + if (r < 0) + lafe_errc(1, 0, "%s", archive_error_string(a)); + if (!r) + break; + } r = archive_read_next_header(a, &entry); progress_data.entry = entry; @@ -282,7 +287,11 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer) * rewrite, there would be no way to exclude foo1/bar * while allowing foo2/bar.) */ - if (archive_match_excluded(bsdtar->matching, entry)) + r = archive_match_excluded(bsdtar->matching, entry); + if (r == ARCHIVE_FATAL) + lafe_errc(1, 0, "%s", + archive_error_string(bsdtar->matching)); + if (r) continue; /* Excluded by a pattern test. */ if (mode == 't') { @@ -395,7 +404,7 @@ unmatched_inclusions_warn(struct archive *matching, const char *msg) matching, &p)) == ARCHIVE_OK) lafe_warnc(0, "%s: %s", p, msg); if (r == ARCHIVE_FATAL) - lafe_errc(1, errno, "Out of memory"); + lafe_errc(1, 0, "%s", archive_error_string(matching)); return (archive_match_path_unmatched_inclusions(matching)); } diff --git a/tar/subst.c b/tar/subst.c index 53497ad0d1a3..6acf8cd15f31 100644 --- a/tar/subst.c +++ b/tar/subst.c @@ -75,11 +75,14 @@ add_substitution(struct bsdtar *bsdtar, const char *rule_text) subst->last_rule->next = rule; subst->last_rule = rule; - if (*rule_text == '\0') + const char delim = *rule_text; + if (delim == '\0') lafe_errc(1, 0, "Empty replacement string"); - end_pattern = strchr(rule_text + 1, *rule_text); + end_pattern = strchr(rule_text + 1, delim); if (end_pattern == NULL) - lafe_errc(1, 0, "Invalid replacement string"); + lafe_errc(1, 0, "Invalid replacement string \"%s\": " + "missing closing delimiter '%c' after pattern", + rule_text, delim); pattern = malloc(end_pattern - rule_text); if (pattern == NULL) @@ -95,9 +98,11 @@ add_substitution(struct bsdtar *bsdtar, const char *rule_text) free(pattern); start_subst = end_pattern + 1; - end_pattern = strchr(start_subst, *rule_text); + end_pattern = strchr(start_subst, delim); if (end_pattern == NULL) - lafe_errc(1, 0, "Invalid replacement string"); + lafe_errc(1, 0, "Invalid replacement string \"%s\": " + "missing closing delimiter '%c' after replacement", + rule_text, delim); rule->result = malloc(end_pattern - start_subst + 1); if (rule->result == NULL) diff --git a/tar/test/CMakeLists.txt b/tar/test/CMakeLists.txt index d3c0bd22af9a..5318c24c077e 100644 --- a/tar/test/CMakeLists.txt +++ b/tar/test/CMakeLists.txt @@ -105,25 +105,12 @@ IF(ENABLE_TAR AND ENABLE_TEST) # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. # GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h - ${CMAKE_CURRENT_LIST_FILE} ${bsdtar_test_SOURCES}) + ${CMAKE_CURRENT_LIST_FILE} bsdtar_test ${bsdtar_test_SOURCES}) SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}) - # list.h has a line DEFINE_TEST(testname) for every - # test. We can use that to define the tests for cmake by - # defining a DEFINE_TEST macro and reading list.h in. - MACRO (DEFINE_TEST _testname) - ADD_TEST( - NAME bsdtar_${_testname} - COMMAND bsdtar_test -vv - -p $<TARGET_FILE:bsdtar> - -r ${CMAKE_CURRENT_SOURCE_DIR} - -s - ${_testname}) - SET_TESTS_PROPERTIES(bsdtar_${_testname} PROPERTIES SKIP_RETURN_CODE 2) - ENDMACRO (DEFINE_TEST _testname) + DISCOVER_TESTS(bsdtar ${bsdtar_test_SOURCES}) - INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/tar/test) diff --git a/tar/test/test_option_P_upper.c b/tar/test/test_option_P_upper.c index 953d9f58991c..69810a304318 100644 --- a/tar/test/test_option_P_upper.c +++ b/tar/test/test_option_P_upper.c @@ -79,4 +79,5 @@ DEFINE_TEST(test_extract_tar_absolute_paths) #else assertFileNotExists(temp_absolute_file_name + 1); // Skip the slash. #endif + free(temp_absolute_file_name); } diff --git a/tar/test/test_option_mtime.c b/tar/test/test_option_mtime.c index 75cdb8390bc0..8e337a46da85 100644 --- a/tar/test/test_option_mtime.c +++ b/tar/test/test_option_mtime.c @@ -6,23 +6,6 @@ */ #include "test.h" -#if defined(_WIN32) && !defined(__CYGWIN__) -/* system() on Windows runs its arguments through CMD.EXE, which has - * notoriously unfriendly quoting rules. The current best documented way around - * them is to wrap your *entire commandline* in sacrificial quotes. - * - * See CMD.EXE /? for more information. Excerpted here: - * | Otherwise, old behavior is to see if the first character is - * | a quote character and if so, strip the leading character and - * | remove the last quote character on the command line, preserving - * | any text after the last quote character. - * - * Since this test makes heavy use of systemf() with quoted arguments inside - * the commandline, this macro is unfortunately an easier workaround. - */ -#define systemf(command, ...) systemf("\"" command "\"", __VA_ARGS__) -#endif - DEFINE_TEST(test_option_mtime) { /* Create three files with different mtimes. */ diff --git a/tar/test/test_option_s.c b/tar/test/test_option_s.c index 00753b99be3c..16e871087717 100644 --- a/tar/test/test_option_s.c +++ b/tar/test/test_option_s.c @@ -46,9 +46,9 @@ DEFINE_TEST(test_option_s) systemf("%s -xf test1_3.tar -C test1", testprog); assertFileContents("foo", 3, "test1/in/d1/f##"); // For the 0-length pattern check, remember that "test1/" isn't part of the string affected by the regexp - systemf("%s -cf test1_4.tar -s /f*/\\<~\\>/g in/d1/foo", testprog); + systemf("%s -cf test1_4.tar -s /f*/[~]/g in/d1/foo", testprog); systemf("%s -xf test1_4.tar -C test1", testprog); - assertFileContents("foo", 3, "test1/<>i<>n<>/<>d<>1<>/<f><>o<>o<>"); + assertFileContents("foo", 3, "test1/[]i[]n[]/[]d[]1[]/[f][]o[]o[]"); /* * Test 2: Basic substitution when extracting archive. */ diff --git a/tar/util.c b/tar/util.c index 6b21e8aeff2b..3fb0f9b02055 100644 --- a/tar/util.c +++ b/tar/util.c @@ -746,12 +746,13 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) snprintf(tmp, sizeof(tmp), "%lu,%lu", (unsigned long)archive_entry_rdevmajor(entry), (unsigned long)archive_entry_rdevminor(entry)); + p = tmp; } else { - strcpy(tmp, tar_i64toa(archive_entry_size(entry))); + p = tar_i64toa(archive_entry_size(entry)); } - if (w + strlen(tmp) >= bsdtar->gs_width) - bsdtar->gs_width = w+strlen(tmp)+1; - fprintf(out, "%*s", (int)(bsdtar->gs_width - w), tmp); + if (w + strlen(p) >= bsdtar->gs_width) + bsdtar->gs_width = w + strlen(p) + 1; + fprintf(out, "%*s", (int)(bsdtar->gs_width - w), p); /* Format the time using 'ls -l' conventions. */ tim = archive_entry_mtime(entry); @@ -772,11 +773,13 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry) #else ltime = localtime(&tim); #endif - if (ltime) + if (ltime) { sw = strftime(tmp, sizeof(tmp), fmt, ltime); + p = tmp; + } if (!ltime || !sw) - sprintf(tmp, "-- -- ----"); - fprintf(out, " %s ", tmp); + p = "-- -- ----"; + fprintf(out, " %s ", p); safe_fprintf(out, "%s", archive_entry_pathname(entry)); /* Extra information for links. */ diff --git a/tar/write.c b/tar/write.c index abff3831bcda..302df020ad3a 100644 --- a/tar/write.c +++ b/tar/write.c @@ -699,7 +699,18 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina) int e; while (ARCHIVE_OK == (e = archive_read_next_header(ina, &in_entry))) { - if (archive_match_excluded(bsdtar->matching, in_entry)) + e = archive_match_excluded(bsdtar->matching, in_entry); + if (e < 0) { + if (!bsdtar->verbose) + lafe_errc(1, 0, "%s", + archive_error_string(bsdtar->matching)); + else { + fprintf(stderr, ": %s", + archive_error_string(bsdtar->matching)); + exit(1); + } + } + if (e) continue; if(edit_pathname(bsdtar, in_entry)) continue; diff --git a/test_utils/test_main.c b/test_utils/test_main.c index 1f641bbe8db7..f5de428f2890 100644 --- a/test_utils/test_main.c +++ b/test_utils/test_main.c @@ -187,10 +187,10 @@ const char *testprog; #ifdef RUN_TEST_UNPRIV /* Unprivileged user to run as */ -const char *tuser = "nobody"; +static const char *tuser = "nobody"; /* Original and test credentials */ -uid_t ouid, tuid; -uid_t ogid, tgid; +static uid_t ouid, tuid; +static uid_t ogid, tgid; #endif #if defined(_WIN32) && !defined(__CYGWIN__) @@ -3056,11 +3056,41 @@ systemf(const char *fmt, ...) pid_t pid; #endif va_list ap; + size_t off = 0, avail = sizeof(buff); int r; +#if defined(_WIN32) && !defined(__CYGWIN__) + /* system() on Windows runs its arguments through CMD.EXE, which has + * notoriously unfriendly quoting rules. The current best documented way around + * them is to wrap your *entire commandline* in sacrificial quotes. + * + * See CMD.EXE /? for more information. Excerpted here: + * | Otherwise, old behavior is to see if the first character is + * | a quote character and if so, strip the leading character and + * | remove the last quote character on the command line, preserving + * | any text after the last quote character. + * + * Since these tests often make use of systemf() with quoted arguments inside + * the commandline, wrap every formatted commandline in quotes. + */ + avail -= 2; + off++; + buff[0] = '"'; +#endif + va_start(ap, fmt); - vsnprintf(buff, sizeof(buff), fmt, ap); + r = vsnprintf(buff + off, avail, fmt, ap); va_end(ap); + + if (r < 0 || (size_t)r > avail) { + return (-1); + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + buff[off + r] = '"'; + buff[off + r + 1] = '\0'; +#endif + if (verbosity > VERBOSITY_FULL) logprintf("Cmd: %s\n", buff); #if USE_POSIX_SPAWN @@ -3747,7 +3777,7 @@ usage(const char *program) printf("Usage: %s [options] <test> <test> ...\n", program); printf("Default is to run all tests.\n"); - printf("Otherwise, specify the numbers of the tests you wish to run.\n"); + printf("Otherwise, specify tests by name or number.\n"); printf("Options:\n"); printf(" -d Dump core after any failure, for debugging.\n"); printf(" -k Keep all temp files.\n"); diff --git a/test_utils/test_utils.c b/test_utils/test_utils.c index be717f4ccfe0..a24b0272cb1f 100644 --- a/test_utils/test_utils.c +++ b/test_utils/test_utils.c @@ -149,7 +149,7 @@ unsigned int i4le(const void* p_) { const char *p = p_; - return (i2le(p) | (i2le(p + 2) << 16)); + return (i2le(p) | ((unsigned int)i2le(p + 2) << 16)); } unsigned long long i8le(const void* p_) diff --git a/unzip/CMakeLists.txt b/unzip/CMakeLists.txt index 9fe21eeebe0a..10582b70760b 100644 --- a/unzip/CMakeLists.txt +++ b/unzip/CMakeLists.txt @@ -16,6 +16,8 @@ IF(ENABLE_UNZIP) la_queue.h ../libarchive_fe/lafe_err.c ../libarchive_fe/lafe_err.h + ../libarchive_fe/lafe_fnmatch.c + ../libarchive_fe/lafe_fnmatch.h ../libarchive_fe/lafe_getline.c ../libarchive_fe/lafe_getline.h ../libarchive_fe/lafe_platform.h diff --git a/unzip/bsdunzip.c b/unzip/bsdunzip.c index aa849568ba7e..454d7f7bade2 100644 --- a/unzip/bsdunzip.c +++ b/unzip/bsdunzip.c @@ -9,6 +9,7 @@ #include "bsdunzip_platform.h" #include "la_queue.h" +#include "lafe_fnmatch.h" #include "lafe_getline.h" #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> @@ -51,9 +52,6 @@ #include <sys/time.h> #endif #endif -#ifdef HAVE_GETOPT_OPTRESET -#include <getopt.h> -#endif #include "bsdunzip.h" #include "passphrase.h" @@ -307,12 +305,8 @@ match_pattern(struct pattern_list *list, const char *str) struct pattern *entry; STAILQ_FOREACH(entry, list, link) { -#ifdef HAVE_FNMATCH if (fnmatch(entry->pattern, str, C_opt ? FNM_CASEFOLD : 0) == 0) return (1); -#else -#error "Unsupported platform: fnmatch() is required" -#endif } return (0); } diff --git a/unzip/test/CMakeLists.txt b/unzip/test/CMakeLists.txt index 45138202a9a3..c2bbfa1b27bf 100644 --- a/unzip/test/CMakeLists.txt +++ b/unzip/test/CMakeLists.txt @@ -52,25 +52,12 @@ IF(ENABLE_UNZIP AND ENABLE_TEST) # Generate list.h by grepping DEFINE_TEST() lines out of the C sources. # GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h - ${CMAKE_CURRENT_LIST_FILE} ${bsdunzip_test_SOURCES}) + ${CMAKE_CURRENT_LIST_FILE} bsdunzip_test ${bsdunzip_test_SOURCES}) SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR}) - # list.h has a line DEFINE_TEST(testname) for every - # test. We can use that to define the tests for cmake by - # defining a DEFINE_TEST macro and reading list.h in. - MACRO (DEFINE_TEST _testname) - ADD_TEST( - NAME bsdunzip_${_testname} - COMMAND bsdunzip_test -vv - -p $<TARGET_FILE:bsdunzip> - -r ${CMAKE_CURRENT_SOURCE_DIR} - -s - ${_testname}) - SET_TESTS_PROPERTIES(bsdunzip_${_testname} PROPERTIES SKIP_RETURN_CODE 2) - ENDMACRO (DEFINE_TEST _testname) + DISCOVER_TESTS(bsdunzip ${bsdunzip_test_SOURCES}) - INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/unzip/test) diff --git a/unzip/test/test_P_encryption.c b/unzip/test/test_P_encryption.c index ed08a068811b..ed789ec13291 100644 --- a/unzip/test/test_P_encryption.c +++ b/unzip/test/test_P_encryption.c @@ -9,6 +9,7 @@ /* Test P arg - password protected */ DEFINE_TEST(test_P_encryption) { +#ifdef HAVE_LIBZ const char *reffile = "test_encrypted.zip"; int r; @@ -23,4 +24,7 @@ DEFINE_TEST(test_P_encryption) assertTextFileContents("plaintext\n", "encrypted/file.txt"); } +#else + skipping("zlib not available"); +#endif } |
