From bb5661101a85984ce72835c167874f96279720f7 Mon Sep 17 00:00:00 2001 From: Dana Robinson <43805+derobins@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:09:42 -0700 Subject: [PATCH] Remove the high-level GIF tools (#4976) The high-level GIF tools, h52gif and gif2h5, have unfixed CVE issues (with no proof-of-concept files). They are not critical tools, are not well maintained, and are an odd fit for building with the library. Because of this, they have been removed. We may move them to a separate repository in the future. --- configure.ac | 25 -- hl/tools/CMakeLists.txt | 8 - hl/tools/Makefile.am | 8 +- hl/tools/gif2h5/CMakeLists.txt | 107 ------ hl/tools/gif2h5/CMakeTests.cmake | 76 ---- hl/tools/gif2h5/Makefile.am | 50 --- hl/tools/gif2h5/decompress.c | 331 ------------------ hl/tools/gif2h5/gif.h | 183 ---------- hl/tools/gif2h5/gif2hdf.c | 152 -------- hl/tools/gif2h5/gif2mem.c | 330 ------------------ hl/tools/gif2h5/gifread.c | 376 -------------------- hl/tools/gif2h5/h52gifgentst.c | 99 ------ hl/tools/gif2h5/h52giftest.sh.in | 95 ----- hl/tools/gif2h5/hdf2gif.c | 334 ------------------ hl/tools/gif2h5/hdfgifwr.c | 463 ------------------------- hl/tools/gif2h5/testfiles/README | 6 - hl/tools/gif2h5/testfiles/ex_image2.h5 | Bin 224533 -> 0 bytes hl/tools/gif2h5/testfiles/h52giftst.h5 | Bin 82816 -> 0 bytes hl/tools/gif2h5/testfiles/image1.gif | Bin 9736 -> 0 bytes hl/tools/gif2h5/writehdf.c | 115 ------ release_docs/INSTALL_Autotools.txt | 2 - release_docs/RELEASE.txt | 13 +- src/H5build_settings.autotools.c.in | 1 - src/libhdf5.settings.autotools.in | 1 - 24 files changed, 13 insertions(+), 2762 deletions(-) delete mode 100644 hl/tools/gif2h5/CMakeLists.txt delete mode 100644 hl/tools/gif2h5/CMakeTests.cmake delete mode 100644 hl/tools/gif2h5/Makefile.am delete mode 100644 hl/tools/gif2h5/decompress.c delete mode 100644 hl/tools/gif2h5/gif.h delete mode 100644 hl/tools/gif2h5/gif2hdf.c delete mode 100644 hl/tools/gif2h5/gif2mem.c delete mode 100644 hl/tools/gif2h5/gifread.c delete mode 100644 hl/tools/gif2h5/h52gifgentst.c delete mode 100644 hl/tools/gif2h5/h52giftest.sh.in delete mode 100644 hl/tools/gif2h5/hdf2gif.c delete mode 100644 hl/tools/gif2h5/hdfgifwr.c delete mode 100644 hl/tools/gif2h5/testfiles/README delete mode 100644 hl/tools/gif2h5/testfiles/ex_image2.h5 delete mode 100644 hl/tools/gif2h5/testfiles/h52giftst.h5 delete mode 100644 hl/tools/gif2h5/testfiles/image1.gif delete mode 100644 hl/tools/gif2h5/writehdf.c diff --git a/configure.ac b/configure.ac index c5bfe4276af..6f1ed6aa50e 100644 --- a/configure.ac +++ b/configure.ac @@ -1154,7 +1154,6 @@ AC_LANG_POP(C++) ## library is disabled. AC_SUBST([HDF5_HL]) AC_SUBST([HDF5_HL_TOOLS]) -AC_SUBST([HDF5_HL_GIF_TOOLS]) ## The high-level library and high-level tools are enabled unless the build mode ## is clean. @@ -1477,27 +1476,6 @@ AC_ARG_ENABLE([tools], AC_MSG_RESULT([$HDF5_TOOLS]) -## ---------------------------------------------------------------------- -## Check if they would like to disable building the high-level GIF -## tools (they have unfixed CVE issues) -## - -AC_MSG_CHECKING([if the high-level GIF tools are enabled]) -AC_ARG_ENABLE([hlgiftools], - [AS_HELP_STRING([--enable-hlgiftools], - [Enable the high-level GIF tools. NOTE: These have unfixed CVE issues! - [default=no] - ])], - [HDF5_HL_GIF_TOOLS=$enableval]) - -if test "X-$HDF5_TOOLS" = "X-yes" -a "X-$HDF5_HL" = "X-yes" -a "X-$HDF5_HL_GIF_TOOLS" = "X-yes"; then - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) - HDF5_HL_GIF_TOOLS="no" -fi - - ## ---------------------------------------------------------------------- ## Check if they would like to enable building doxygen files ## @@ -4411,7 +4389,6 @@ AM_CONDITIONAL([BUILD_HDF5_HL_CONDITIONAL], [test "X$HDF5_HL" = "Xyes"]) AM_CONDITIONAL([BUILD_TESTS_CONDITIONAL], [test "X$HDF5_TESTS" = "Xyes"]) AM_CONDITIONAL([BUILD_TESTS_PARALLEL_CONDITIONAL], [test -n "$TESTPARALLEL"]) AM_CONDITIONAL([BUILD_TOOLS_CONDITIONAL], [test "X$HDF5_TOOLS" = "Xyes"]) -AM_CONDITIONAL([BUILD_TOOLS_HL_GIF_CONDITIONAL], [test "X$HDF5_HL_GIF_TOOLS" = "Xyes"]) AM_CONDITIONAL([BUILD_DOXYGEN_CONDITIONAL], [test "X$HDF5_DOXYGEN" = "Xyes"]) ## ---------------------------------------------------------------------- @@ -4619,8 +4596,6 @@ AC_CONFIG_FILES([Makefile hl/test/Makefile hl/test/H5srcdir_str.h hl/tools/Makefile - hl/tools/gif2h5/Makefile - hl/tools/gif2h5/h52giftest.sh hl/tools/h5watch/Makefile hl/tools/h5watch/testh5watch.sh hl/examples/Makefile diff --git a/hl/tools/CMakeLists.txt b/hl/tools/CMakeLists.txt index a369d9efa18..cbff5a92157 100644 --- a/hl/tools/CMakeLists.txt +++ b/hl/tools/CMakeLists.txt @@ -1,12 +1,4 @@ cmake_minimum_required (VERSION 3.18) project (HDF5_HL_TOOLS C) -#----------------------------------------------------------------------------- -#-- Option to build the High level GIF Tools -#----------------------------------------------------------------------------- -option (HDF5_BUILD_HL_GIF_TOOLS "Build HDF5 HL GIF Tools" OFF) -if (HDF5_BUILD_HL_GIF_TOOLS) - add_subdirectory (gif2h5) -endif () - add_subdirectory (h5watch) diff --git a/hl/tools/Makefile.am b/hl/tools/Makefile.am index 9f93f676dce..620eb5dbfcc 100644 --- a/hl/tools/Makefile.am +++ b/hl/tools/Makefile.am @@ -18,13 +18,7 @@ include $(top_srcdir)/config/commence.am -if BUILD_TOOLS_HL_GIF_CONDITIONAL - TOOLS_GIF_DIR = gif2h5 -else - TOOLS_GIF_DIR = -endif - # All subdirectories -SUBDIRS=h5watch $(TOOLS_GIF_DIR) +SUBDIRS=h5watch include $(top_srcdir)/config/conclude.am diff --git a/hl/tools/gif2h5/CMakeLists.txt b/hl/tools/gif2h5/CMakeLists.txt deleted file mode 100644 index abef080910c..00000000000 --- a/hl/tools/gif2h5/CMakeLists.txt +++ /dev/null @@ -1,107 +0,0 @@ -cmake_minimum_required (VERSION 3.18) -project (HDF5_HL_TOOLS_GIF2H5 C) - -#----------------------------------------------------------------------------- -# Define Sources -#----------------------------------------------------------------------------- -set (GIF2H5_SOURCES - ${HDF5_HL_TOOLS_GIF2H5_SOURCE_DIR}/gif.h - ${HDF5_HL_TOOLS_GIF2H5_SOURCE_DIR}/decompress.c - ${HDF5_HL_TOOLS_GIF2H5_SOURCE_DIR}/gif2hdf.c - ${HDF5_HL_TOOLS_GIF2H5_SOURCE_DIR}/gif2mem.c - ${HDF5_HL_TOOLS_GIF2H5_SOURCE_DIR}/gifread.c - ${HDF5_HL_TOOLS_GIF2H5_SOURCE_DIR}/writehdf.c -) - -#-- Add gif2hdf5 program -add_executable (gif2h5 ${GIF2H5_SOURCES}) -target_compile_options(gif2h5 PRIVATE "${HDF5_CMAKE_C_FLAGS}") -target_include_directories (gif2h5 PRIVATE "${HDF5_SRC_INCLUDE_DIRS};${HDF5_SRC_BINARY_DIR};$<$:${MPI_C_INCLUDE_DIRS}>") -if (HDF5_BUILD_STATIC_TOOLS) - TARGET_C_PROPERTIES (gif2h5 STATIC) - target_link_libraries (gif2h5 PRIVATE ${HDF5_HL_LIB_TARGET} ${HDF5_LIB_TARGET} ${HDF5_TOOLS_LIB_TARGET}) -else () - TARGET_C_PROPERTIES (gif2h5 SHARED) - target_link_libraries (gif2h5 PRIVATE ${HDF5_HL_LIBSH_TARGET} ${HDF5_LIBSH_TARGET} ${HDF5_TOOLS_LIBSH_TARGET}) -endif () -set_target_properties (gif2h5 PROPERTIES FOLDER tools/hl) -set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};gif2h5") -set (H5_DEP_EXECUTABLES - gif2h5 -) - -#----------------------------------------------------------------------------- -# Add Target to clang-format -#----------------------------------------------------------------------------- -if (HDF5_ENABLE_FORMATTERS) - clang_format (HDF5_HL_TOOLS_GIF2H5_FORMAT gif2h5) -endif () - -#-- Add h52gif program -set (hdf2gif_SOURCES - ${HDF5_HL_TOOLS_GIF2H5_SOURCE_DIR}/hdf2gif.c - ${HDF5_HL_TOOLS_GIF2H5_SOURCE_DIR}/hdfgifwr.c -) -add_executable (h52gif ${hdf2gif_SOURCES}) -target_compile_options(h52gif PRIVATE "${HDF5_CMAKE_C_FLAGS}") -target_include_directories (h52gif PRIVATE "${HDF5_SRC_INCLUDE_DIRS};${HDF5_SRC_BINARY_DIR};$<$:${MPI_C_INCLUDE_DIRS}>") -if (HDF5_BUILD_STATIC_TOOLS) - TARGET_C_PROPERTIES (h52gif STATIC) - target_link_libraries (h52gif PRIVATE ${HDF5_HL_LIB_TARGET} ${HDF5_LIB_TARGET} ${HDF5_TOOLS_LIB_TARGET}) -else () - TARGET_C_PROPERTIES (h52gif SHARED) - target_link_libraries (h52gif PRIVATE ${HDF5_HL_LIBSH_TARGET} PRIVATE ${HDF5_LIBSH_TARGET} ${HDF5_TOOLS_LIBSH_TARGET}) -endif () -set_target_properties (h52gif PROPERTIES FOLDER tools/hl) -set_global_variable (HDF5_UTILS_TO_EXPORT "${HDF5_UTILS_TO_EXPORT};h52gif") -set (H5_DEP_EXECUTABLES ${H5_DEP_EXECUTABLES} - h52gif -) - -#----------------------------------------------------------------------------- -# Add Target to clang-format -#----------------------------------------------------------------------------- -if (HDF5_ENABLE_FORMATTERS) - clang_format (HDF5_HL_TOOLS_H52GIF_FORMAT h52gif) -endif () - -if (BUILD_TESTING AND HDF5_TEST_SERIAL) - # -------------------------------------------------------------------- - # This executable can generate the actual test files - Currently not - # used in the CMake Build system as we rely on the test files that are - # shipped with HDF5 source archives - # -------------------------------------------------------------------- - if (HDF5_BUILD_GENERATORS AND BUILD_STATIC_LIBS) - add_executable (hl_h52gifgentest ${HDF5_HL_TOOLS_GIF2H5_SOURCE_DIR}/h52gifgentst.c) - target_include_directories (hl_h52gifgentest PRIVATE "${HDF5_SRC_INCLUDE_DIRS};${HDF5_SRC_BINARY_DIR};$<$:${MPI_C_INCLUDE_DIRS}>") - TARGET_C_PROPERTIES (hl_h52gifgentest STATIC) - target_link_libraries (hl_h52gifgentest PRIVATE ${HDF5_HL_LIB_TARGET} ${HDF5_LIB_TARGET}) - set_target_properties (hl_h52gifgentest PROPERTIES FOLDER generator/tools/hl) - - #----------------------------------------------------------------------------- - # Add Target to clang-format - #----------------------------------------------------------------------------- - if (HDF5_ENABLE_FORMATTERS) - clang_format (HDF5_HL_TOOLS_hl_h52gifgentest_FORMAT hl_h52gifgentest) - endif () - -# add_test (NAME hl_h52gifgentest COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - endif () - - if (HDF5_TEST_TOOLS) - include (CMakeTests.cmake) - endif () -endif () - -#----------------------------------------------------------------------------- -# Add file(s) to CMake Install -#----------------------------------------------------------------------------- -if (HDF5_EXPORTED_TARGETS) - install ( - TARGETS - ${H5_DEP_EXECUTABLES} - EXPORT - ${HDF5_EXPORTED_TARGETS} - RUNTIME DESTINATION ${HDF5_INSTALL_BIN_DIR} COMPONENT hltoolsapplications - ) -endif () diff --git a/hl/tools/gif2h5/CMakeTests.cmake b/hl/tools/gif2h5/CMakeTests.cmake deleted file mode 100644 index be431c1507b..00000000000 --- a/hl/tools/gif2h5/CMakeTests.cmake +++ /dev/null @@ -1,76 +0,0 @@ -# -# Copyright by The HDF Group. -# All rights reserved. -# -# This file is part of HDF5. The full HDF5 copyright notice, including -# terms governing use, modification, and redistribution, is contained in -# the COPYING file, which can be found at the root of the source code -# distribution tree, or in https://www.hdfgroup.org/licenses. -# If you do not have access to either file, you may request a copy from -# help@hdfgroup.org. -# - -############################################################################## -############################################################################## -### T E S T I N G ### -############################################################################## -############################################################################## - -# Make testfiles dir under build dir -file (MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/testfiles") - -# -# copy test files from source to build dir -# -HDFTEST_COPY_FILE("${PROJECT_SOURCE_DIR}/testfiles/image1.gif" "${PROJECT_BINARY_DIR}/testfiles/image1.gif" "gif2h5_files") -HDFTEST_COPY_FILE("${PROJECT_SOURCE_DIR}/testfiles/h52giftst.h5" "${PROJECT_BINARY_DIR}/testfiles/h52giftst.h5" "gif2h5_files") -HDFTEST_COPY_FILE("${PROJECT_SOURCE_DIR}/testfiles/ex_image2.h5" "${PROJECT_BINARY_DIR}/testfiles/ex_image2.h5" "gif2h5_files") -add_custom_target(gif2h5_files ALL COMMENT "Copying files needed by gif2h5 tests" DEPENDS ${gif2h5_files_list}) - -# Remove any output file left over from previous test run -set (HL_TOOLS_CLEANFILES - image1.gif - image1.h5 - image.gif - image24.gif -) -add_test ( - NAME HL_TOOLS-clear-objects - COMMAND ${CMAKE_COMMAND} - -E remove ${HL_TOOLS_CLEANFILES} -) -set_tests_properties (HL_TOOLS-clear-objects PROPERTIES FIXTURES_SETUP clear_tools_hl) -add_test ( - NAME HL_TOOLS-clean-objects - COMMAND ${CMAKE_COMMAND} - -E remove ${HL_TOOLS_CLEANFILES} -) -set_tests_properties (HL_TOOLS-clean-objects PROPERTIES FIXTURES_CLEANUP clear_tools_hl) - -add_test (NAME HL_TOOLS_gif2h5 COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ testfiles/image1.gif image1.h5) -set_tests_properties (HL_TOOLS_gif2h5 PROPERTIES - FIXTURES_REQUIRED clear_tools_hl -) - -add_test (NAME HL_TOOLS_h52gif COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ testfiles/h52giftst.h5 image1.gif -i image) -set_tests_properties (HL_TOOLS_h52gif PROPERTIES - FIXTURES_REQUIRED clear_tools_hl -) - -add_test (NAME HL_TOOLS_h52gif_none COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ testfiles/h52giftst.h5 image.gif -i nosuch_image) -set_tests_properties (HL_TOOLS_h52gif_none PROPERTIES - WILL_FAIL "true" - FIXTURES_REQUIRED clear_tools_hl -) - -#add_test (NAME HL_TOOLS_h52gifpal COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ testfiles/h52giftst.h5 image.gif -i palette) -#set_tests_properties (HL_TOOLS_h52gifpal PROPERTIES -# WILL_FAIL "true" -# FIXTURES_REQUIRED clear_tools_hl -#) - -add_test (NAME HL_TOOLS_h52gif24bits COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ testfiles/ex_image2.h5 image24.gif -i image24bitpixel) -set_tests_properties (HL_TOOLS_h52gif24bits PROPERTIES - WILL_FAIL "true" - FIXTURES_REQUIRED clear_tools_hl -) diff --git a/hl/tools/gif2h5/Makefile.am b/hl/tools/gif2h5/Makefile.am deleted file mode 100644 index d8786f70060..00000000000 --- a/hl/tools/gif2h5/Makefile.am +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright by The HDF Group. -# All rights reserved. -# -# This file is part of HDF5. The full HDF5 copyright notice, including -# terms governing use, modification, and redistribution, is contained in -# the COPYING file, which can be found at the root of the source code -# distribution tree, or in https://www.hdfgroup.org/licenses. -# If you do not have access to either file, you may request a copy from -# help@hdfgroup.org. -## -## Makefile.am -## Run automake to generate a Makefile.in from this file. -# -# HDF5 Library Makefile(.in) -# - -include $(top_srcdir)/config/commence.am - -# Include src and tools/lib directories -AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_srcdir)/tools/lib -I$(top_srcdir)/hl/src - -# These are our main targets, the tools - -bin_PROGRAMS=gif2h5 h52gif - -# Add h52gif and gif2h5 specific linker flags here -h52gif_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) -gif2h5_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS) - -gif2h5_SOURCES=gif2hdf.c gif2mem.c decompress.c gifread.c writehdf.c - -h52gif_SOURCES=hdf2gif.c hdfgifwr.c - - -# Programs all depend on the hdf5 library, the tools library, and the HL -# library. -LDADD=$(LIBH5_HL) $(LIBH5TOOLS) $(LIBHDF5) - -if BUILD_TESTS_CONDITIONAL - TEST_SCRIPT=h52giftest.sh - check_SCRIPTS=$(TEST_SCRIPT) - noinst_PROGRAMS=h52gifgentst - h52gifgentst_SOURCES=h52gifgentst.c -endif - -CHECK_CLEANFILES+=*.h5 -CHECK_CLEANFILES+=*.gif - -include $(top_srcdir)/config/conclude.am diff --git a/hl/tools/gif2h5/decompress.c b/hl/tools/gif2h5/decompress.c deleted file mode 100644 index 62a22922ff4..00000000000 --- a/hl/tools/gif2h5/decompress.c +++ /dev/null @@ -1,331 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * - * All rights reserved. * - * * - * This file is part of HDF5. The full HDF5 copyright notice, including * - * terms governing use, modification, and redistribution, is contained in * - * the COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include -#include - -#include "gif.h" - -GIFWORD iWIDE, iHIGH, eWIDE, eHIGH, expand, numcols, strip, nostrip; -unsigned long cols[256]; -char *cmd; - -FILE *fp; - -static GIFWORD XC = 0, YC = 0, /* Output X and Y coords of current pixel */ - InitCodeSize, /* Starting code size, used during Clear */ - CodeSize, /* Code size, read from GIF header */ - BytesPerScanline, /* Bytes per scanline in output raster */ - IWidth, IHeight; /* image dimensions */ -static int BitOffset = 0, /* Bit Offset of next code */ - Pass = 0, /* Used by output routine if GIFWORDerlaced pic */ - OutCount = 0, /* Decompressor output 'stack count' */ - Code, /* Value returned by ReadCode */ - MaxCode, /* limiting value for current code size */ - ClearCode, /* GIF clear code */ - EOFCode, /* GIF end-of-information code */ - CurCode, OldCode, InCode, /* Decompressor variables */ - FirstFree, /* First free code, generated per GIF spec */ - FreeCode, /* Decompressor, next free slot in hash table */ - FinChar, /* Decompressor variable */ - DataMask, /* AND mask for data size */ - ReadMask; /* Code AND mask for current code size */ - -/*MODIFICATIONS*/ -GIFBYTE tempbyte[10]; -GIFBYTE *tempGIFBYTEptr[10]; -GIFWORD tempint[10]; -GIFWORD ImageCount = 0; -/*END MODIFICATION*/ - -boolean Interlace, HasColormap; - -GIFBYTE *Image; /* The result array */ -GIFBYTE *RawGIF; /* The heap array to hold it, raw */ -GIFBYTE *Raster; /* The raster data stream, unblocked */ - -/* The hash table used by the decompressor */ - -static int *Prefix; -static int *Suffix; - -/* An output array used by the decompressor */ - -int *OutCode; - -/* The color map, read from the GIF header */ - -int numused; - -/* - * Fetch the next code from the raster data stream. The codes can be any - * length from 3 to 12 bits, packed into 8-bit GIFBYTEs, so we have to maintain - * our location in the Raster array as a BIT Offset. We compute the GIFBYTE - * Offset into the raster array by dividing this by 8, pick up three GIFBYTEs, - * compute the bit Offset into our 24-bit chunk, shift to bring the desired - * code to the bottom, then mask it off and return it. - */ -static int -ReadCode(void) -{ - int RawCode, ByteOffset; - - ByteOffset = BitOffset / 8; - RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]); - - if (CodeSize >= 8) - RawCode += (0x10000 * Raster[ByteOffset + 2]); - - RawCode >>= (BitOffset % 8); - BitOffset += (int)CodeSize; - return (RawCode & ReadMask); -} - -static void -AddToPixel(GIFBYTE Index) -{ - if (YC < IHeight) - *(Image + YC * BytesPerScanline + XC) = Index; - - /* Update the X-coordinate, and if it overflows, update the - * Y-coordinate */ - if (++XC == IWidth) { - /* - * If a non-interlaced picture, just increment YC to the next scan - * line. If it's interlaced, deal with the interlace as described - * in the GIF spec. Put the decoded scan line out to the screen if we - * haven't gone past the bottom of it. - */ - XC = 0; - - if (!Interlace) { - YC++; - } - else { - switch (Pass) { - case 0: - YC += 8; - - if (YC >= IHeight) { - Pass++; - YC = 4; - } - - break; - case 1: - YC += 8; - - if (YC >= IHeight) { - Pass++; - YC = 2; - } - - break; - case 2: - YC += 4; - - if (YC >= IHeight) { - Pass++; - YC = 1; - } - - break; - case 3: - YC += 2; - break; - default: - break; - } - } - } -} - -/* Main routine. Convert a GIF image to an HDF image */ - -GIFBYTE * -Decompress(GIFIMAGEDESC *GifImageDesc, GIFHEAD *GifHead) -{ - int i; - - if (!(Prefix = calloc(4096, sizeof(int)))) { - printf("Out of memory"); - exit(EXIT_FAILURE); - } - if (!(Suffix = calloc(4096, sizeof(int)))) { - printf("Out of memory"); - exit(EXIT_FAILURE); - } - if (!(OutCode = calloc(1024, sizeof(int)))) { - printf("Out of memory"); - exit(EXIT_FAILURE); - } - - XC = 0; - YC = 0; - Pass = 0; - OutCount = 0; - BitOffset = 0; - - DataMask = (1 << ((GifHead->PackedField & 0x07) + 1)) - 1; - Raster = GifImageDesc->GIFImage; - - /* Check for image separator */ - - /* Now read in values from the image descriptor */ - IWidth = GifImageDesc->ImageWidth; - IHeight = GifImageDesc->ImageHeight; - Interlace = (uint8_t)(GifImageDesc->PackedField & 0x40); - - /* - * Note that I ignore the possible existence of a local color map. I'm - * told there aren't many files around that use them, and the spec says - * it's defined for future use. This could lead to an error reading some - * files. - */ - - /* - * Start reading the raster data. First we get the initial code size and - * compute decompressor constant values, based on this code size. - */ - - CodeSize = GifImageDesc->CodeSize; - ClearCode = (1 << CodeSize); - EOFCode = ClearCode + 1; - FreeCode = FirstFree = ClearCode + 2; - - /* - * The GIF spec has it that the code size is the code size used to compute - * the above values is the code size given in the file, but the code size - * used in compression/decompression is the code size given in the file - * plus one. (thus the ++). - */ - - CodeSize++; - InitCodeSize = CodeSize; - MaxCode = (1 << CodeSize); - ReadMask = MaxCode - 1; - - /* - * Read the raster data. Here we just transpose it from the GIF array to - * the Raster array, turning it from a series of blocks into one long - * data stream, which makes life much easier for ReadCode(). - */ - - /* Allocate the Image */ - - if (!(Image = (GIFBYTE *)malloc((size_t)IWidth * (size_t)IHeight))) { - printf("Out of memory"); - exit(EXIT_FAILURE); - } - - BytesPerScanline = IWidth; - - /* - * Decompress the file, continuing until you see the GIF EOF code. One - * obvious enhancement is to add checking for corrupt files here. - */ - - Code = ReadCode(); - - while (Code != EOFCode) { - /* - * Clear code sets everything back to its initial value, then reads - * the immediately subsequent code as uncompressed data. - */ - if (Code == ClearCode) { - CodeSize = InitCodeSize; - MaxCode = (1 << CodeSize); - ReadMask = MaxCode - 1; - FreeCode = FirstFree; - CurCode = OldCode = Code = ReadCode(); - FinChar = CurCode & DataMask; - AddToPixel((GIFBYTE)FinChar); - } - else { - /* - * If not a clear code, then must be data: save same as CurCode - * and InCode - */ - CurCode = InCode = Code; - - /* - * If greater or equal to FreeCode, not in the hash table yet; - * repeat the last character decoded - */ - if (CurCode >= FreeCode) { - CurCode = OldCode; - OutCode[OutCount++] = FinChar; - } - - /* - * Unless this code is raw data, pursue the chain pointed to by - * CurCode through the hash table to its end; each code in the - * chain puts its associated output code on the output queue. - */ - while (CurCode > DataMask) { - if (OutCount >= 1024) { - /*return error message*/ - } - - OutCode[OutCount++] = Suffix[CurCode]; - CurCode = Prefix[CurCode]; - } - - /* The last code in the chain is treated as raw data. */ - FinChar = CurCode & DataMask; - OutCode[OutCount++] = FinChar; - - /* - * Now we put the data out to the Output routine. It's been - * stacked LIFO, so deal with it that way... - */ - for (i = OutCount - 1; i >= 0; i--) - AddToPixel((GIFBYTE)OutCode[i]); - - OutCount = 0; - - /* - * Build the hash table on-the-fly. No table is stored in the - * file. - */ - if (FreeCode >= 4096) { - printf("Error: FreeCode out of bounds\n"); - exit(EXIT_FAILURE); - } - Prefix[FreeCode] = OldCode; - Suffix[FreeCode] = FinChar; - OldCode = InCode; - - /* - * Point to the next slot in the table. If we exceed the current - * MaxCode value, increment the code size unless it's already 12. - * If it is, do nothing: the next code decompressed better be - * CLEAR - */ - FreeCode++; - - if (FreeCode >= MaxCode) - if (CodeSize < 12) { - CodeSize++; - MaxCode *= 2; - ReadMask = (1 << CodeSize) - 1; - } - } - - Code = ReadCode(); - } - - free(Prefix); - free(Suffix); - free(OutCode); - - return Image; -} diff --git a/hl/tools/gif2h5/gif.h b/hl/tools/gif2h5/gif.h deleted file mode 100644 index 62f09a5b2ee..00000000000 --- a/hl/tools/gif2h5/gif.h +++ /dev/null @@ -1,183 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * - * All rights reserved. * - * * - * This file is part of HDF5. The full HDF5 copyright notice, including * - * terms governing use, modification, and redistribution, is contained in * - * the COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* - * Title: GIF.H - * Purpose: GIF Header file - */ -#ifndef GIF_H_ -#define GIF_H_ 1 - -#include -#include -#include - -#include "hdf5.h" - -#define MAX_PAL 768 - -/* typedef H5T_NATIVE_UINT8 GIFBYTE; */ -typedef unsigned char GIFBYTE; - -/* typedef H5T_NATIVE_UINT16 GIFWORD; */ -typedef unsigned long GIFWORD; - -typedef char GIFCHAR; - -#ifndef boolean -typedef unsigned char boolean; -#endif - -#ifndef false -#define false 0 -#endif -#ifndef true -#define true 1 -#endif - -/* Set the EndianOrder. -** The GIF Reader file should do this. -** Set EndianOrder = 0 if machine is little endian -** EndianOrder = 1 if machine is big endian. -*/ -extern int EndianOrder; - -/* -** The GIF header format. -** -** This structure actually contains the header, logical screen -** descriptor, and the global color table for the GIF image. -*/ -typedef struct _GifHeader { /* Offset Description */ - GIFBYTE PackedField; /* 0Ah Color Information */ - GIFWORD TableSize; - GIFBYTE ImageCount; /* Keep a count of the number of images */ - GIFBYTE CommentCount; - GIFBYTE ApplicationCount; - GIFBYTE PlainTextCount; - GIFBYTE HDFPalette[256][3]; - GIFBYTE HeaderDump[6]; /* GIFBYTE array to dump header contents */ - GIFBYTE LSDDump[7]; /* Logical Screen Descriptor dump */ -} GIFHEAD; - -/* -** The GIF Image Descriptor. -*/ -typedef struct _GifImageDescriptor { - GIFWORD ImageWidth; /* Width of the image in pixels */ - GIFWORD ImageHeight; /* Height of the image in pixels */ - GIFBYTE PackedField; /* Image and Color Table Data Information */ - GIFWORD TableSize; - GIFWORD CodeSize; /* Minimum LZW CodeSize for image data */ - GIFBYTE HDFPalette[256][3]; - GIFBYTE GIDDump[9]; /* GifImageDescriptor dump */ - - GIFBYTE *Image; /* Decompressed Raster Image */ - GIFBYTE *GIFImage; -} GIFIMAGEDESC; - -/* -** GIF 89a Graphic Control Extension Block -*/ -typedef struct _GifGraphicControlExtension { - GIFBYTE GCEDump[5]; /* Graphic Control Extension Dump */ -} GIFGRAPHICCONTROL; - -/* -** GIF 89a Plain Text Extension Block -*/ -typedef struct _GifPlainTextExtension { - GIFBYTE PTEDump[15]; /* Plain Text Extension Dump */ - GIFBYTE *PlainTextData; /* Plain Text data sub-blocks */ - GIFWORD DataSize; -} GIFPLAINTEXT; - -/* -** GIF 89a Application Extension Block -*/ -typedef struct _GifApplicationExtension { - GIFBYTE AEDump[14]; /* Application Extension Dump */ - GIFBYTE *ApplicationData; /* Application data sub-blocks */ - GIFWORD DataSize; -} GIFAPPLICATION; - -/* -** GIF 89a Comment Extension Block -*/ -typedef struct _GifCommentExtension { - GIFBYTE CEDump[2]; /* Comment Extension Dump */ - GIFBYTE *CommentData; /* Comment data sub-blocks */ - GIFWORD DataSize; - GIFBYTE Terminator; /* Block Terminator (always 0) */ -} GIFCOMMENT; - -/* -** GIF to HDF Memory Struct -** Purpose : The gif to hdf structure is used to pass all the -** gif data to the memory, which gets caught by the hdf driver -** Its the drivers job to put the data in the appropriate places -** in the HDF file. -** I have assumed that the ImageDescriptors and GraphicControls follow -** one another, ie. I have not associated them with each other. The driver -** must assume a 1-1 correspondence. The same discussion with plain text -** extension. -*/ -typedef struct _GifToMem { - GIFHEAD *GifHeader; - GIFIMAGEDESC **GifImageDesc; - GIFGRAPHICCONTROL **GifGraphicControlExtension; - GIFPLAINTEXT **GifPlainTextExtension; - GIFAPPLICATION **GifApplicationExtension; - GIFCOMMENT **GifCommentExtension; -} GIFTOMEM; - -/* -** Function Prototypes -*/ - -/* GIF2MEM.C */ -int Gif2Mem(GIFBYTE *, GIFTOMEM *); - -/* GIFREAD.C */ -int ReadGifHeader(GIFHEAD *, GIFBYTE **); -int ReadGifImageDesc(GIFIMAGEDESC *, GIFBYTE **); -int ReadGifGraphicControl(GIFGRAPHICCONTROL *, GIFBYTE **); -int ReadGifPlainText(GIFPLAINTEXT *, GIFBYTE **); -int ReadGifApplication(GIFAPPLICATION *, GIFBYTE **); -int ReadGifComment(GIFCOMMENT *, GIFBYTE **); - -/* HDFGIFWR.C */ -int hdfWriteGIF(FILE *fp, GIFBYTE *pic, int ptype, int w, int h, const GIFBYTE *rmap, const GIFBYTE *gmap, - const GIFBYTE *bmap, const GIFBYTE *pc2ncmap, int numcols, int colorstyle, int BitsPerPixel); - -/* WRITEHDF.C */ -int WriteHDF(GIFTOMEM, GIFCHAR *); - -/* Function: ReadHDF -** Return: 0 on completion without error, -1 on error -** Input: GIFCHAR *h5_file - HDF file name -** GIFCHAR *dset_name - Name of the HDF Image dataset -** GIFCHAR *pal_name - Name of the HDF palette -** Output: GIFBYTE* data - the HDF Image to be converted -** GIFBYTE palette[256][3] - the corresponding palette -** hsize_t* image_size - the size of each dimension of the image -*/ -int ReadHDF(GIFBYTE **data, GIFBYTE palette[256][3], hsize_t *image_size, GIFCHAR *h5_file, - GIFCHAR *dset_name, GIFCHAR *pal_name); - -GIFBYTE *Decompress(GIFIMAGEDESC *, GIFHEAD *); -GIFBYTE GetByte(const GIFBYTE *); -GIFWORD GetWord(GIFBYTE *); - -void cleanup(GIFBYTE *); - -#endif /* GIF_H_ */ diff --git a/hl/tools/gif2h5/gif2hdf.c b/hl/tools/gif2h5/gif2hdf.c deleted file mode 100644 index 161761c7ee4..00000000000 --- a/hl/tools/gif2h5/gif2hdf.c +++ /dev/null @@ -1,152 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * - * All rights reserved. * - * * - * This file is part of HDF5. The full HDF5 copyright notice, including * - * terms governing use, modification, and redistribution, is contained in * - * the COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include -#include -#include - -#include "gif.h" -#include "h5tools.h" -#include "h5tools_utils.h" - -int -main(int argv, char *argc[]) -{ - GIFTOMEM GifMemoryStruct; - GIFIMAGEDESC gifImageDesc; - - FILE *fpGif; - - /* replacing int32 with long */ - long i, ImageCount; - HDoff_t filesize; - - GIFBYTE *MemGif; - GIFBYTE *StartPos; - - char *GIFFileName; - char *HDFFileName; - - /* - * Initialize all GifMemoryStruct pointers to null to prevent hassles - * later on - */ - GifMemoryStruct.GifHeader = NULL; - GifMemoryStruct.GifImageDesc = NULL; - GifMemoryStruct.GifGraphicControlExtension = NULL; - GifMemoryStruct.GifPlainTextExtension = NULL; - GifMemoryStruct.GifApplicationExtension = NULL; - GifMemoryStruct.GifCommentExtension = NULL; - - /* Initialize h5tools lib */ - h5tools_init(); - - if (argc[1] && (strcmp("-V", argc[1]) == 0)) { - print_version("gif2h5"); - exit(EXIT_SUCCESS); - } - - if (argv < 3) { - printf("Usage: gif2h5 \n"); - fprintf(stdout, " gif2h5 -V \n"); - fprintf(stdout, " Print HDF5 library version and exit\n"); - exit(EXIT_FAILURE); - } - - GIFFileName = argc[1]; - HDFFileName = argc[2]; - - if (!(fpGif = fopen(GIFFileName, "rb"))) { - printf("Unable to open GIF file for reading.\n"); - exit(EXIT_FAILURE); - } - - /* Get the whole file into memory. Mem's much faster than I/O */ - fseek(fpGif, 0L, 2); - filesize = HDftell(fpGif); - fseek(fpGif, 0L, 0); - - if (filesize == 0) - printf("File Size Zero"); - - if (!(MemGif = StartPos = (GIFBYTE *)malloc((size_t)filesize))) { - printf("Out of memory"); - exit(EXIT_FAILURE); - } - - if (fread(MemGif, (size_t)filesize, 1, fpGif) != 1) { - printf("Corrupted Input File"); - exit(EXIT_FAILURE); - } - - fseek(fpGif, 0L, 0); - - /* - * Call Gif2Mem and break the whole file into parts. Gif2Mem also calls - * decompresses the images so we don't have to worry about that - */ - Gif2Mem(MemGif, &GifMemoryStruct); - - if (ferror(fpGif)) { - printf("File Stream Error\n\n"); - exit(EXIT_FAILURE); - } - - fclose(fpGif); - - /* - * Call WriteHDF from here. Go ahead and change WriteHDF to write whatever - * format you want - */ - if (WriteHDF(GifMemoryStruct, HDFFileName)) - printf("HDF Write Error\n\n"); - - /* Free all buffers */ - /* replacing int32 with long */ - ImageCount = (long)((GifMemoryStruct.GifHeader)->ImageCount); - - for (i = 0; i < ImageCount; i++) { - gifImageDesc = *(GifMemoryStruct.GifImageDesc[i]); - - if (gifImageDesc.Image != NULL) - free(gifImageDesc.Image); - - if (GifMemoryStruct.GifImageDesc[i] != NULL) { - free(GifMemoryStruct.GifImageDesc[i]); - GifMemoryStruct.GifImageDesc[i] = NULL; - } - - if (GifMemoryStruct.GifGraphicControlExtension[i] != NULL) { - free(GifMemoryStruct.GifGraphicControlExtension[i]); - GifMemoryStruct.GifGraphicControlExtension[i] = NULL; - } - } - - free(StartPos); - if (GifMemoryStruct.GifHeader != NULL) { - free(GifMemoryStruct.GifHeader); - GifMemoryStruct.GifHeader = NULL; - } - if (GifMemoryStruct.GifApplicationExtension != NULL) { - free(GifMemoryStruct.GifApplicationExtension); - GifMemoryStruct.GifApplicationExtension = NULL; - } - if (GifMemoryStruct.GifImageDesc != NULL) { - free(GifMemoryStruct.GifImageDesc); - GifMemoryStruct.GifImageDesc = NULL; - } - if (GifMemoryStruct.GifGraphicControlExtension != NULL) { - free(GifMemoryStruct.GifGraphicControlExtension); - GifMemoryStruct.GifGraphicControlExtension = NULL; - } - - return EXIT_SUCCESS; -} diff --git a/hl/tools/gif2h5/gif2mem.c b/hl/tools/gif2h5/gif2mem.c deleted file mode 100644 index 1471bb7993a..00000000000 --- a/hl/tools/gif2h5/gif2mem.c +++ /dev/null @@ -1,330 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * - * All rights reserved. * - * * - * This file is part of HDF5. The full HDF5 copyright notice, including * - * terms governing use, modification, and redistribution, is contained in * - * the COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* - * This file contains snippets of code from James Murray's original file to - * display the GIF header information, but most of it has been modified to - * suit gif2hdf - */ - -/****************************************************************************\ -** Title: GIFHEAD.C ** -** Purpose: Display the data in a GIF image file. ** -** Version: 1.0 ** -** C Compilers: Borland C++ v2.0, Microsoft C v6.00a ** -** ** -** GIFHEAD displays all real information contained within a GIF image ** -** file, including all color tables and extension block information. ** -** GIFHEAD reads both GIF 87a abd 89a-format files. ** -** ** -** Copyright (C) 1991-92 by Graphics Software Labs. All rights reserved. ** -\****************************************************************************/ -#include - -#include "gif.h" - -int -Gif2Mem(GIFBYTE *MemGif, GIFTOMEM *GifMemoryStruct) -{ - /* - * The gif structure outline for passing data to memory is given in gif.h. - * These pointers are redundant, should take them out in ver. 2 - */ - GIFHEAD *gifHead; /* GIF Header structure */ - GIFIMAGEDESC **gifImageDesc; /* Logical Image Descriptor struct */ - GIFPLAINTEXT **gifPlainText; /* Plain Text Extension structure */ - GIFAPPLICATION **gifApplication; /* Application Extension structure */ - GIFCOMMENT **gifComment; /* Comment Extension structure */ - GIFGRAPHICCONTROL **gifGraphicControl; /* Graphic Control Extension strct */ - - GIFWORD i; /* Loop counter */ - GIFBYTE Identifier; /* Extension block identifier holder */ - GIFBYTE Label; /* Extension block label holder */ - GIFBYTE ImageCount; /* Count of the number of images in the file */ - GIFBYTE ImageArray; /* Keep the size of the array to store Images */ - GIFBYTE CommentCount; - GIFBYTE CommentArray; - GIFBYTE ApplicationCount; - GIFBYTE ApplicationArray; - GIFBYTE PlainTextCount; - GIFBYTE PlainTextArray; - GIFBYTE GCEflag; - GIFBYTE aTemp; - GIFBYTE j; - GIFBYTE w; /* Two more variables needed only while testing */ - GIFBYTE *b; /* Endian Ordering */ - - /* Allocate memory for the GIF structures */ - /* Plug the structs into GifMemoryStruct at the end */ - /****************************************************/ - if (!(gifHead = (GIFHEAD *)malloc(sizeof(GIFHEAD)))) { - printf("Could not allocate memory for gifHead\n"); - exit(EXIT_FAILURE); - } - - /* - * The next three have to grow dynamically so we leave them for now and - * let realloc handle it later on. - */ - gifImageDesc = NULL; - gifPlainText = NULL; - gifGraphicControl = NULL; - gifComment = NULL; - gifApplication = NULL; - - /******************************/ - /* Memory allocation complete */ - /******************************/ - - /* Carry out Endian Testing and set Endian Order */ - w = 0x0001; - b = (GIFBYTE *)&w; - EndianOrder = (b[0] ? 1 : 0); - - /* Read the GIF image file header information */ - ReadGifHeader(gifHead, &MemGif); - - /* Check for FILE stream error */ -#if 0 - if (ferror(fpGif)) - { - fputs("GIFHEAD: Error reading header information!\n", stderr); - exit(EXIT_FAILURE); - } -#endif /* 0 */ - - /* - * Identify, read, and display block information. - */ - ImageCount = ImageArray = 0; - CommentCount = CommentArray = 0; - ApplicationCount = ApplicationArray = 0; - PlainTextCount = PlainTextArray = 0; - GCEflag = 0; - - for (;;) { - Identifier = *MemGif++; - - switch (Identifier) { - case 0x3B: /* Trailer */ - /* - * The counts are stored to make it easier while putting stuff - * into the HDF file and then deallocating space. - */ - gifHead->ImageCount = ImageCount; - gifHead->CommentCount = CommentCount; - gifHead->ApplicationCount = ApplicationCount; - gifHead->PlainTextCount = PlainTextCount; - - /* putting stuff into the gif2mem structure */ - GifMemoryStruct->GifHeader = gifHead; - GifMemoryStruct->GifImageDesc = gifImageDesc; - GifMemoryStruct->GifPlainTextExtension = gifPlainText; - GifMemoryStruct->GifApplicationExtension = gifApplication; - GifMemoryStruct->GifCommentExtension = gifComment; - GifMemoryStruct->GifGraphicControlExtension = gifGraphicControl; - - /* return the struct */ - return 0; - - case 0x2C: /* Image Descriptor */ - /* - * If there was no image descriptor before this increase image - * count. If an imagedescriptor was present, reset GCEflag - */ - if (GCEflag == 0) - ImageCount++; - else - GCEflag = 0; - - if (ImageCount > ImageArray) { - aTemp = ImageArray; - ImageArray = (GIFBYTE)((ImageArray << 1) + 1); - if (!(gifImageDesc = - (GIFIMAGEDESC **)realloc(gifImageDesc, sizeof(GIFIMAGEDESC *) * ImageArray))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - if (!(gifGraphicControl = (GIFGRAPHICCONTROL **)realloc( - gifGraphicControl, sizeof(GIFGRAPHICCONTROL *) * ImageArray))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - for (j = aTemp; j < ImageArray; j++) { - gifGraphicControl[j] = NULL; - gifImageDesc[j] = NULL; - } - } - - if (!(gifImageDesc[ImageCount - 1] = (GIFIMAGEDESC *)malloc(sizeof(GIFIMAGEDESC)))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - if (ReadGifImageDesc(gifImageDesc[ImageCount - 1], &MemGif) == -1) - fputs("Error reading Image Descriptor information\n", stderr); - - /* Decompress the Image */ - gifImageDesc[ImageCount - 1]->Image = Decompress(gifImageDesc[ImageCount - 1], gifHead); - free(gifImageDesc[ImageCount - 1]->GIFImage); - - /* - * Convert the local palette into an HDF compatible palette In - * case the local color table is present, it is written out as - * the HDFPalette If it is absent the global table is written - * as the HDFPalette. - */ - if (!((gifImageDesc[ImageCount - 1]->PackedField) & 0x80)) { - /* Check to see if the global color table exists.... */ - if (gifHead->PackedField & 0x80) { - for (i = 0; i < gifHead->TableSize; i++) { - gifImageDesc[ImageCount - 1]->HDFPalette[i][0] = gifHead->HDFPalette[i][0]; - gifImageDesc[ImageCount - 1]->HDFPalette[i][1] = gifHead->HDFPalette[i][1]; - gifImageDesc[ImageCount - 1]->HDFPalette[i][2] = gifHead->HDFPalette[i][2]; - } - } - - gifImageDesc[ImageCount - 1]->TableSize = gifHead->TableSize; - } - - break; - - case 0x21: /* Extension Block */ - Label = *MemGif++; - - switch (Label) { - case 0x01: /* Plain Text Extension */ - puts("Plain Text Extension\n"); - PlainTextCount++; - - if (PlainTextCount > PlainTextArray) - PlainTextArray = (GIFBYTE)((PlainTextArray << 1) + 1); - - if (!(gifPlainText = (GIFPLAINTEXT **)realloc(gifPlainText, sizeof(GIFPLAINTEXT *) * - PlainTextArray))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - if (!(gifPlainText[PlainTextCount - 1] = - (GIFPLAINTEXT *)malloc(sizeof(GIFPLAINTEXT)))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - if (ReadGifPlainText(gifPlainText[PlainTextCount - 1], &MemGif)) - fprintf(stderr, "Error reading Plain Text Extension information.\n"); - - break; - - case 0xFE: /* Comment Extension */ - CommentCount++; - - if (CommentCount > CommentArray) - CommentArray = (GIFBYTE)((CommentArray << 1) + 1); - - if (!(gifComment = - (GIFCOMMENT **)realloc(gifComment, sizeof(GIFCOMMENT *) * CommentArray))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - if (!(gifComment[CommentCount - 1] = (GIFCOMMENT *)malloc(sizeof(GIFCOMMENT)))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - if (ReadGifComment(gifComment[CommentCount - 1], &MemGif)) - fprintf(stderr, "Error reading Comment Extension information\n"); - - break; - - case 0xF9: /* Graphic Control Extension */ - if (GCEflag == 0) - ImageCount++; - - GCEflag = 1; - - if (ImageCount > ImageArray) { - aTemp = ImageArray; - ImageArray = (GIFBYTE)((ImageArray << 1) + 1); - - if (!(gifGraphicControl = (GIFGRAPHICCONTROL **)realloc( - gifGraphicControl, sizeof(GIFGRAPHICCONTROL *) * ImageArray))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - if (!(gifImageDesc = (GIFIMAGEDESC **)realloc( - gifImageDesc, sizeof(GIFIMAGEDESC *) * ImageArray))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - for (j = aTemp; j < ImageArray; j++) { - gifGraphicControl[j] = NULL; - gifImageDesc[j] = NULL; - } - } - - if (!(gifGraphicControl[ImageCount - 1] = - (GIFGRAPHICCONTROL *)malloc(sizeof(GIFGRAPHICCONTROL)))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - if (ReadGifGraphicControl(gifGraphicControl[ImageCount - 1], &MemGif)) - fprintf(stderr, "Error reading Graphic Control Extension information\n"); - - (*MemGif)++; - if ((!*MemGif) == 0) - fprintf(stderr, "Error reading Graphic Control Extension\n"); - - break; - - case 0xFF: /* Application Extension */ - ApplicationCount++; - - if (ApplicationCount > ApplicationArray) - ApplicationArray = (GIFBYTE)((ApplicationArray << 1) + 1); - - if (!(gifApplication = (GIFAPPLICATION **)realloc( - gifApplication, sizeof(GIFAPPLICATION *) * ApplicationArray))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - if (!(gifApplication[ApplicationCount - 1] = - (GIFAPPLICATION *)malloc(sizeof(GIFAPPLICATION)))) { - printf("Out of memory!"); - exit(EXIT_FAILURE); - } - - if (ReadGifApplication(gifApplication[ApplicationCount - 1], &MemGif)) - fprintf(stderr, "Error reading Application Extension information\n"); - - break; - - default: - printf("Unknown Extension Label: %#02x\n", Label); - break; - } - - break; - - default: - fprintf(stderr, "Unknown Block Separator Character: %#02x\n", Identifier); - } - } -} diff --git a/hl/tools/gif2h5/gifread.c b/hl/tools/gif2h5/gifread.c deleted file mode 100644 index 5fb1fd5428a..00000000000 --- a/hl/tools/gif2h5/gifread.c +++ /dev/null @@ -1,376 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * - * All rights reserved. * - * * - * This file is part of HDF5. The full HDF5 copyright notice, including * - * terms governing use, modification, and redistribution, is contained in * - * the COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include -#include - -#include "gif.h" - -int EndianOrder; - -static GIFBYTE *ReadDataSubBlocks(GIFBYTE **MemGif2, GIFWORD *DSize); - -GIFWORD -GetWord(GIFBYTE *MemGif) -{ - GIFWORD w; - - if (EndianOrder == 1) { - /* LittleEndian */ - w = (GIFWORD)(*MemGif++ & 0xFF); - w |= (GIFWORD)((*MemGif++ & 0xFF) << 0x08); - } - else { - w = (GIFWORD)(*MemGif++ & 0xFF); - w = ((GIFWORD)(*MemGif++ & 0xFF)) | (w << 0x08); - } - - return w; -} - -GIFBYTE -GetByte(const GIFBYTE *MemGif) -{ - return *MemGif; -} - -/* - * Read a GIF image GIFBYTE Header. - * - * This function reads the Header, Logical Screen Descriptor, and - * Global Color Table (if any) from a GIF image file. The information - * is stored in a GIFHEAD structure. - * - * Returns: -1 if a FILE stream error occurred during the read, - * otherwise 0 if no error occurred. - */ -int -ReadGifHeader(GIFHEAD *GifHead, /* Pointer to GIF header structure */ - GIFBYTE **MemGif2) /* GIF image file input FILE stream */ -{ - GIFWORD i; /* Loop counter */ - GIFWORD tableSize; /* Number of entries in the Global Color Table */ - - GifHead->TableSize = 0; - for (i = 0; i < 6; i++) { - GifHead->HeaderDump[i] = *(*MemGif2)++; - } - - if (strncmp((const char *)GifHead->HeaderDump, "GIF", (size_t)3) != 0) { - printf("The file does not appear to be a valid GIF file.\n"); - exit(EXIT_FAILURE); - } - - for (i = 0; i < 7; i++) { - GifHead->LSDDump[i] = *(*MemGif2)++; - } - - GifHead->PackedField = GifHead->LSDDump[4]; - - /* Check if a Global Color Table is present */ - if (GifHead->PackedField & 0x80) { - /* Read number of color table entries */ - tableSize = (GIFWORD)(1L << ((GifHead->PackedField & 0x07) + 1)); - GifHead->TableSize = tableSize; - - /* Read the Global Color Table */ - - /* - * There are some changes made here apart from just reading in the - * global color table as would seem intuitively obvious. The colors - * are stored in the bottom part of the palette as opposed to the top - */ - - for (i = 0; i < tableSize; i++) { - GifHead->HDFPalette[i][0] = *(*MemGif2)++; - GifHead->HDFPalette[i][1] = *(*MemGif2)++; - GifHead->HDFPalette[i][2] = *(*MemGif2)++; - } - } - - /* Check for a FILE stream error */ -#if 0 - if (ferror(FpGif)) - return -1; -#endif /* 0 */ - - return 0; /* No FILE stream error occurred */ -} - -/* -** Read a GIF Local Image Descriptor. -** -** This function reads the Local Image Descriptor, and Local Color -** Table (if any) from a GIF image file. The information is stored -** in a GIFIMAGEDESC structure. -** -** Note that the ImageSeparator field value in the GIFIMAGEDESC -** structure is assigned by the function calling ReadGifImageDesc(). -** -** Returns: -1 if a FILE stream error occurred during the read, -** otherwise 0 if no error occurred. -*/ -int -ReadGifImageDesc(GIFIMAGEDESC *GifImageDesc, /* Pointer to GIF image descriptor structure */ - GIFBYTE **MemGif2 /* GIF image file input FILE stream */ -) -{ - GIFWORD i; /* Loop counter */ - GIFWORD tableSize; /* Number of entries in the Local Color Table */ - /* GIFBYTE Interlace; */ /* PackedField & 0x20 gives information on interlacing */ - GIFBYTE *TempPtr; - int ch, ch1; - - GifImageDesc->TableSize = 0; - for (i = 0; i < 9; i++) { - GifImageDesc->GIDDump[i] = *(*MemGif2)++; - } - - /* - ** Get the relevant fields. I need ImageWidth and Height actively hence I have - ** taken information from those fields. I intend to keep the GifImageDesc data - ** structure as it is so that anyone needing the rest of the fields can do so - ** quickly. - */ - - if (EndianOrder == 1) /* LittleEndian */ - { - GifImageDesc->ImageWidth = (GIFWORD)(GifImageDesc->GIDDump[4] & 0xFF); - GifImageDesc->ImageWidth |= (GIFWORD)((GifImageDesc->GIDDump[5] & 0xFF) << 0x08); - - GifImageDesc->ImageHeight = (GIFWORD)(GifImageDesc->GIDDump[6] & 0xFF); - GifImageDesc->ImageHeight |= (GIFWORD)((GifImageDesc->GIDDump[7] & 0xFF) << 0x08); - } - else { - GifImageDesc->ImageWidth = (GIFWORD)(GifImageDesc->GIDDump[4] & 0xFF); - GifImageDesc->ImageWidth = - ((GIFWORD)(GifImageDesc->GIDDump[5] & 0xFF)) | (GifImageDesc->ImageWidth << 0x08); - - GifImageDesc->ImageHeight = (GIFWORD)(GifImageDesc->GIDDump[6] & 0xFF); - GifImageDesc->ImageHeight = - ((GIFWORD)(GifImageDesc->GIDDump[7] & 0xFF)) | (GifImageDesc->ImageWidth << 0x08); - } - - GifImageDesc->PackedField = GifImageDesc->GIDDump[8]; - - /* Interlace = GifImageDesc->PackedField & 0x20; */ - - /* Check if a Local Color Table is present */ - if (GifImageDesc->PackedField & 0x80) { - /* Read number of color table entries */ - tableSize = (GIFWORD)(1L << ((GifImageDesc->PackedField & 0x07) + 1)); - GifImageDesc->TableSize = tableSize; - /* Read the Local Color Table */ - for (i = 0; i < tableSize; i++) { - GifImageDesc->HDFPalette[i][0] = *(*MemGif2)++; - GifImageDesc->HDFPalette[i][1] = *(*MemGif2)++; - GifImageDesc->HDFPalette[i][2] = *(*MemGif2)++; - } - } - - /* - ** Get LZW minimum Code Size - */ - GifImageDesc->CodeSize = (GIFWORD) * (*MemGif2)++; - - /*GifImageDesc->GIFImage = ReadDataSubBlocks(FpGif);*/ - if (!(GifImageDesc->GIFImage = - (GIFBYTE *)malloc((GifImageDesc->ImageWidth) * (GifImageDesc->ImageHeight)))) { - printf("Out of memory"); - exit(EXIT_FAILURE); - } - - TempPtr = GifImageDesc->GIFImage; - do { - ch = ch1 = (int)*(*MemGif2)++; - while (ch--) - *TempPtr++ = *(*MemGif2)++; - } while (ch1); - - return (0); /* No FILE stream error occurred */ -} - -/* -** Read a GIF Graphic Control Extension block. -** -** Note that the Introducer and Label field values in the GIFGRAPHICCONTROL -** structure are assigned by the function calling ReadGifGraphicControl(). -** -** Returns: -1 if a FILE stream error occurred during the read, -** otherwise 0 if no error occurred. -*/ -int -ReadGifGraphicControl(GIFGRAPHICCONTROL *GifGraphicControl, /* Pointer to GC Extension structure */ - GIFBYTE **MemGif2 /* GIF image file input FILE stream */ -) -{ - int i; - - for (i = 0; i < 5; i++) { - GifGraphicControl->GCEDump[i] = *(*MemGif2)++; - } - - return (0); /* No FILE stream error occurred */ -} - -/* -** Read a GIF Plain Text Extension block. -** -** Note that the Introducer and Label field values in the GIFLPLAINTEXT -** structure are assigned by the function calling ReadGifPlainText(). -** -** Returns: -1 if a FILE stream error occurred during the read, -** otherwise 0 if no error occurred. -*/ -int -ReadGifPlainText(GIFPLAINTEXT *GifPlainText, /* Pointer to Plain Text Extension structure */ - GIFBYTE **MemGif2 /* GIF image file input FILE stream */ -) -{ - int i; - - for (i = 0; i < 13; i++) { - GifPlainText->PTEDump[i] = *(*MemGif2)++; - } - - /* Read in the Plain Text data sub-blocks */ - if (!(GifPlainText->PlainTextData = ReadDataSubBlocks(MemGif2, &(GifPlainText->DataSize)))) - return (1); - - /* - GifPlainText->Terminator = 0; - */ - - /* Check for a FILE stream error */ - /* - if (ferror(FpGif)) - return(-1); - */ - - return (0); /* No FILE stream error occurred */ -} - -/* -** Read a GIF Application Extension block. -** -** Note that the Introducer and Label field values in the GIFAPPLICATION -** structure are assigned by the function calling ReadGifApplication(). -** -** Returns: -1 if a FILE stream error occurred during the read, -** otherwise 0 if no error occurred. -*/ -int -ReadGifApplication(GIFAPPLICATION *GifApplication, /* Pointer to Application Extension structure */ - GIFBYTE **MemGif2 /* GIF image file input FILE stream */ -) -{ - int i; - - for (i = 0; i < 12; i++) { - GifApplication->AEDump[i] = *(*MemGif2)++; - } - - /* Read in the Plain Text data sub-blocks */ - if (!(GifApplication->ApplicationData = ReadDataSubBlocks(MemGif2, &(GifApplication->DataSize)))) - return (1); - /* - GifApplication->Terminator = 0; - */ - - /* Check for a FILE stream error */ - /* - if (ferror(FpGif)) - return(-1); - */ - - return (0); /* No FILE stream error occurred */ -} - -/* -** Read a GIF Comment Extension block. -** -** Note that the Introducer and Label field values in the GIFCOMMENT -** structure are assigned by the function calling ReadGifComment(). -** -** Returns: -1 if a FILE stream error occurred during the read, -** otherwise 0 if no error occurred. -*/ -int -ReadGifComment(GIFCOMMENT *GifComment, /* Pointer to GIF Comment Extension structure */ - GIFBYTE **MemGif2 /* GIF image file input FILE stream */ -) -{ - - /* Read in the Plain Text data sub-blocks */ - if (!(GifComment->CommentData = ReadDataSubBlocks(MemGif2, &(GifComment->DataSize)))) - return (1); - - GifComment->Terminator = 0; - - return (0); /* No FILE stream error occurred */ -} - -/* -** Read one or more GIF data sub-blocks and write the information -** to a buffer. -** -** A GIF "sub-block" is a single count byte followed by 1 to 255 -** additional data bytes. -** -** Returns: A NULL pointer if a memory allocation error occurred, -** otherwise a valid pointer if no error occurred. -*/ -static GIFBYTE * -ReadDataSubBlocks(GIFBYTE **MemGif2, /* GIF image file input FILE stream */ - GIFWORD *DSize) -{ - GIFBYTE *ptr1; /* Pointer used to "walk the heap" */ - GIFBYTE *ptr2; /* Pointer used to mark the top of the heap */ - GIFBYTE dataSize; /* Size of the current data sub-block being read */ - GIFWORD bufSize; /* Total size of the Plain Text data buffer */ - int tempcount = 0; - - bufSize = 0; /* The output buffer is empty */ - - dataSize = *(*MemGif2)++; /* Get the size of the first sub-block */ - - /* Allocate initial data buffer */ - if (!(ptr1 = ptr2 = (GIFBYTE *)malloc((size_t)dataSize + 1))) { - printf("Out of memory. Allocation of memory for data sub-blocks for\neither Comment, Plain Text or " - "Application Extensions failed"); - return ((GIFBYTE *)NULL); - } - for (;;) { - tempcount++; - bufSize += (dataSize); /* Running total of the buffer size */ - *DSize = bufSize; - -#ifdef COMMENTED_OUT - *ptr1++ = dataSize; /* Write the data count */ -#endif /* COMMENTED_OUT */ - while (dataSize--) /* Read/write the Plain Text data */ - *ptr1++ = *(*MemGif2)++; - - /* Check if there is another data sub-block */ - if ((dataSize = *(*MemGif2)++) == 0) - break; /* Block Terminator encountered */ - - /* Increase the buffer size to accommodate the next sub-block */ - if (!(ptr1 = ptr2 = (GIFBYTE *)realloc(ptr2, bufSize + dataSize + 1))) - return ((GIFBYTE *)NULL); - - ptr1 += bufSize; /* Move pointer to the end of the data */ - } - - *ptr1++ = '\0'; - - return (ptr2); /* Return a pointer to the sub-block data */ -} diff --git a/hl/tools/gif2h5/h52gifgentst.c b/hl/tools/gif2h5/h52gifgentst.c deleted file mode 100644 index 4851145ec45..00000000000 --- a/hl/tools/gif2h5/h52gifgentst.c +++ /dev/null @@ -1,99 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * - * All rights reserved. * - * * - * This file is part of HDF5. The full HDF5 copyright notice, including * - * terms governing use, modification, and redistribution, is contained in * - * the COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include -#include -#include -#include "hdf5.h" -#include "H5IMpublic.h" - -/*------------------------------------------------------------------------- - * Program: h52gifgentst - * - * Purpose: generate files for h52gif testing - * - *------------------------------------------------------------------------- - */ - -#define FILENAME "h52giftst.h5" -#define WIDTH 400 -#define HEIGHT 200 -#define PAL_ENTRIES 256 -#define IMAGE1_NAME "image" -#define PAL_NAME "palette" - -/*------------------------------------------------------------------------- - * Function: main - * - * Purpose: main program - * - *------------------------------------------------------------------------- - */ - -int -main(void) -{ - hid_t fid; - int i, j, n, space; - unsigned char *buf; - unsigned char pal[PAL_ENTRIES * 3]; /* palette array */ - hsize_t pal_dims[2] = {PAL_ENTRIES, 3}; /* palette dimensions */ - hsize_t width = WIDTH; - hsize_t height = HEIGHT; - - /* Allocate buffer */ - if (NULL == (buf = (unsigned char *)malloc(WIDTH * HEIGHT))) - return EXIT_FAILURE; - - /* create a file */ - if ((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) - return EXIT_FAILURE; - - /* create an image */ - space = WIDTH * HEIGHT / PAL_ENTRIES; - for (i = 0, j = 0, n = 0; i < WIDTH * HEIGHT; i++, j++) { - buf[i] = (unsigned char)n; - if (j > space) { - n++; - j = 0; - } - } - - /* make the image */ - if (H5IMmake_image_8bit(fid, IMAGE1_NAME, width, height, buf) < 0) - return EXIT_FAILURE; - - /*------------------------------------------------------------------------- - * define a palette, blue to red tones - *------------------------------------------------------------------------- - */ - for (i = 0, n = 0; i < PAL_ENTRIES * 3; i += 3, n++) { - pal[i] = (unsigned char)n; /* red */ - pal[i + 1] = (unsigned char)0; /* green */ - pal[i + 2] = (unsigned char)(255 - n); /* blue */ - } - - /* make a palette */ - if (H5IMmake_palette(fid, PAL_NAME, pal_dims, pal) < 0) - return EXIT_FAILURE; - - /* attach the palette to the image */ - if (H5IMlink_palette(fid, IMAGE1_NAME, PAL_NAME) < 0) - return EXIT_FAILURE; - - if (H5Fclose(fid) < 0) - return EXIT_FAILURE; - - free(buf); - - return EXIT_SUCCESS; -} diff --git a/hl/tools/gif2h5/h52giftest.sh.in b/hl/tools/gif2h5/h52giftest.sh.in deleted file mode 100644 index bdc85c3f540..00000000000 --- a/hl/tools/gif2h5/h52giftest.sh.in +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh -# -# Copyright by The HDF Group. -# All rights reserved. -# -# This file is part of HDF5. The full HDF5 copyright notice, including -# terms governing use, modification, and redistribution, is contained in -# the COPYING file, which can be found at the root of the source code -# distribution tree, or in https://www.hdfgroup.org/licenses. -# If you do not have access to either file, you may request a copy from -# help@hdfgroup.org. -# -# HDF Utilities Test script - - -TESTFILE1="$srcdir/testfiles/h52giftst.h5" -TESTFILE2="$srcdir/testfiles/image1.gif" -TESTFILE3="$srcdir/testfiles/ex_image2.h5" - -# initialize errors variable -errors=0 - -TESTING() { - SPACES=" " - echo "Testing $* $SPACES" | cut -c1-70 | tr -d '\012' -} - - - -# Verify the test runs with success (return code is 0) -TOOLTEST() -{ - # for now, discard any error messages generated. - $RUNSERIAL $* > /dev/null 2>&1 - - RET=$? - if [ $RET = 0 ] ; then - echo " PASSED" - else - echo "*FAILED*" - errors="` expr $errors + 1 `"; - fi - -} - -# Verify the test runs with failure (return code is not 0) -# Use for testing if tool can handle error conditions like -# illegal input, bad arguments, exceeding limits, ... -TOOLTESTFAIL() -{ - # for now, discard any error messages generated. - $RUNSERIAL $* > /dev/null 2>&1 - - RET=$? - if [ $RET != 0 ] ; then - echo " PASSED" - else - echo "*FAILED*" - errors="` expr $errors + 1 `"; - fi -} - - -# Positive tests for gif2h5 -echo "**validate the gif2h5 tool processes input correctly..." -TESTING "./gif2h5 image1.gif image1.h5" -TOOLTEST ./gif2h5 $TESTFILE2 image1.h5 -echo "" - -# Positive tests for h52gif -echo "**validate the h52gif tool processes input correctly..." -TESTING "./h52gif h52giftst.h5 image1.gif -i image" -TOOLTEST ./h52gif $TESTFILE1 image1.gif -i image -echo "" - -# Negative tests. -echo "**verify that the h52gif tool handles error conditions correctly..." -# nonexisting dataset name -TESTING "./h52gif h52giftst.h5 image.gif -i nosuch_image" -TOOLTESTFAIL "./h52gif $TESTFILE1 image.gif -i nosuch_image" -# this test should have failed but it did not. Comment it out for now. -#TESTING "./h52gif h52giftst.h5 image.gif -i palette" -#TOOLTESTFAIL "./h52gif $TESTFILE1 image.gif -i palette" -TESTING "./h52gif h52giftst.h5 image24.gif -i image24bitpixel" -TOOLTESTFAIL "./h52gif $TESTFILE3 image24.gif -i image24bitpixel" -echo "" - -# all done. summarize results. -if test $errors -eq 0 ; then - echo "All gif2h5 and h52gif tests passed." - exit 0 -else - echo "Some gif2h5 or h52gif tests failed with $errors errors." - exit 1 -fi diff --git a/hl/tools/gif2h5/hdf2gif.c b/hl/tools/gif2h5/hdf2gif.c deleted file mode 100644 index 120e42e294c..00000000000 --- a/hl/tools/gif2h5/hdf2gif.c +++ /dev/null @@ -1,334 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * - * All rights reserved. * - * * - * This file is part of HDF5. The full HDF5 copyright notice, including * - * terms governing use, modification, and redistribution, is contained in * - * the COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include -#include -#include "gif.h" -#include "H5IMpublic.h" -#include "h5tools.h" -#include "h5tools_utils.h" - -/* Name of tool */ -#define PROGRAMNAME "hdf2gif" - -#define IMAGE_WIDTH_MAX 65535 /* unsigned 16bits integer */ -#define IMAGE_HEIGHT_MAX 65535 /* unsigned 16bits integer */ - -int EndianOrder; - -static void -putword(int w, FILE *fp) -{ - /* writes a 16-bit integer in GIF order (LSB first) */ - fputc(w & 0xff, fp); - fputc((w >> 8) & 0xff, fp); -} - -static void -usage(void) -{ - printf("Usage: h52gif -i \n"); - fprintf(stdout, " h52gif -V \n"); - fprintf(stdout, " Print HDF5 library version and exit\n"); - printf("h52gif expects *at least* one h5_image.\n"); -} - -static void -leave(int ret) -{ - h5tools_close(); - exit(ret); -} - -static FILE *fpGif = NULL; -int -main(int argc, char **argv) -{ - GIFBYTE *Image; - - /* compression structs */ - GIFCHAR *HDFName = NULL; - GIFCHAR *GIFName = NULL; - - GIFBYTE *b; - - GIFBYTE GlobalPalette[256][3]; - GIFBYTE Red[256]; - GIFBYTE Green[256]; - GIFBYTE Blue[256]; - - int RWidth, RHeight; - int ColorMapSize, InitCodeSize, Background, BitsPerPixel; - int j, nc; - int i; - int numcols = 0; - - GIFBYTE pc2nc[256], r1[256], g1[256], b1[256]; - - int arg_index = 2; - int bool_is_image = 0; /* 0 = false , 1 = true */ - char *image_name = NULL; - int idx; - - h5tools_setprogname(PROGRAMNAME); - h5tools_setstatus(EXIT_SUCCESS); - - /* Initialize h5tools lib */ - h5tools_init(); - - if (argv[1] && (strcmp("-V", argv[1]) == 0)) { - print_version("gif2h5"); - h5tools_setstatus(EXIT_SUCCESS); - } - - if (argc < 4) { - /* they didn't supply at least one image -- bail */ - usage(); - h5tools_setstatus(EXIT_FAILURE); - } - - HDFName = argv[1]; - GIFName = argv[2]; - - /* get the options */ - while (arg_index++ < argc - 1) { - if (!strcmp(argv[arg_index], "-i")) { - bool_is_image = 1; - continue; - } - - if (bool_is_image) { - /* allocate space to store the image name */ - size_t len = strlen(argv[arg_index]); - image_name = (GIFCHAR *)malloc(len + 1); - strcpy(image_name, argv[arg_index]); - - bool_is_image = 0; - continue; - } - - /* oops. This was not meant to happen */ - usage(); - - goto out; - } - - /* Do Endian Order testing and set Endian Order */ - idx = 0x0001; - b = (GIFBYTE *)&idx; - EndianOrder = (b[0] ? 1 : 0); - - if (!(fpGif = fopen(GIFName, "wb"))) { - printf("Error opening gif file for output. Aborting.\n"); - goto out; - } - - Background = 0; - { - hsize_t width, height, planes; - hid_t fid; - char interlace[20]; - hssize_t npals; - hsize_t pal_dims[2]; - unsigned char *pal; - - if ((fid = H5Fopen(HDFName, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) { - fprintf(stderr, "Unable to open HDF file for input. Aborting.\n"); - goto out; - } - - /* get image's information */ - if (H5IMget_image_info(fid, image_name, &width, &height, &planes, interlace, &npals) < 0) { - fprintf(stderr, "Unable to get information of the image. Aborting.\n"); - goto out; - } - - if (width > IMAGE_WIDTH_MAX || height > IMAGE_HEIGHT_MAX) { - fprintf(stderr, "HDF5 image is too large. Limit is %d by %d.\n", IMAGE_WIDTH_MAX, - IMAGE_HEIGHT_MAX); - goto out; - } - - /* tool can handle single plane images only. */ - if (planes > 1) { - fprintf(stderr, "Cannot handle multiple planes image\n"); - goto out; - } - - Image = (GIFBYTE *)malloc((size_t)width * (size_t)height); - - if (H5IMread_image(fid, image_name, Image) < 0) { - fprintf(stderr, "Unable to read the image. Aborting.\n"); - goto out; - } - - if (npals) { - if (H5IMget_palette_info(fid, image_name, 0, pal_dims) < 0) { - fprintf(stderr, "Unable to get information of the palette. Aborting.\n"); - goto out; - } - - pal = (GIFBYTE *)malloc((size_t)pal_dims[0] * (size_t)pal_dims[1]); - - if (H5IMget_palette(fid, image_name, 0, pal) < 0) - goto out; - - numcols = (int)pal_dims[0]; - - for (i = 0, j = 0; i < numcols; j += 3, i++) { - GlobalPalette[i][0] = pal[j]; - GlobalPalette[i][1] = pal[j + 1]; - GlobalPalette[i][2] = pal[j + 2]; - } - - free(pal); - } - - H5Fclose(fid); - - RWidth = (int)width; - RHeight = (int)height; - - /* - * If the first image does not have a palette, I make my own global - * color table Obviously this is not the best thing to do, better - * steps would be: - * - * 1. Check for either a global palette or a global attribute called - * palette - * 2. Check for palettes in any of the other images. - */ - if (!npals) { - numcols = 256; - for (i = 0; i < numcols; i++) { - Red[i] = (GIFBYTE)(255 - i); - Green[i] = (GIFBYTE)(255 - i); - Blue[i] = (GIFBYTE)(255 - i); - } - } - else { - for (i = 0; i < numcols; i++) { - Red[i] = GlobalPalette[i][0]; - Green[i] = GlobalPalette[i][1]; - Blue[i] = GlobalPalette[i][2]; - } - } - - for (i = 0; i < numcols; i++) { - pc2nc[i] = r1[i] = g1[i] = b1[i] = 0; - } - - /* compute number of unique colors */ - nc = 0; - - for (i = 0; i < numcols; i++) { - /* see if color #i is already used */ - for (j = 0; j < i; j++) { - if (Red[i] == Red[j] && Green[i] == Green[j] && Blue[i] == Blue[j]) - break; - } - - if (j == i) { - /* wasn't found */ - pc2nc[i] = (GIFBYTE)nc; - r1[nc] = Red[i]; - g1[nc] = Green[i]; - b1[nc] = Blue[i]; - nc++; - } - else { - pc2nc[i] = pc2nc[j]; - } - } - - /* figure out 'BitsPerPixel' */ - for (i = 1; i < 8; i++) { - if ((1 << i) >= nc) - break; - } - - BitsPerPixel = i; - ColorMapSize = 1 << BitsPerPixel; - - if (BitsPerPixel <= 1) - InitCodeSize = 2; - else - InitCodeSize = BitsPerPixel; - - if (!fpGif) { - fprintf(stderr, "WriteGIF: file not open for writing\n"); - goto out; - } - - fwrite("GIF87a", sizeof(char), 6, fpGif); /* the GIF magic number */ - - putword(RWidth, fpGif); /* screen descriptor */ - putword(RHeight, fpGif); - - i = 0x00; /* No, there is no color map */ - i |= (8 - 1) << 4; /* OR in the color resolution (hardwired 8) */ - i |= (BitsPerPixel - 1); /* OR in the # of bits per pixel */ - fputc(i, fpGif); - - fputc(Background, fpGif); /* background color */ - fputc(0, fpGif); /* future expansion byte */ - - /* - * Put Image Descriptor - * Hardwiring Left Offset and Top Offset to 0x00 - */ - fputc(0x2c, fpGif); - putword(0x00, fpGif); - putword(0x00, fpGif); - putword(RWidth, fpGif); - putword(RHeight, fpGif); - - /* since we always have a local color palette ... */ - fputc((0x80 | (BitsPerPixel - 1)), fpGif); - - for (i = 0; i < ColorMapSize; i++) { - /* write out Global colormap */ - fputc(r1[i], fpGif); - fputc(g1[i], fpGif); - fputc(b1[i], fpGif); - } - - fputc(InitCodeSize, fpGif); - - i = hdfWriteGIF(fpGif, Image, 0, RHeight, RWidth, r1, g1, b1, pc2nc, 256, 8, BitsPerPixel); - fputc(0x00, fpGif); - free(Image); - } - - if (fputc(';', fpGif) == EOF) { - /* Write GIF file terminator */ - fprintf(stderr, "Error!"); - goto out; - } - - if (fpGif != NULL) - fclose(fpGif); - if (image_name != NULL) - free(image_name); - - leave(h5tools_getstatus()); - -out: - - if (fpGif != NULL) - fclose(fpGif); - if (image_name != NULL) - free(image_name); - - h5tools_setstatus(EXIT_FAILURE); - leave(h5tools_getstatus()); -} diff --git a/hl/tools/gif2h5/hdfgifwr.c b/hl/tools/gif2h5/hdfgifwr.c deleted file mode 100644 index 95f75d5d85e..00000000000 --- a/hl/tools/gif2h5/hdfgifwr.c +++ /dev/null @@ -1,463 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * - * All rights reserved. * - * * - * This file is part of HDF5. The full HDF5 copyright notice, including * - * terms governing use, modification, and redistribution, is contained in * - * the COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* - * hdfgifwr.c - handles writing of GIF files. - * - * Contains: - * hdfWriteGIF(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle, - * comment) - * - * Note: slightly brain-damaged, in that it'll only write non-interlaced - * GIF files (in the interests of speed, or something) - */ - -/***************************************************************** - * Portions of this code Copyright (C) 1989 by Michael Mauldin. - * Permission is granted to use this file in whole or in - * part for any purpose, educational, recreational or commercial, - * provided that this copyright notice is retained unchanged. - * This software is available to all free of charge by anonymous - * FTP and in the UUNET archives. - * - * - * Authors: Michael Mauldin (mlm@cs.cmu.edu) - * David Rowley (mgardi@watdcsu.waterloo.edu) - * - * Based on: compress.c - File compression ala IEEE Computer, June 1984. - * - * Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) - * Jim McKie (decvax!mcvax!jim) - * Steve Davies (decvax!vax135!petsd!peora!srd) - * Ken Turkowski (decvax!decwrl!turtlevax!ken) - * James A. Woods (decvax!ihnp4!ames!jaw) - * Joe Orost (decvax!vax135!petsd!joe) - *****************************************************************/ - -#include -#include -#include - -#include "gif.h" - -typedef GIFBYTE byte; -typedef long int count_int; - -#ifdef __STDC__ -static void compress(int, FILE *, byte *, int); -static void output(int); -static void cl_block(void); -static void cl_hash(count_int); -static void char_init(void); -static void char_out(int); -static void flush_char(void); -#else -static void compress(), output(), cl_block(), cl_hash(); -static void char_init(), char_out(), flush_char(); -#endif /* __STDC__ */ - -static byte pc2nc[256]; - -/***********************************************************************/ -static unsigned long cur_accum = 0; -static int cur_bits = 0; - -#define MAXCODE(n_bits) ((1 << (n_bits)) - 1) -#define XV_BITS 12 /* BITS was already defined on some systems */ -#define HSIZE 5003 /* 80% occupancy */ - -typedef unsigned char char_type; - -static int n_bits; /* number of bits/code */ -static int maxbits = XV_BITS; /* user settable max # bits/code */ -static int maxcode; /* maximum code, given n_bits */ -static int maxmaxcode = 1 << XV_BITS; /* NEVER generate this */ - -static count_int *htab; -static unsigned short *codetab; - -#define HashTabOf(i) htab[i] -#define CodeTabOf(i) codetab[i] - -static int hsize = HSIZE; /* for dynamic table sizing */ - -/* - * To save much memory, we overlay the table used by compress() with those - * used by decompress(). The tab_prefix table is the same size and type as - * the codetab. The tab_suffix table needs 2**BITS characters. We get this - * from the beginning of htab. The output stack uses the rest of htab, and - * contains characters. There is plenty of room for any possible stack (stack - * used to be 8000 characters). - */ - -static int free_ent = 0; /* first unused entry */ - -/* - * block compression parameters -- after all codes are used up, - * and compression rate changes, start over. - */ -static int clear_flg = 0; - -static long int in_count = 1; /* length of input */ -static long int out_count = 0; /* # of codes output (for debugging) */ - -/* - * compress stdin to stdout - * - * Algorithm: use open addressing double hashing (no chaining) on the prefix - * code / next character combination. We do a variant of Knuth's algorithm D - * (vol. 3, sec. 6.4) along with G. Knott's relatively-prime secondary probe. - * Here, the modular division first probe is gives way to a faster - * exclusive-or manipulation. Also do block compression with an adaptive - * reset, whereby the code table is cleared when the compression ratio - * decreases, but after the table fills. The variable-length output codes are - * re-sized at this point, and a special CLEAR code is generated for the - * decompressor. Late addition: construct the table according to file size - * for noticeable speed improvement on small files. Please direct questions - * about this implementation to ames!jaw. - */ - -static int g_init_bits; -static FILE *g_outfile; - -static int ClearCode; -static int EOFCode; - -/*************************************************************/ -int -hdfWriteGIF(FILE *fp, byte *pic, int ptype, int w, int h, const byte *rmap, const byte *gmap, - const byte *bmap, const byte *pc2ncmap, int numcols, int colorstyle, int BitsPerPixel) -{ - int InitCodeSize; - int i; - byte *pic8 = pic; - - if (!(htab = calloc(HSIZE, sizeof(count_int)))) { - fprintf(stderr, "Out of memory"); - return 1; - } - if (!(codetab = calloc(HSIZE, sizeof(unsigned short)))) { - fprintf(stderr, "Out of memory"); - return 1; - } - - /* Shut compiler up... */ - (void)ptype; - (void)rmap; - (void)gmap; - (void)bmap; - (void)numcols; - (void)colorstyle; - - for (i = 0; i < 256; i++) { - pc2nc[i] = pc2ncmap[i]; - } - - if (BitsPerPixel <= 1) - InitCodeSize = 2; - else - InitCodeSize = BitsPerPixel; - - if (!fp) { - fprintf(stderr, "WriteGIF: file not open for writing\n"); - return 1; - } - - compress(InitCodeSize + 1, fp, pic8, w * h); - - free(htab); - free(codetab); - - if (ferror(fp)) - return -1; - - return 0; -} - -/********************************************************/ -static void -compress(int init_bits, FILE *outfile, byte *data, int len) -{ - long fcode; - int i = 0; - int c; - int ent; - int disp; - int hsize_reg; - int hshift; - - /* - * Set up the globals: g_init_bits - initial number of bits g_outfile - - * pointer to output file - */ - g_init_bits = init_bits; - g_outfile = outfile; - - /* initialize 'compress' globals */ - maxbits = XV_BITS; - maxmaxcode = 1 << XV_BITS; - hsize = HSIZE; - free_ent = 0; - clear_flg = 0; - in_count = 1; - out_count = 0; - cur_accum = 0; - cur_bits = 0; - - /* Set up the necessary values */ - out_count = 0; - clear_flg = 0; - in_count = 1; - maxcode = MAXCODE(n_bits = g_init_bits); - - ClearCode = (1 << (init_bits - 1)); - EOFCode = ClearCode + 1; - free_ent = ClearCode + 2; - - char_init(); - ent = pc2nc[*data++]; - len--; - - hshift = 0; - for (fcode = (long)hsize; fcode < 65536L; fcode *= 2L) - hshift++; - - hshift = 8 - hshift; /* set hash code range bound */ - - hsize_reg = hsize; - cl_hash((count_int)hsize_reg); /* clear hash table */ - - output(ClearCode); - - while (len) { - c = pc2nc[*data++]; - len--; - in_count++; - - fcode = (long)(((long)c << maxbits) + ent); - i = (((int)c << hshift) ^ ent); /* xor hashing */ - - if (HashTabOf(i) == fcode) { - ent = CodeTabOf(i); - continue; - } - else if ((long)HashTabOf(i) < 0) { - /* empty slot */ - goto nomatch; - } - - disp = hsize_reg - i; /* secondary hash (after G. Knott) */ - - if (i == 0) - disp = 1; - -probe: - if ((i -= disp) < 0) - i += hsize_reg; - - if (HashTabOf(i) == fcode) { - ent = CodeTabOf(i); - continue; - } - - if ((long)HashTabOf(i) >= 0) - goto probe; - -nomatch: - output(ent); - out_count++; - ent = c; - - if (free_ent < maxmaxcode) { - CodeTabOf(i) = (unsigned short)free_ent++; /* code -> hashtable */ - HashTabOf(i) = fcode; - } - else { - cl_block(); - } - } - - /* Put out the final code */ - output(ent); - out_count++; - output(EOFCode); -} - -/***************************************************************** - * TAG( output ) - * - * Output the given code. - * Inputs: - * code: A n_bits-bit integer. If == -1, then EOF. This assumes - * that n_bits =< (long)wordsize - 1. - * Outputs: - * Outputs code to the file. - * Assumptions: - * Chars are 8 bits long. - * Algorithm: - * Maintain a BITS character long buffer (so that 8 codes will - * fit in it exactly). Use the VAX insv instruction to insert each - * code in turn. When the buffer fills up empty it and start over. - */ - -static unsigned long masks[] = {0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, - 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF}; - -static void -output(int code) -{ - cur_accum &= masks[cur_bits]; - - if (cur_bits > 0) - cur_accum |= (unsigned long)((long)code << cur_bits); - else - cur_accum = (unsigned long)code; - - cur_bits += n_bits; - - while (cur_bits >= 8) { - char_out((int)((unsigned int)cur_accum & 0xff)); - cur_accum >>= 8; - cur_bits -= 8; - } - - /* - * If the next entry is going to be too big for the code size, then - * increase it, if possible. - */ - if (free_ent > maxcode || clear_flg) { - if (clear_flg) { - maxcode = MAXCODE(n_bits = g_init_bits); - clear_flg = 0; - } - else { - n_bits++; - - if (n_bits == maxbits) - maxcode = maxmaxcode; - else - maxcode = MAXCODE(n_bits); - } - } - - if (code == EOFCode) { - /* At EOF, write the rest of the buffer */ - while (cur_bits > 0) { - char_out((int)((unsigned int)cur_accum & 0xff)); - cur_accum >>= 8; - cur_bits -= 8; - } - - flush_char(); - fflush(g_outfile); - -#ifdef FOO - if (ferror(g_outfile)) - FatalError("unable to write GIF file"); -#endif - } -} - -/********************************/ -static void -cl_block(void) /* table clear for block compress */ -{ - /* Clear out the hash table */ - cl_hash((count_int)hsize); - free_ent = ClearCode + 2; - clear_flg = 1; - output(ClearCode); -} - -/********************************/ -static void -cl_hash(count_int hashsize) /* reset code table */ -{ - count_int *htab_p = htab + hashsize; - long i, m1 = -1; - - i = hashsize - 16; - - do { /* might use Sys V memset(3) here */ - *(htab_p - 16) = m1; - *(htab_p - 15) = m1; - *(htab_p - 14) = m1; - *(htab_p - 13) = m1; - *(htab_p - 12) = m1; - *(htab_p - 11) = m1; - *(htab_p - 10) = m1; - *(htab_p - 9) = m1; - *(htab_p - 8) = m1; - *(htab_p - 7) = m1; - *(htab_p - 6) = m1; - *(htab_p - 5) = m1; - *(htab_p - 4) = m1; - *(htab_p - 3) = m1; - *(htab_p - 2) = m1; - *(htab_p - 1) = m1; - htab_p -= 16; - } while ((i -= 16) >= 0); - - for (i += 16; i > 0; i--) - *--htab_p = m1; -} - -/****************************************************************************** - * - * GIF Specific routines - * - ******************************************************************************/ - -/* - * Number of characters so far in this 'packet' - */ -static int a_count; - -/* - * Set up the 'byte output' routine - */ -static void -char_init(void) -{ - a_count = 0; -} - -/* - * Define the storage for the packet accumulator - */ -static char accum[256]; - -/* - * Add a character to the end of the current packet, and if it is 254 - * characters, flush the packet to disk. - */ -static void -char_out(int c) -{ - accum[a_count++] = (char)c; - - if (a_count >= 254) - flush_char(); -} - -/* - * Flush the packet to disk, and reset the accumulator - */ -static void -flush_char(void) -{ - if (a_count > 0) { - fputc(a_count, g_outfile); - fwrite(accum, (size_t)1, (size_t)a_count, g_outfile); - a_count = 0; - } -} diff --git a/hl/tools/gif2h5/testfiles/README b/hl/tools/gif2h5/testfiles/README deleted file mode 100644 index a428d479e66..00000000000 --- a/hl/tools/gif2h5/testfiles/README +++ /dev/null @@ -1,6 +0,0 @@ -ex_image2.h5 - Generated by hl/examples/ex_image2.c -5giftst.h5: - Generated by ../h52gifgentst.c -image1.gif: - To be determined. diff --git a/hl/tools/gif2h5/testfiles/ex_image2.h5 b/hl/tools/gif2h5/testfiles/ex_image2.h5 deleted file mode 100644 index a36df1b480f1f8e307b8996d56c1e3aa32c90079..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224533 zcmeFa2UOHqw*T90wzY#f+vZ5lITTe;fubmi3P6!5GANh>A}WX|B4Sn~qY{*yK@mj7 z9J*WEZtXBLcV_PUum7FlCGiWbG^xA#6fopTNd z`R*ToH20$qXiS*!!I%#|V|NFB{D1l}BVjaqYT)s}>mm9(AL?&2^|u#Cad$rafd2d7 zgW3A$r|3Wb?f3cm2m~MCodcggaI61kADE2c?hSm-!1E)w{~82@0#|SPOEvmG*F=AN zOD|{ohabcwghuIX!eTb+pI9FnuiLm$$31Umffv@tY}LgxnWVR@8u*95aQop0lezcm z1^h$(zxZ$z_rwwX^9K6cw;z9|m-nq>xnD5w{l|VVfqm|%QQQYjfQHaVjQ%iW0{6~q zPxT+k9!|ykY0z_1PH*s8FTeBkEks!-syY50Gf{(ZRlKqPhbfMVgV;D~+r z!6)qf?D=4oz(*mHdEs^Xccfwizthyn43B8&zYh1{1BI82|KSItKUk!HylTAu&M({y z{Od)W`S^u*y|xbz^_+h3jsKgxFd!G-(Z#|LayPh6HtgPqAACCGIw_Pq{RO7$^a=hS zxK7-46nXIl8Udd@&&k!m8{U@Jf#(M=hyH^G9*>5+(o-}Ga4&IJ@R#Lv(YJ4X1peg* zAN&@1rQe|cj1RnBJq5nLf+6xcnQ_4LL!@>1^7>1E&ujf5?U^w6duQRh4E;U>^7!Eg zA93GN|3yC>xK5+FCyvt}jqxLQ0}bKEFFikS{Zrz(cb?L}|5rGF$Ni?jLj$bnpZpfi z@76BpzwqC=`EX>65EvmaLSTfz2!Rm-BLqeWj1U+hFhXF2zzBg60wV-Q2#gRIAuvK< zgun=a5dtFwMhJ`$7$Go1V1&R3fe`{D1V#vq5EvmaLSTfz2!Rm-BLqeWj1U+hFhXF2 zzzBg60wV-Q2#gRIAuvKdPtCQleU>Ua4?{~P=gM~jtnJ{qAltScF) zlDe9FHf~t&{a1fed~9^M#$?un5z+ell8_J=8ygemFn8?Vf9t>eJK|!Zqhn$sM9W9i z@bAh(JYy9dC|EH1@4ok6{S65*QBl#cu~B~ZlgIq4v-o>||2oDhE;d57V8nI!JFt>s zB6X25aq+Pc*3(Dq`>(^=5ErS7&_&0^$7$AlI^sC|Dy+>3Q4!%0kumY{;m!-k|LR-+ zd#uj~_Q?G)`>!eaDuhSYj0! z9UmX;y70fFlQnAem~rDLPWt$>snci9o;z>e{Q2|d%$_;@vyUfD7&rQN#kFNaLS$$} zRCIJ~e3Z=Szn{edsEL!O%$T!q$tnXA3u`+EM<*u-I~xm=)k_!5nmTFxnBS4shU9gz z;i2%bV&h^1To;c2Z={8zMvt5L@$|WiSDV`N#NO(lu*lei^-0MaHf%^I0pg_DO&9UKuImzcC+ z)0VB>w`?%4O(GaLGU2H;pe4I{cGw+je{~chB z9{16wGZ(M5bP+29!=n?1VA{1Sb@%QxHd0fzZ-@=?bvIi+=d+2w$F~j+)kVif;QJ)T z$46`3R?PaZ4|Sk>lc&yGX5uVS21g|(ZQQhZ%hs*iwr$_OeFq5@(Mn6(vuDrVy?fG9 zwK3#@3Q?cN$6AhP^?>PPQA?C|ps3<-~k2-795ON`ek`Buwk{Fi#9 zqbGhgcZG#m6OoV%P$0Ew(}pBm$N2d8goMPzb!6O0(zfl`xodYC!P>WXPwLiqh11%( zpSid`GUlOY^6FyzA#!jSxm?v+<*pQSM9~T=F z6N70wj$jS4+6q`HptWc3zJ2@lrtR9GQ#c#UnDk!fM7730Fgz++7aAUy5Fe!#yV@Fm zKJmW@*60bJ&RJnE)`Z8AV*qhVh>MAe#E6QHiH%PnPJ=oL^Yt25dV2bvok`(x%O%r4 zdXH10TCLH-6^#lH)J4bW0wp{LD}$;3C62?WF_UI4HRtQ_h+Q1#QWMUp7h>qyuW`ya5QW}bYy@^<>#mHaCWdW`7fv#j{SJ9 zfjB6RNF}e2j|d403=9rI@RhhJB|ZD(`O-_5>l&L|+uAYOTAQ2dYpO1m7MwYjb1*X< z1`C39_r&P)(e^!d|Y6 zU!RtGrLn%I`ci4( z*%LX34(unnVz5#-`8h6|@_s}sBosb73STiXx?r`p)KlW&=4`)q*6-^#jF~vkSfGho zpOloe4y3gH0otIjsN@|Pxo0n2u5anM*4@+7OQWZUU|qX*wF|UJylO93lml08c2;I4 zM{Dn<5D$Zy?`1v=k06(wrsZf|u*y>?^bqiz%oa}iJz@sEl#PP^S$l=VuTNUPEw>W%ZTXy84F3#>R&Fy1JU`isG}!bM&+_ z(l%<1XT68;BPu37F)>OP83k5RVQP22n;Xy7Va@d4&tQ$8Wh{w6vL$IPDB1k#n%dghnk$#9E|#1- zs#nE*yQBHbKY8bp6&(|o09J5fqDcwe-FQ5ntE0iJ-;33#@$;-?p>gY>embpMsZ{xg zuit&7^h$FF(>(^Nq54AM>D>Lhw{J*{3J=!$LG;v`09dqmnk0`GlvPw;z6^o8P;}-P ze2GkW4?Ckh4c~eE5k;)1?iC#!85-d0!E?oMGMfECrjBc5rFy!rwl&pUDn5BQedmVg&;X^kr^rJ!lF(1FbT>8b0LE2q9&STIxwOR1?LI#B8D?Imy}R))Wm4o;Y3 zp^8OBye>+slzaQA!;<$GU1`1AL+1SY)pp3#xg-0w#s$blh$n2Ut*vNSvtfe)Yy^xa z^wzFV%Q;t8QCV4WspM>4HehA!*)Cf%<(--mgj-S3=qrkg4+Sc@x5y2w9M?>H=Z5ho z>W3#LE_TrZRbre@?IV-<1Sal1UD?J+^>lZ&H&hj$%-Rwi;O*{cXKiK427@&e*8nfR zr(evD+=B9oic1$t^N%sn+8Jaw_gzX>csMGlBwGmqKHl)#g>JA{w#z>G9sH|N<34xM zL?P1>6XqwE$$SGhX60XQy-ssqH_24#$*djm{$2v-K~jWEPwNfof;u|72s~A>I}e^N zy?F6rS>cHz2Q&BY-4f(9_Z>=BSXgLicm!E^joe!<_i~4Ecd=ObJM@8!8b8BPt&8JO zNoC5Aq{GFv?bn$z)!9;asUSNgF~mpUWM^$@L4y;l!Jiy6sN)b_^zx6{e()S|)81XuBrG%}I3z3r!Mwi@P>K0GSDv%M%y%ieKc{_oZrn6OjV>-eJ~m7v zmwNezZpgaO*wxe52Se4-bh-58f#fh>k&CSrM~dOn^WyGv519R8xFB3kJc(cIzGDSt z7s^ZWPvijB)-dCDm**u`$bFzV5vK6=7BTiBdf&|(Jy+WrtBdotN2|roHdcC4 z=H_}Dm#0wR zV!h&h<;sT0)#w@43SBHv1<1t`c~J84%2q-JpQ@qqe9q2rg@==k+Bwl#FQ@v4J}#3>UrE zl0*wOUJ{U;S5R77ayIv1dWvk>&nAoTw zg~UUsjNf0}3Q{+E;8j)R?@RO-JHb&HM5Pxhy~cqRiPLLRhTJeR0xu?oOtvWU5$kpx zEriiJaX53Q#^fDj2& zovXiolgv6C(ENkz0wm7NRB=+pS#^jQCs0FC4ak+AmZ6amM~gI(td^@ZcvIH7(vpHx zIq92}#vlLOH~CG^k;6c&qI4nQx*(z1>ILtAA=8*?hCWd-(Gfx3BB4aJ^>}sHO>!36 z>MPD?Zw-*R5GqEBnIO;_f@;7<4cwA|85tQG8ekY28X23Cfg{m^9`Yms>oU$27Z;q$ z-j}3U^G~li8ekP29TpZ5=4-NK=KC)WPFUy=91{~6q7i$Dd?F5BXuEN%ulHJeV^v|! zjtEYwfQmGV94A8chEVA-4S5c@I9djVBwL)>vPFz2RK^@QT~u6nJbPcV_ndz=tsER2 zL~@1NZWQX4VYZ8>yu0}67X*CNr)xcR_;mqtcXz3FQ$cgjty{g_a6wD+c18Oz1!OA6 zp&}U@f`vd0J{*|;@OIE5(SmRpn+%ASy`wW<8k=#dxTNsJp}kw|Xa19(Lr@S{0aZ*~ zTx3KxZQ>kc00H zLpZU!5I}CGG&eIbGB8-XcCDTkR2SW)PA;OrEjfiHMW=JpH}K~FbFhe2hz@y%xcHdJ zh{#a4B@=%^9NyW}6ITjDqoYIAUhV=}cxvI*zFY7XnrkoS?~PZx+YP|^8C0)1VII_b z3y?Cv;&c_X3_;7lz{r?;&dQd;>44-z1w{p?52xxJXZ=$Sd>~kbQX^!1LVUC?Qs-+v z^&NO3zs7acXXf&Vs7S4kSRhm<9jWQNb+h+cTYY6=?gp*c2`(t7fM#4CVTf5DKxIP4 zoYOZLa}yK2T|+jI$rdMCAjmvZz!Lkd&plUIa4K`V*7DO|`(}UdHLwZ^V`7znw7V`c zgum#Y6V$)=3qKq^$5|5@6|V6T3M8Sag&qC3`mT32UM@YcH(cgwV+p^CpqQB>fAFRT za;!`^;Q=zzT^!&@v`HTx(!tVn)81C1AMXc0riJa$el0!6}s{G$Ba zy_;?Si7K%+C?q@zsE8H>D>5=dW%befgf-@42Tiyx0wpYWQRLyvJ^i<@cQ#)sJ+UWF z!BPtp!kEHXkwy&_D(&nhT5 zlam@`^w~dbkHHF!_83&kK^J6HWRPge`^+GZn1v{E*%1@-l zDqLV}I8@BAGgJdQ2qch}wX0W=P#F!16g`c>g*C5X>5Ue%S#Z%{;GNw>%AI+DwI|AH z_CKmNfx%ej!cejPRjlaMg&KYKkAB*(K+?Z7YSJR#kchBAi9289mtEW2f4jS_zN$DI zVr5S{2dQEzNahL;ng76vkSU>BwR$ZabDAgF03^B{m^TL{%Mvz=)Q}83<>PG~UEDkZ zQ;!!G9^U0|{L$b4nm_vvup)C68yiE-z6o&AT2|xSZck$%tPuKW|MucjF0)baV ze%sCd+nr5U%FpbMlDm*=#Wc_q{sIlg0U$UoMr&5BTD67~Di$lk64}_$%!jwYIfZo^ zR7Abaf>&xn-akwhV2QNbj~5jj+NxRl4|+vG!OXOy2a_?i)MJG%zeY zSn1Ap_er?Wb?f#`xS>UPn*&8`66C~+W5vXZ3>RQCN_d8op%mKV)R!GSD;_OY#(j z#i_(9&}{lJKWo&GF`CxcjvM>yOGQUbnCloE78WQM@I?W;ntN~G>S?SlJ-Ihr>SR4& z*~zzjt%96jnHsMFs?`P%9t1U34t%L5Br<;erY+mHZQHaC309&-{uXDS$k>tRfbm+e zczmI6{E33IhqpV<`G<19Ls`*6UKsbNP`f$9O66m9?bvY`W5ZG%Unl%IABA=XBrd@9V6&aOOagHzh*{RgnB`mJQWgD|1t$H7i%FTtlw9v8koA zNUqkx%qFbguz6d`ZdwVDv1d!P#>2+Ugp3xGO0YJi$<kviY|5u5JQ%k$>8$!gDFo z<^RZB_}X4U2gzRHMkiSO>)z<7(H~7;WMJ*;E|$u?WnP{lbZx^ZBs1ftThp>VtVX$h&idAcohcPxWx8+OZ zYJY8jpBk$d0>ff9?nq1Dk81qJ2v27#QwED@(dSV<0%0^O9NIa9l~5M5|9nwawBtWg ziw@#^1}qYaLS_bzJESX8xb)ZbdDPg+vsPP@an<-E^u`JYt-nU&rwv0IjJ19%UDp0m z8!#$3a>H|SZBU@^ae36`UqyN6J$-jG{-Dn+?w z(i`eEtOw+a!nTufr^cdqq-CO`#LLJ3^5zFvVzkUstkC!eV1N}mM?$HKOGka*SYr-c zp)#ulKOae;Ea4j#7OWAw@nx}RZ}j)~HdhoJ-Wup?OFF|m296cHOwPSxtc+H#SWYSk zxiYnO6o^C~t^_jy_p9O?oRaguw{-Zj1~kF0VESFri3;QJa>^uqr(xxW6}Jxv$$vo>f3!{))F=pZZHF@*{)U%8gCGP8Dc zb91pp#7B-fhM}RcnKe(FoObZ=;r*L~JuJz4)f+q}Sn#n(u59dG+{K<^vA6C>>8ah? z)xW*2pbZX@FE#z*4r>g4F? zM9(*-Q2lB@6tw(VzuV~1ZwlzxS>}wD#BG38W7+A91O=7k2hA1Jy8*$XThp~GmoHxh zDyV9iS=rm$no}Zy8-xokr@4zVF+C^u@ZNZly#>o?(d;lFSn%krk!}!3yk(xAim3A? zC$~wa|7KW}li^q;V8rW)l}@m1^2CWh<2H<%w7^W@qt>X9|8>Qd608{RE>#9Xt}rJM zC|v~fk)$j_v;;}RQR64Ru_@=+*%o?Me6LuNtLqK$u3}^?$v2>aoRK0(`eCwW#q#Bt za*36xrM0y=(pZCo!7?y1vloZ%$<95TuJd%XfZ}p9sa~)cD_ci5kzC;|^->-xIF}i< z;*+2G3xCya1t5h?c?QT7B}Qo%l=hT!nI#uiQ(TbgbY+s^i?> zT3q#m!NRT|j8%Lr);(j9YKX()sZ)MZQXMs6nz2CUqwtZ5-MLP4v>w_yxO#Z0g9%ks zWJG9iU;q{*YO(e&R2Lb@TQX_v_$dpPEtoR6l4$HKCRgM$ct)J;>+iqbP;z`%gqW3@ z!D=8-9#lidi(|!EC-|Z)J2ePt@Q$GgKYVBQu_HS|g*NzSoM6GaW58^z~K3_aR!k$WYHkA5Hpnu9@YknFF?A%uF*y82l@#o0~ZFXy2Xw zo`#ZRDdD1@VKqduz-rm@)r=L~C1b7*ILL^l-&tPS*ex_Q_xRzhT32#8$Y7b7GFB$$ z#LCXaL*^ggr<6%I94pIDa{R3g-AYP~vY9?MHaY^+e?(N2ui2tGGY3V1Q{holjfCDZ zi3n@v&?f0hu%LseD7kz2!QkQF2CEcuZ?woORDJ$2WV?H7BVyuWqiC^=m#0K5 zk$NlC94j=F==?m)mn}DUb+cc^^;J?wExNt5a=x3pI`wM*og2+%$5Mu{B1rl%Xs*mn ziPcJEL?KJ$Bn-e>OC=p-l~=8VJzKF7*=2LS?%>g*nMpz<4u>eAu^D6Ka4e z*wl9GZeMHp@m=9UBpD!AZ-~_p9W-0Ja@n#KkQ*9+rI#y01(AYKtysQn=~8-!p_OE3 zc3#e2KQ|l3%EBB)GV(Og!e(RZB#^3+aGgc1B2noGZ;n8qCgVl102hZ8b$=Q`J z^pqp^K`jkUs9~r=_Qzl*l894A) zLN_-_NJa0x+g%l>(jp~qvtsk%Yb7*V4OT12BE6v%Ej=zy`IrJiuE6T^1q&7|UV+KdCL}dC?@)r=ffFpGX(-}mtQ_1t zRRLk}Zu}MMgujgt-y>2Ew>S25S^jcYB)i&7m~#`E2bm-T0{d5Iu##hbLVAzFwYQQh_<* z)lm~>ivvPJf@JP)0_nk~{=2=kg$EMlwu5~PW`mU(d>llBSXr1+@Vo+praSN=bB;VI z_kfJniY1>fm_Pq>nk>zIHo{_U4d5Z)#{%d9R<^bdJWr*6h%P!RSmhgZvf#`f?->Km z%r6sq{fbbHlnU}PvB>u6Fv0^Qmh+}h9+K-DJ=>BGz4O*$ABPxSXaHOTsaPoW@e9%E z!h*F*FL!5KvY;>`ti%Lb&H{;iAgD&r12NJl5Q(`NP8u_6?59qu;E-S+p&MVcy}Iw- z&4$wK4N9&$PqrOwNVJe`7{ZDKi%?+@Bm7S{Fi$iqQrFCy<%_^-!4gcCCLS@FdAYlF z@Yx6!GJceufLw8`{DQ)xqr?3bs;qP84@WNkmAvF@NcwvoYVw6b&=t(KxzU9vTvkp0 zWQcP$dV+zgNGK4g!;sy=7B9j6YG16L^9#l-5aO?t30*0YU4ujbjPF{|Lh{H4k(ZZ` zQjImqh!jyj2oKfbA9?cTel&W_1QS_cNQg=duOY7J+P(hPi$}NmJF>`0C1fDx)LTz5_-MgLDr*?(7*pQDsz)BB`>7d>NH#26^G>8k=1@$kgR8aB8 z!rW-ZB0VcZJHMT|N3)WZj--TCqhPEcR(9yNRcZo)p@bo7MO<#dxkJ3)QVJEQkg@aA zXu}{_F;Vax%@%$#e(dYq6B3ysm?yq0IGTcMl=1--GeB5qpi1a$ZL$^u1>XjwXe_0f z2>uKlWgDJQ>Mi&64~CP45vdEsGI>v<8RN!%W+4j-4wPdi^xApp_Jf{=!ps|f z78&z_G#}Y3y~P3zDiAUkfr%6pi$g^vFiT4_2-bpyBv*#kzMGF6J+vjjg(?*KEWSC` zQ-GD5#8>U74ULKl5AY4#f41PXcFoXP>@7KZ`ypQ$5a6#-D*X}Lz!-@w7f+cubnCl` z^Xw&vmEF9tLl0Q7U3wrUA=t6f$=rxY(F8?uR-Ou_+Ak%{vIIZ7IHn@P!Ba%iJ9; zjc76=pN9-A`l6VGF)xS(Y1ldyMxJd9is=x%0L$OoX5pks^Q?V>f;2LBozCmPpm#)M1hc@HCW|lZwne= zMY?Ta4ODhcd`}<5_5l>BD%G2g6cz3gEEwuZzAZ^_J_aj)e?PexBH%4{wVXc%JLe8* zP#QnaQX<8=UY>U#rJ4~VM}`IY`3UXI4B#^pC$g<<;xaLWlr4kHxRM%wFz~fa5mtCA z;b{%P@)Ma%ojlDzs11Z*^4#QG%KPv2G#2jj7uXG9MTD3t606s+SP_dOrB^`u)l9u? z%~vm7v}p12Rj^`qsx3LWhqjVjK?#{1G_$k;DtjkBG9^fRqgO6etxCu$EIO!IIsE0y zJcS>z@^Eo-wliBfcgiOp4c*vu)a2#PUQ#~xA@D-+5(W*XUFFHMF=0Jp)ObJWG*XGl za1G)%NEUn`Zmcmdwsa8qYD2<63mMapAT@u{r&AW&s{;}3yYWO(M|bR5>E^*Ww zED|QJPYtvfE5?l~r1UGuS;Ej;btZa*!PaEul0}P_kS}WN7_dF(NY>^6juk$Zc#>Gz zBOXK|#K#wNc$l9ma^LylF(r3sd-vpvBxoGQ>={OdKSLSV^+TF;%+Enm%WZ zSgZB(ap&=sTdv%{+tYA9S>Mdtz&bxk?-({t$cUC+Ot=Ip%c`Tf${q=L%eBif zwIIi3XlUlHOFMETW4+RuZRfy|22Z>VPO=w^l5Pp{rc2(fDg* zJS$W9bMvNs`o@~niHq&M?Bw+9kZTLQDjvQ};S!-C zR@8_^gM-CXa_})s6(HDIo35lp12oXk$jUo$|B;-u7;i^CD>w4+q{lzK*RmW~)_fYUDg?hHI^nm8*9kiiltp7NWIZHh+;3ia~0b8_!*n zcD291r#?I0$Hj`8&ImmDjTqc6A3ue~7;+qOfe^6US(_OwUxus=Ij1Jh+ARlOOv%L=S>;PYV=GL zO%*~{%7Jn{tCVEqNRj$+>-fM5vo^e9M@L6{$lVZF`cPzzftiz!mMX3U%gc1>q7_1= zpGG0zxp~FZ+_-zI^X&FOcUw|I0*}^VJA2q5Y>L7Sw1u!}Q*XZr9|m3{1`hT%=7y`t zPNLFdWMUzS*?suPfg}x|gUz4b&ARN8;+!y(VOOA?ycC#4{rr@k zE@=5Od}E8>QDYZ6$&|hxU|D9?4>xpU)EW{eD_D#i-_68qb*%?=V5G?*6B zWXtIx$BB}{Ok9A9>O3o{hHq?c@4qGUNY0)}nUj9|8NAyDsKCmRCzMEp?(Xj1NDBoi z)$y4nB`4x-hrJ5ZK_d6@QEG6Jg*+!aiZ@#nE!iCCi}rhYPK4$R; zu2(^-dkLHZi`^p2|rtr%-h>XrO~Lo(CuPx zICQ(rv7cB-Rcd1809KGHTsPPg7XL%4Ko1XLTp$IgKtrn7aIm#NRhaTilm#cJ9;^V% z$XYi9QZiB&uZHQA@)IGFpTK+Qfy6cv1iR zS=AjBG4)c*ErnKu%E2=qb6>ZLjv7CeG({!kIXl{!Q=yGm5h@H?u?P1G zjv$$gfkDU|?X59a5-gS(VDlldLVDNTAC49}AY~3n$qAKerBvYR>XUk*_x_#Mg54o} z@<-Xc3Y~UzLP{Ew3Jp7gMGDFUnRu~T5&o7bE(@D$N&igD>?J`PG7n|#Ns{yINUR`J zsLKHrad&VQh{QtF1o#qlU{Ij1G9sn0yeM6>c(}VPU8E~6zb8V&v4RQPISL2NDQPas$<24WEplH+R)Eu;)qs7hdB zXyGPTtGtCg7msLU8y@stIhy3}ELg^*lKGqq#z4A<+K=D+E~?&_TMs*1ZwvUIJ`ftp-E z0Wpb#lQXOz{z$#yLPj3H1->1(bO{%L3k?QIp^a1$x*;v=;J(eM(gPJo%E6IY2FR5o z^%Ri`^2N%4zyO7B$hPwr%W|TPhnpKUvcukBJh2>hNiG%GE&c3u>T1jud~XUZGM_P{5NXp6$8!ps(RjB4#g63u$(>hh(7y!hpdF5-jRH zW1%Q#qsV}gFHBnNAo5Sxot~MwCjpxl*pi*1DTh7+pTWe_Ss+A$7pPDw@C)$s@d?^| z?$U)*o1KPRpjd5!Fw5M=*brJEX+38jm%i4{){C6o#fYX+p%^*y-X zTe2@&?!xR6si6g?dQK=fTJ}t|$VkzL4>4Q#PUbdlityyr%*^zZ^?qU(pn^X^h6tU9jmy)VY@aNB3LKQ9sZCEXp}CqctE}4u~GecVK>&Dfg4LKv-Bi3AG8^_hlZ~ zw>{3^-N{ZbR3OE}ZmA?!uzHSe9u(37l|Y2KOf8oOZaP_Sc`>7RY}Mi@aQt4K_%Ph!(BDVezw` z8N4xjcVFF(z56o{q;HAz<>NiJER1k=<+-_`PX(-KhHxSkB-4)0ZJ1}3H?gX`RJc#} zM&Wqq#P`p| zpuJ^RA3W`EIiD7Y_HE{pGBbn^CI^Z6ZS>nYR)`q}q|3tAMIO37C4GM;`jBrU6Xo%%@!tsLfs|5=$hWo)U=!?KB=9a7EB7 z;_ZuiT-^Fi+jgex*t{+#KwxbGugt=9?dmn=uHI_3N+A>ST^t?7(ODHek00J_I=?MM zsxRtruvor_=6?)?EF@C64lLX;hZPj7A~x>alb*SM&$fg>Prfr^ZZhdEJdlDNCst(I z(cSF^R2~8WP+Y(ef^2I2)UQN!ZM&;`*cIP?UW4_P1(*N*5U-OBbIv=cK z;$j*?!h#z5?OeRTfx-lX9&8a>+c!d{_Gj$bnh=7W5FKG7h!kWBREQO+AbA~Vgy&eH z#~qsk`zRD(wfTHiW$EGI;huiFY{}>I=gpoqbHqUPn2y|8lSih$4YJ8v1`x%gE>b} zoIaOdP;ma->AVBGV&o1;HLqH>blGZacLgFVrH@o7aD~^ROg`3j`{Bdeb!Yd)DtW9g zS#Q39i-{Nm$AV`h4v^wh2E}Yi%{YLACw6a7LLr;yglJn&3dsa_M9BlJoLzW)vg~Mw zf{!H@d&zy|V6~;Ns;cZr#OJT$x;NzL?FWq2oH?_(F>B`ZDIZUurATAPe>8Qmjlxe0 z{f>Yk9v*(Mj zDI+#que@}jNA8gA=#y$vl*OIQ!6ny<20oURXpyAs?m!9$6%e*Q_u%FjQdW?oO71 zuCKS3EO2X4byfM%sNpV=Tef)Nym@ojn2Vo;Y}ORmuF2EqEj6%{scCV9pRdFjlaG~^ z`PyZlf4+F>vgNC&`X_)nLOLe^2RGq#+QjuZ$88&1cLkk0oO}FiL2(&&zrK8>rnauG zzMgGKUvy$mB;Ueh&GMzojU6RQKYu^9ueX$gI=u>hP&1Ka=YMUj#}7348a~*EbA~`s&gXyR`O{n_CH1 ztmLhdOVKI_{jqoQPB>K2^XTz|+uc|44{nQAdwI~38|aU_Sf&gJk6pic$L_uRv$AuJ z966G6Fe7#A`UtI3Cg!_Rj7`o3j}L1kqQPKswjGWGJTy|`;#2(Y&Y7+;s5?-ml+Q-Wi znG)m^?OeR0_7-35fAHX5Z~K*!6cZlUA~y7}K#P1&4i#k01N}X|zCKbmyn<88uUx)(GHLZNHv?I{xwK9-xCn|JKQ$x|m!9zTkW+0*ry{1n*UlN#n& z5&?V8GpB`o7IIo7V(J2B<_Q)Ggt&n_@IqlDp@kS;A*mN@E?+veVeK%FxG`L_Y~fr| zJZRrs2o|w|$(l8Lk%86i{nY?Tsmo4pB))#rU!Tb9CC-dHABIG$=sjBlCnq#&<&RdU7$K)J%2!3l}X~v~a+jJbYAW1>S%9n zBoo!x)Y8^@^*VO$#ddtX*E(7VA83{D4d$64c19g61Z}o{O1YN=LLlJ5F?Vp}`^M}( ziT&=c;oy?y`kKlMCFf6N@7)?7>gz?jHFJ<4NEkdGq)AT+#u@`w2pE`PK^66uYmgXx zV=9oK4;kI%5{Xy%zN*?Qmridn9_Eh8pG}=MeFg>?Vc^cJISZDc*0yvZ+Ao(ISvtDQ z5IZRqUP5P!)vT<91gEi$ND&Yg4R?GOChjB0PJ-0MDjfR5{e=x=(3@I2y1ILB-MRPR z(c>pi9zVL@f8$zP6RBiv{w}Q(+A$o&{vjxWY1Il6EWmQb0t0*WviL=(WF0?WT3%jK za3(i1byFNV!e!`KB{y7eePEZMaAc!pFxDu%(~lvnpoIgl28fA75-+(5jcU<4+O1kF z@ruZ(uDeokX6tYp)~3;z&W#x}XU&TY(MQiVppgXv%YUwnV&P zZoGDlktI*=7aE-imwaDlPTtA01*I3N>Y6*Rbzi^M-c(;#Q`gYk+Hv*zjazpfJbwD+ zSI;q?ef9L=og0uX2v+s!?J88{tzDIYXzE6DAX5F%Lh5ct*Sv!>^5LPe8@8vWrfl07 z7p_%#i>XirW5e`}(UHqhe)56$jX`&?pE_94>_+NECX3Nxob*2c$45;acZqQUK2p5w zrOUih4_4bur@c;azU_YweT**4d2`9Q!@SR%zYv`!+zM=C>a9Wx+G5}`cY=HFDR!r| z5*9{l3@w~Jaehc5)){9UJaXbp0VclM=FaY3?7ZGqf93KO*sPAL-Mu&a?>+kBt7l)o zc<~L57tg+Ubh8TwOEooCp4=?7Gqf>nuL@Kh-RB43+0 zvG@SB%(sTGuP@PJsF(^eQ^a5mp#>R}cmh>mSOU&~Oo9>;tEhuD#A>_QFj=7_wH)CPbwV36b7yZXhezKS zbb`g(5G~Yg5z>+W%}f%E68uOkL6;LI)sUfQMy!B}Q$R=+lPj{^dg$!FN_RX%^iVMtYbzQ}oZoPLNeL*ty;_GK$eDTGX z&t81{^3|&sUp?sSfIrb#o0llFGc$LR21L-oJpO=1?jwYV3L!}T02kxM_kc*Vl`S|H z2iA&lgZ?q?W9mmD1ye-|NQ1LqWWMx+>>2C2LhoZj(zevJJ-ZVFvHU|Ui#<|Dtag}B zAD#{}EVz`c=SF`yxfB_`GY&Insf~<6^QFcIec<{a4q24Jhy~#r%Ac+{KoXS+6pN_g(FQ3o+Ux)}iw$A|Rzw7i zXe4~>U?vUy)C(d!YB+;2i5oWW+?%mKV^f%~6s+QN>wgm~M3^jjG2r0BZ{uts1?6z| z2pCJ>S+L#Qcvyj>4UbLQzB}V!?&*Tkip!1d-Fx=&8c;%G$=xp4<2C-Ri0>D=ev~Yb8=R>#pr;-`$6gA3wZKYoG+d8lH+}?(Yi{YN2tucFcyNG9&KWJr4qr8|{ z>_LZ;veg)rzeCFfszIoEtuZvWp`I`?86u`*XkeiwYiQ&}(=%ihBN9WW)8Pqhq!62s zL|dw)9XNdCNP41H23Cp3!RpeP9mBQl`kF^ ziA28cL?g-7ux&e-V^C8yEr90+S`I?7>@tX!9r;s`g8}izS(AvAiB!g+yi@rlmuj2Z zyKg;sc)zdd%;~d5HJxzTn_2p$vF+N;ekf*7d);MBjCD;opbOsnt=o4WJp-)g4{i{w z`ilM0UiPL~0I#7HVYKOqQX%IiezMY1iHEB#myf0Tk*%|bmlE4TsO28cNcvN=1U7jx z#6BQA4~Yz`VQ~UF?R`LNw{Z^idO9T&gWV=?*syW)R-{7qq-P&HedhS?7$we5NjlZk z1XkNjhUqh`TemKe#*nK(o2+q*D5wvQR?3BhkZfaXo^{Eax9?8R%E>zeQ&rR4as4(> zb=TydI8#>F-qqRGSck&^p>wcdWbQi~sw*om*LC#vKY;Oi`uM^9M_+vX>id^p-S0un z*j!(jj!s2W3wsZ&whO>MD-<9wSBbd*Vu3TEqTDqk3kz5HQgsLxBnJ9=@*SgpQdZr!?d<7)Gj%F62c_FE6Xd;y2y+i#vfee%V#Z@>TUn=kKP zZ3nC?`RTE8I|~atZ2ACB@Rc}k32uOwRP5$xgN+urwj5GJ2REsjtrrebVZD@%1@%m< zU2AA!WskI@H&`L(2&qE;nvP*-1Ah)1bgDg$hfYPV_QZn5kHJ|B|qCh!!%%HBs0@3gM0k7oZaC8n zR;M-^43pJCHnOs^4zQzHGt&3%+q;Lz?PAn`jmGvJIQxAMOTB;;vYwY4TDz{_d;H|l z-O{|nN6)u*L8@x6VARklrZ|+cx3{OO>GGwD%Plt^zx?43fBfU0{`AK`{_zj5zWMsa ztM9-6?#2DyPMi_je5D{$=jCK+X6;1lsVT=Rp`4{e=;ma@${}#7P?e><<-iK(btP@y zvMGUJ30xddgCpOWc9)aLG3}rOKYm>j8KxaOQ`p!^SDpr*KsGYtz~Q_T=SnVID9nuY z@m6j;%UC53H-B{s<0Qt36UUDq%gf8nJ%Z}gp@Ug;f?qm;!@yb78JStgap$2VgXpiK zy0)dGyYK$frw^|eXJs8LYrBebrD`rCYh2ILd^lzJdQW$2O~s|krW;RQ0n(qi@y9>> z@ao%F-~aH#ch3k`TU$&0#q5n*p{=QzrL7C!4IPA32}RMA8gOXn^$aZp){gG-z=TaZ zQg&`i(BbGtl**h~;uy&*PZ{cv*!(jAc48}C*i?3)_<+)+?b)+;U&euhhmRaTbFQ$g zqN4ohMwO3dGqJjKV%@4?Zfa4)Mqyzgs#5vq&Yd}Z>f{MPJ4(pFj2ozz965>u&d;GJ zQ(jSB)6mj&{pS6rUp%^6mYsR5tg#D+wbUYLu4}@<-mpUyI(J`ftiE*da@YMAKY$fC zAXich=-nkB^wXLP0-xU<4hlGA{NV?n z`r(IHUq8Bat(^``uPZyYJI)7f48UPSK`45cSVtFyRje6cE!%R>&Q0nUxhXY$e@4p2 zxG+C&)=`YjzYs3Ud{kPjLq=7w}%npjuOv2kd<{X`*2P!lmZ2~@(Y(LFJG=Y zzb{0s-IhB3Bvs2!{;dQvB1Ten_Usup&YsObkLyv6+6+=tNOpGj z-hS}(t1oX~%1zHK0;-M%lB)W)?wd6GwKli3BYbYVa_PdwmU}OL90H2&{^3U&-+zlR zy0e35HC#HIiKZz!J`Zif`hcDK(WtouKj1@Qt%R#wAO)Lbb!6d4e_<2+bhJgOV+ zLf$SKod``jaEV)x{H?3KQVn3`r2tk0-NYy=E-AZEQFXZn{x=SWzt(f}_QNlqef7oV z!+ZB1ZviUUs_M(N?Y(y%JVe0?(Ox^^=a%XV7cO0W`sz)wB3PIafBfOQ7hl}H)(KWf zIpeEui&VPnH#WgWSgbXd^-QcrFE%<)1BBv(!gm$6G}T@>5<1*d z();z}_U&6Y`{Pg6uj3O1S!lj@v1pzSfQa#9a-hYfl=fl?Yw9GTjSD}Dc zs;aIucJ)7e`qfuo-n-t~1fm@sjg{r)6*r&1wpOp@i}??)UVL%88`lV71~B;}%Bh zKo%s4Ac4_wKss|4Edqr_C8f~5>KaO7Qh?7JI`7jZIA2gc>4>xtOo@oKBtsrt<}b#U-U>)FwbB z@VcfJR%5zSup=fRqqL>5ru2Yn_UnG)p(*2^+(*vxC5>;t{pRcEUw!%H(Sv(;Zr$j) z*40k=0$c=CtyWf!*2B+n-I=&|D`PeJJjQ&~ARQ;=#P zpn&U#Z`Ou9c3p8=V)B7f5Z4Q#=rgBpZ@sc_iz=z`rg(yg20I1? z>AZUF`i+|m)8i*kk>PxfZ0Gaam$FiGDq3NdYAP>Q)OYsXdrYr<{p{h5_NK;WT)n!B zC1q6)U;dO8xmxfYzJK-d`IEahuHrX9WUnFat}M*U*cwHLIm69_E?Q71NDCye`>`S@ zCV6*mSv^ii%Sw(wU57|f42VsrNdKswn{j|h5hzUBY%;n;{S=H6Fj1`%*PZ6xmWJ~E z8@6O$Y;LS6N|Oxt1hfD6+u#27pZ|#;fBV~i{LlaK@Bj8A^1M%>jd%NDzi#yQ;soKF zx4FUFRBlx?x|?I+KEHBkPYobxbu`yef{iFUpuOR_*QinN=hq#i4|R# z?_PcT>`{MD7rP$a*ROZO#1$ReyE!&kDMr(ojTOy{)X{Itld6%5O+8Z5)ZTRIWLgYP z?Uu2&6YM}4315A~=IyDdQ^MCIFYpYR@v@6F88J~JM!0sZtq>`YVzU_XvfFm%R)AGO ziu;g0^`Ge7&?o-i|L6byzy42P`k#RIpa1KB{pa8QT-^$Z&J^$S*Mc=2U%dP-*bH3T+|<)!6Stv&D|SaSWv^G7#3Q8R_=Las_K-Y22JnsA_Jwa(1)R zPqy0|3TViEh$bRC_(graD7-xR=EuMMAOHTBKmG9S^DiDhdiVh2A=Ry(J^P9V$<(tu z*XoLLcJ9nBYeQuihnp5(tnKK#_v9S6_I9Kh62QF#1d$_CU0QIAF;U5*`KBIA-%vd&-W?7P)oc4$+$$`{&) zEkzLiB_?6^+l}TK1YpNcp2;tOTV8p&ww`7eQf~bqMEXI`bhNizKCv(J%$4Sb%O}?l zdo94R;@Zv|{rAzEa+k)#FTeTW&;S0{KmXx7l=GfGfq_B==IiHA`)~B!zH_Iq{Yqi( zzTGL?Hf%do+S1+ChQqxJiYpqr`X7DyoS}O0_0zl8+fbs1qgGK;Sls=LWf&MNPN4KZ z|46J}z5Mp;r+032cXh(PUqc?}_U*oFtu+_&k7VrHye=vnr)^SiSA6pJ^rMCK*KXhG zt3J9t%3rC{keiO20z#UdsOM566Fewti$ko6LT)=uAc{#euF@bUlDtU$=;&yzIep;J z`P$}&>bw}!H^llN5Tn7?A{+PRt3UtsuYdm2_b*>Sn4W$8&CBQa zt~ZsDmvZ{hju@4Phj&ms%wp^H?lwAHF~6j$x%)m>-XdIIKDg1@M4>=kWocny%aiX& zt}q7UXATw;G++fS{OZ9i%(?`t8=l+UySI8eaJb&doXoWCn>QjQlniHlZ_c@jrW<$f z-|jfMGe)b%HYX9$Tt1EZPO>3Vro+b85SKx;tAMtBOvaDXwnmeGK*FbnwOV$Nkq@;O*7dRh1Q|4b0JvWqa=M-%jNQdQ@IB-_NJ!n*s*J0c0nb4l82A) zT`SuWrPXKxaYP0SlXs@2AIQ#y?jie8ehH2yf-7V=dN3pPQOAjX^!44KSqj{U8KkVU zv%Rh$_e5C(^4M7c%ZIxr?gmK}ee3TqzW@Haub)16@Z_66{N=BI`STxt{P9nJ`nqL< z{pxvBC!vXS+(+|GMWLJbXP+u>?d=7srpv{rPMj*NYP$`0feb%p$ZuYJ_3&m#GqJjS zq3C>Z*Hb7VivT&RMN$RpMX0`Gg7x*|0anO6!_R&6;O@<9%{7-w@{i}{WM>~eU0m7F zasAf)Cr|D+o!k_x)uKAGE_owbnbIh82OCAPOLbi%bx?p2Oz-V}$miXA_wLgcZoF{r_^}h`t2*w%_+y%6tiJjB%lqAJ zP4)F?*C{z)P)pXGvBD1$F&YqLToxLyzIpcGHjY(?dASa=`RK`0%)od1x?1Y0FP4@d zE7j{XTa%b;{e4~gcb2M^hx zd-p-?4tU+XL4jOXdqeS=!YVj6#XE$9NH(>ShZ_wSH_-IUU+IEw_=v2)eezd*;(lP6z6u&C4H8`QKqo58C3 zQc-?Eb~QAk3296BlTi^?l5*EhFcrRfvmM4q62FzwUBB2{_8G7%%2vO8~w=B6Q+4O97v%A^$_xIcjqfxPgTQ-}Y`+U#U zodFFq@4V+bU%$Wj?eBm8yI)GX6qo2%>lF8!2%WrY*@Lj~QoLd-4hojlr5Re>dY3dpp8|f|F#hdqhhO>7O(gjxZ@#!Z}(VzYd z%IbH&x!V#Te&xx>(4GURez4LfBD=f=c|VZ-9GHN-!q`w%3BjtW@BH1nH?Lg0bRESW zv|&#Sfin|OSlylV=IXjmd>;>B1)PY{e(gMpLSb7^PGb>WxJc82d}i{Y@$f1>D?Z(Y zVavJKEdY+DPbyXfWK(;>uME zR&+cCa9zK4`8oihe zJzXtzW^>)Zg*#t>R)kJC2u@$Xc>CZw?mRdNs8Cr04+r5M=ChOabQxP1t#huPpXjW} ziV6#XcbtH=S5#gLZj&7k`yD_6MuT0g4KLp~4vEl$DD8to=2ppp{v(3QI%UO9UbO8DXx#IQd482X)T zhU27)xT&_fs$t;ttTcXGvVM2@=Vmp~7k+ATev_`n4+;&rD(x zz9AukH21`(89=F4Qol<~0~q_`L%nT{HI*eO<<3Z(&C`)gR|08DFyxymvC5DchaED9 z6$-%s*0qZStIqD>F(gJp)$^ZIWIlfRgHM6dtl5B?pPT3U3ImLjl?}Lk@=2%zTWlvk(YU;^V8{;bnrw|7q zb}#}pr(kDKO^&viYiiA9rFG*s?%cXCb8Lu2PbW`e>;C}M0$5j1PYm_|tm=yL%7($K zcRmAqfz?MJLVaH)0a$n-P*W&WCSfu1Iq0t)@!2aEP95uOEXqubIT{fW85NhFYceuS%uXtL#QMmV9jC$ux`Ku zJvPuYI6gkoU$m7q|J%ccr5Y<+;BOAWC8^Ab-tH`X_m!tDlp??`S-v)=st*cf7AtrR zr)H*SrpMYFo0{s%N}G<~ymR9$N=4gSTUtAMQM-2T8Xa}Gd+XAPVN%QwZBklV(=&bb zBVtit1;R3bjX}r5W@8w@iEMxu&z>0XZ?CV&%Ore3t{8nz)_0B0oTm%N>A#0>CCaNwzk&#($bdcTOVFOb9|_y5vr-0=+u#!b0kLd(Vbfez7O_vw$z&|N=vKi zS_e;Fx`}Whd~%vZ;1Sd<4bjZR=s-8h{wqt13ZQ;cQ&1&9iUM+rD(c(&vGUHGJ$bCR zsUkls6fdoS6WM@5iIjPRpz>BXoEn}O1Tp$qd3 ze;HVvogNz)7)R2(BV4|G-l}~O<__-KvE6&q`qij4v={Mg-+SYgXRUd)^f`}|hM^g( z7dR0(uvx*rI(6#gWPevzJFsd$0jy3>47Al&nhK4^;xcn%&+ydQD+qhtxqbEQ6you1 zO|?~J*fJ}@kI@ODpNQfkTm96;*ic_rdvhJoEXvQ#&P+!+1<9zVXQCXgvK|}z#LVe4 zL>JeW8#9w)QP4q(bqpwXY3>9!&~Jbj!a>GyNudWttCXGoLwyM=SxuJD(t*b_Av&`zg9GD@V z+%z%;3Y=iDx_B9h3u3#U7$59wt0^h%IrG77npfu1{LIt@Xc6rWyD)jBeL=EAI@de4Jl{1}{x{dBC;oS%F&1Qn3MM-sA2o4|A8LovKU73&02 zO(+*@%h&yA{_1KGDX~WZGnx?n{87)h!^>U4dCh9f_G2&EmG)v8oPc|K78qT)3=f3Z z%jZr`40JbDnM(W4q6p;t)KFJlxiLF6AqM*p_Uwezf~t*0pt`rVEBPQjk}Vch;7d7<1A=sBoyAkkF$^Ip+33l&6v(Gkyz@fgMiv z2OPwMnT3i5>(Z%_){=zqK;jx5P04TUXX-G?zH;m81$4TMPaYrXGVPmhTR4N27rJz} zY~Jj1C@vu(CT!0}o$$REtpd4-fN=ZP6;!&95A;AuHK7&8Wv{zV7xmZ&(fBS+sPyt{UBZh=a}`#&qEd6Fj?m?s#uwWhKn^qT;qGn0hdc z&P|UGbT(I-^0U)uw2mA>L2GQ9v9@RW{8en&w{M}*i*ym9x&);XsFOef4;^9nBCtzc zy>#v*8V36s(&AxSq8=|gA~YyqKLUF(>4nWh({Stvp%}-G??H8Z63aUQ#vaGaoWD*V-j0WgOq8V;nyENWhVn{QVmX#D1HjJS>20PHz zOBc`~*we49d000l+TP7W)|zb(%F1@d2-&9j-G(1P6v3 zP0lhH(i0+s_U^yz?LCS!hS*9o#KF$X#-r$&35&7}od zDe=+Ry-4MBL{wr{N$b$e1%$ZZSQFFzBYOD|hvUkL-s`B@EG5(*!$$&-&C^2mfRx;ckkE{oR(i`%+0SIoIVXzLx1-qI&hYx7V0Yt(eF+iI>3d=4YA3Y z`K7h(sEJ2o;dw-z&d!YWkexFn9;MV-q+$d845?8;`*!&PDL?QVLr3DEATU;F2Z@uu8HCBt3{%~ssBHKeKM1%hcsLqbm z8KMKotrT`g5H@BPH}s86A_y@XoV$MY(&_23zV_OR;(SKaM;t-zHxdf5Xm}z;n-!In zW{e3yf6js6Y?6tk6X>_Eo(txKn;CQza|(O-91waiK}(`bD4Y1?6p zeleITDoRsA18~oYtsaV%KYV<#Rcd3&YugiZveQbs(2sQa{LFwUg@lx%qr>+4?g&cA z$xTZ_1ROp|WnF8}FdYE7iQwZUc!=%w@B&fNoCnv3wj`M50xZesgv>mo)vJJ0a|>+L z+Jd;iom;)odAenX|B>{{u~Urua)aKw=5#q(c}zI+SAgobB-exkfT1LcR4M(GS&CSO z3|1G0s#Ak#tn!*iPhUoT*xkF=&!3o_I6gBq)?KvKcAhhL<`DEfl8}^Ih|0pEI5?&8 zM}zlocN4sR-(6!KTd^%Y=V(M+HtEhN%R<;FKBKs_ywn)BcXwb~ZgxrxZGF-PRR&rp zPF{u*y?gum#S^1l_0T!|ZUwPF zGN+!TniESHi2CmygwF9!5*n z{==ruiF4PGJGuMerBf*Qnw}Z&Z3&lsO64adjY9qYbWB<>=4B>D9^C9Ke#iPgaZ8rjAIyjk4?Y}~kc9S=wCn;> z5ms%k%8w1$7n6~h936oGNN^yzAI#o;2M@;-wvL^>29NI6wKK;DI}vc93+BkO%WLb7{YTQuhfZD~iV6yS7Adfb(dSH{n=HcF1U8eI z#rYQmFz^bQf0|hzGmG%*WV0b`-=4jPVjD+JUA~1Cc>5Y+{HQWH-d~$0TR!h0_p^)8 zH##jdo5l*gDkY^Qg*hn^J3RHm*R72#7^D$Nv0*`h5wS@rsoD9=Dl*qp=ST0|AD5Yx zaP&y%;ozV^+___yAMUoZFTSL6@*0#fjAZl>cC<9n9R}6a)ud1!b@JVP$SI>7b+D(k zrXVdUXb&-{F#0RIX6PJQfA^Lj+5JGOxuRBFe1QUtIh2^BBhEBjNdEu)r=MdL&S5px zYzW`CXJ2qSS%M!BT3tjf148`6?L`6eoq9E=trjiviN>hc64VRj=b5msD#}fH$p^ew ztA$qn^CH}OSR0m_6cKPJ92q*Me6(G;5xrkJO% zfEr{W&XDTcR=QrEu9QdPLjNFY?htGn=xVGm#2?=0w{6?@o&HC28%F8fkL1pX+d>Xl zQ-JC-Vnbn*Bify)EX#2ZEkZU}4}@5ASb6PIjMf z<>Ni9wnV09=a_(1QBiqS6&fWf%1aaXZE#e+cmHaB>|M|3^u+Lx&`5MwlPp|enYpg6 zwz_1G&)%bXIVlK3$Dq3-IW8i=7k7WwyZL0dPGReT8;Jgh5yU=;Pu$ep(%y*%r?F$C z$`1Wb?X@TnJ+#}`$9LDk$l{Jk;+un1#F}Cb0u?!6HxVNg*&rw^Yp{UYEM5dZSXwY0 z=CGQm&kWn=AC%NENi;jMnCE9m?b6IhbC%!x^Q|Phht;Oglvm>70o7jEl!@Tj3};v6C_i1p5C zDwkM}YZT%iKi~i?ebLt0F9@T}&_b1lyg*4MnosI$ zOJnzL*&dOWosB3kx`hzuOpDvU3AYB4y6jHxynK^@bsgCN%pB_J!q`5NKS$}^6yEjm z;hyHo{MZoxoxV`(8P#KFkwUm1D&o%&Qyd4NLOUG|6$6bmWOL8Z7W}6leMqpnabd7B zIq1NlVJ}K0 z=+47gR7e_|zPyiFr~{z$|F;>tz1x%!7!YpkJ#pz4q1A;`_=0Apk9C(FlD|B^)~@@o zTfZ|rEuUajUR7OH0jz2onp+wQ0v%YaM}(ruJZV>-pg2QWmDx=C5&)Lj7`4H5-TtJ! z{M;O%MHT+||>V63a5G%F%t&(56( zWAdAhkp)QX&wI*>_`-CC3^mZ75~WU#*&-X%MKE~LXwlE(FoeE<_jG_UB0)Q7M=?tbz) zgA`qRL0eiVz?dz;V88-U1jR4D`1B*1R@bi#*QSRCMb?g;y@VJ2@FvQxP!u;c*i^Q4 z#n<$182CK59!fHnf+e68mS9CyLwo;Vf4eF8-Pe~{8}IkPUcB__7vGj|4ou9&G_{&K zqTfqG*Qw+#;h6;_GDO$||JxMuvLp zl2$=M)d5+7v?6ElqT`&XuKeV4QddqQ zFHD&V?1I^YwzuwsilNmFMBMAsk47YPPMt?Z`P~n$oF+?$!{@bmHg-LTl~+JY z5gM6+6)_kpkx3sI9T{pj3YIar>M}~W9onCv=x~$;=h*9S7!?$H?{Q{%X z^U<4LU6$bW-iz(I~$7hgC%joLJ*_F1e3 z+NyHn0`~a_$CY+XlL$3&m#q#G;sjQAX|;}4r_VkmYYrE4tfJ$7b67D;^HcN^0jlel zXIkT<;|m5+!;BtUgklJ-rpBAfBb{G*@WagW@y2bTS=a_?tjJ0vU=5)0sM+i7`(nut zzue--o?X5|>bfH=rJ$^;(iG?N{L{;%0r|ydv9+fhM3rGWzDG++#L_`@3L!Oi9VMcGYI3->;;7SdtKi(jAL}cg*|Z}f$5d5A zu!3V-YX-Y&x`svuJ9oeTfC~RsRaLk2j|}w$*xncLd+`6!j|p0DiPr2-G@4A= zL2o?0TS!P5)z~Q*O)`{~ZO9Wos1M41EWOaRlrTNjPbY(fQHwlYACu@_2 ziop&ggSTz~DKuX6l;`Ifdk|ef%<<;s(?Du^YNWF^H^^o_pUV0ZT3v4mPAx90L6t!@ zX`=>MHPux$orA;u;r#i%>f)u(za{lM6moDoJzjswbMLzZCZuPiB_G-C#(EBI1dl!T z#48-nj03URt#kTBZC!`7k$9?1X55{ zG*q8_g!M;Ah0)UkCB}SH+nFnX>O<685U3`{Ivb23GOO|fD-`B;xi!*IQeInM3zvn) ziqvM9+XsgGBlwRp+aK|wsOf&<)t{_<|1Bm53v*)S`dtBm0Xx>)z4-*Gj$Z<>c;4;j zNmK;&$E0%sS!`f+9K6bi2n;%sSkQKi@QPHwG8GC$zk^pKbqn22A`N#@uW$!5j_yB* z1xiQvkQSUn>g;Gsd9kT}=p5Ye+qbWy$S1C#tfKA_ScP%t zy|7W${p@qk&ZVoDJpTOqa(B-S?n;}Nmy(k2B}uo+$^EkvY)2&FaU znUO)k5lICtV`r~hu$oCpL2?r?(1`T_{bYU6dm?ceVO+pcAe_21)z@q;uWB1R zM_%xQ>*vtqJ~KH!*wvW6P59E+OL9E`m|t=+vQ;F+OH?~qgyw3(tG>XmQJ{+|c=T7y zz4GG6o_oVaWG}LLoo*xsSdYQw-dA&yB%O#&dKo<=AQov}sK`1R91@Y3*EoFo>OHI& zu;#G3O@;*HKN5~%Bc!pSRXkaHvp~%ub>Y-RPcvo*_Mof~`j6D_z*@j)uFl$=t^8N! zUmH62VXXh%onBg1ji4RDicwg=s$+1tXYY!qt$*+9T*JTq;j3@Gu^icc^4|dDV^1w} zP3pZ$EKN)tCCiW$i%t%AR2iZ|4o4)S-eBf3sih(HA+v=-G+D?Zr2QTetbh-67u}yk zUD4Vd_209<#BhofQ($x_%9MIfUAYM!qU?)6bsPme=8QeIFMKi&#vw| z4x@p=iUw=0HiTeBH2#Oo7IzaiJYzMGU@3GMQ|JNX6Q!c(r-pmbb=cH3cAk_Ippc!O zGBGha*j1b2!}&I9ou*1)cDcEx0r5?u+=+n&tF*3nxW7TW>|1^dR!js~OJ9}| z1kHokA2CX&QT<^|Kpjn7I#RIM;OD@aLyOc?(O{9%J(vR+!%0f#nMB2Gl?Mrc0w_#8 zA0O;S?^0{uBu3_v!i%dIn2U}s6gqbl9#p^aO(IrSp8=O4hVq(Pf>jNmVz4qd4UBXb z@g5zKx&MF9_YuH)cEv`+Njg1B!dX`@qDUSs^NpsIBjFLTsYY|xF|x(aGRp!M%^Oez z2f+&6xTx8p!+|6Oh&UB+B12tHqR(ppBY@BiL8b_z@Ch*>vdnRBf$sX;?b6rhf7|&l z{ZQdK<+XKV^}HB#vGl;oLX11;ql zk?37c$|-9aK=9-qSPWWpp&kPj!3wZkLK_%eJwrAk^03eN$q-S~Vpv^S6m6)Y7 zJUED{Q>b7@wI%sQ`sF7v;jX{A@Q5epxv!t#dc^07$^}+UO^x+)yfW9+507*kG*sp8CSLDAX*c8H#H<$4|_GH3t`6Hc5j8wMEt& zjTK|}Ll;eBt^?*Nk-6O?V-quHuiU^+KyMv{R1=uv)!S;=r~a;%NGz~wXlg<+H318% zy`~-$Y0CG$`3>?MUk%`rr(Tm69!Hr2wmA4Yq$zIt*g$J#T3mEA1}zwhsyl{IYfLKQ zh$_cHkivm0hF7$5njH#6Mh7rhO`rpD`Xn025&t5q54J8E70|nm3V^1O;lll;K`dND0?t4_X0ftDi|D8e=ZQy2{O^O%2Aw44Qo2`|b<|3%p2}Ic5xjScEHxD3i}L zKG0s8ofJog$7P~a0G*^$Xq_RUEass3#hl0!vjzf2EkJLPgS4{Jb&|k|Zu};%Iz2Il z3Y?Dm%tLGVuRZbIEs%tq5;KieV?B<#n!48B;f`>JdHT&39OiYg4-+EtFa_$tNh)sU*Pc-pCr*>s;+M$#KLBXb=cT7I8fsH+IRP5SpDtAOP*K8^k1hH z5llt2>4I28ZPmt%q$DyEG}BOkCgsk-@fp(6P0If1gFr+hMqe?mx+ersyfuKG?Trswzj^br>oB6jjvn9HP5%P_=#7YQ>JO_ zoY?Nf1e(MutT7odOBh&XVlG zJ_0if&7IXrd!22Ue^qW}p6~d+UrRC+SJa>x7g!;MT;JN=SsAi&p7%|=?}g^|V99f= ztreF^SP3o*R^eH!!qL9A+ER2`W{?T02KrWWKnr*LpsSimpAvn{qGtJreiEyYjEce9 zqi_F(kq|vy?G2^rA!|f$zxWL^TVMV`l5#NOAHz2ps2Vytt7F}k|GBKhm%rSf`^n?W z?L)>dlNAMG(dvEr80LaEl%sXmK&J8HzIiB6uCB*@J}`6#?UZzxEv=g@umL9W1kER? zdD2rnb!-%~b4mMVeQ|2YR_#w-e&#zdKkxfI$+#T?1}ZmV1)?~isk0%?NAS|O_Q>!1 z6ZbuM`faC*DU?ToSoA8S`G7{m8d3|7_RBmnx|rOYuePzhhcx_>i87Ya7PFl!WYIB$ zhe+QpJe(1?dWGXY} zh2r+BnAwKiuDi3N4KUHBPIY-+a`@hj3eGz(KRp*={5D_cqyKNZ5m?bFoa*YPwwkEW z;Dg)6uRrsh+9ePC<)_|TmokLDZ(@eSdxNh-++e^3KN$0OhX?w)TG2>OiYrKd7ieL? z8myX@mX_AmRt$w`ZAD)S4H7+}zrvKC5qof(n*;0hm!5t6JB=jW|IRZo8nD8Qx<_+m zU0aJ0WA{^HHwl)1`yk@|f5!UJ;%99(7o0>Yf(GjvadqJdpMWn6Zy1 zt*C78s!Po*EG;!9ZeV?vLD7fb@^iM^TTYQY3lnRCbwnItS{cy^eBg%Z!NX`KZzkZ( zLPdkcKt+&3VNWGWO!Cr6leXZ^7oYh)DMf#VY+zN{fG+Q8U_bzbB&-icJ7>Dr)A$On;&~tu&Zz! zb1*?IIx0oyqAgHi5Cl0;_yARgMM;JOj$+C()cOFX%ELJCXvf`otILgP;X6IV@4x!| zeJzjQ2{4a%k(}bv$_7j>Zt5B9smv{_!(bP*jK=${_`Wt?<~=NVS+c8Ol<9P(sYTD| zBb5#q(`PkDm5iOilcfBCsDBa$9S7AgZmzY#T$+bDx_aT;--nI<2&fjp6s>OQ!1VC( zV=X25)r}4GAd`$k((loBC+}nFE28arlekGCg1#gwMZ7vXmQK(2nH{Dx8=}HcK18eN zNvfdPB!-t_r>rf@Pd(z}DqZ=bA3XJ41wJ1IkkxY-(^=Ee-h^4%$IOMrwM~uYGT6@9 z5zg}+)NS=zU+Z$|OY9BBW0w#^ATcQt(q!Nwz>txBWW*tXXm-paG1d_d#YnY@vBBQ< zhRW>NL)+ZM@1vFd``!GkK9tc^)!5zA+&wlqT$)#0S6@|v{?U9x%*L0#PkWTSfhAA> z$T7Hd^zv*Bl#a8|Q5Gw=m?mH!0lT+eOBHXZiC_fA5>0HC83& zmhPtJzKN;s;=H1&vSRukRoSuL^Sud!)oXpt%Oy{}qwr0vokUu2HU!GVrDg#G&B(IE zK{$5dEXIm-)SC>6M-FaXtGDO8_oJ7d1Es!4)AON^Q&d{p+R@NDI62v5#6SQenYEOY zlNGyd`F9@vdFXF1e&%()`+?m0{z-K0-V5w85xm(YNmLfnrAWIrRpQ1t`+e3sEBGtl zeicAH{ueM4?t9P07~9)Y*D*YGygCojBg90=RI1FFzXVo`7CrIekHs4Ul8PHiu!1*_h9?WO0Rdi?v{rtgEu@}Ri94wg#K*yNZg zCkq4302TVR(xbL4o9_g8%S(NeizQFK@UBqjxidToITD0mdU2Zw(p^Y*HMR-Xz{(b}roA>8>WKRe5i2dv1fv$XIv-*t}O>Tlk6 zx%lyCUVQcK_iZ>rsY0W7amNiNw)$f1|KV`lv@<3;;&8wopLNa(q0L*%U%(ve|00;^ zw~T7^%JR0+vA#yADRi@8*cre|3D$q#HiHGQ#g9Gy)HBcj;Dr}oUbg(TAHDI`+dqD9 zg$?fEEU}m2-r=~fkbtw|$FDDY;hDd@g0j3v<|5xzT3XSMo7q&7=q)oyFDE-`zuot2 zi{AG(NSP##rAr@w{D~)@eCp|Eo~5ySW!duO%a^_U(hJW&bFc92zW?}_ePF=NDr-gt z+s!64wBbObRzY5NtS{>?X}H|~kx`FJ3UUd2OL06#W_{oP8~;U*4Eco>ofte^O78wy zfZOqum@q*o!t?F_QqAyR1je8FvpEH24ZUsVQcQe7lVmA|c_5*ZbwKsvU&mMZXWso^ z_Q(0An$`|;DW>BTVAc@EQy?Z&l(L<7|8$1G?0foa{cD94_06@+#7_)}C*|#xWUm+!S@?)|Eoe^{%^))Dlh;mW1*?Gq6}#Y^puuGI=;2A1RnumK~6Tos<5~M z^WrdVx4gV0Z#(bBg(dh1tPB~b5W^BQk?CjTC^kfE=}y2${PO?jPi5eiA2e22ftco8 zTxf{(TlIB@Pyc^}UkYwIgO*#=Je3lxigFY7Xv}zc z6*1ZgR?zGT8`ukq{mZ@~V3iA#0ay`Q6&%)l2R(^j_P74KKhN-r3}PZsWp7zI@9z2k z?w|bYzyBnR1Sh;I22{q}WYud6-p!YSNMlu0RE&Yeg#{UhSI%$P$Ctj`-}DcXaK9(8 zsu)libK{Vi|C|1_-|oXDCZ%Q*tVm^fW{B*&ZT9(gZ|$${e{u(U5`W^iD`Dt2uMwTHvVV8U%DgS4`G;-g~?D$;{-(;TopMCMav0uo>k>SVw z;rH57@;8E6Rz~~*-HQtm_W69B2fg*2WeZTv2dYJOHb44{Rff*%4gD4W(sNHN6!85O ze?1FtZ2^G=1QrljKwtrZ1q2olSU_L_fdvE>5LiH90f7Ys77$oKU;%*z1QrljKwtrZ z1q2olSU_L_fdvE>5LiH90f7Ys77$oKU;%*z1QrljKwtrZ1q2olSU_L_fdvE>5LiH9 z0f7Ys77$oKU;%*z1QrljKwtrZ1q2olSU_L_fdvE>5LiH90f7Ys77$oKU;%*z1Qrlj zKwtrZ1q2olSU_L_fdvE>5cp0Jps4@5i26T^ssFu%`d^Px|8ptzKOU$4^9kxdo}~W$ zDeB*zrvCLA>QB#7|MDF5&(Bl;^aJXTKcxQg1?nGOr2g;{_4hARzkh}L-7@O8%cQ_Iae)&4}i#Mphdz1S4Th!0qrhfVk^~H~=&)=m!dyo3`C)6kJQy;IOK3YlL zT}9oop+2;wZnLNl*wif!b(2fo;8EB4)HMNhRY+YCQJ2NkB?)y=N?ov{&f8Px9H_H0 z>WrK^t)NaRsgo+|gqoVsP}5p!N=HrVspF2+gcEhlnHqPY#$2gUH)_P48eUBec~FCE zsDZUq|2nE~J=N<;^=zQJH&R`jsLst)hZohpg=+JrTDMXy+o)zAs%bmb=u0*DQT02h zx}8+*E~;iXW!^(o@1?5tQI-Bw#eS;%09AI7Dh;4Y4pF8+syK)$3Z@D}DC1$OAe71v zqw>P3+#^&@1Z9Y%vX4?(QB-C$l@UXw$5Lr=RBAkxl0YRVQb|cvVltJGLdB<2acNX+ zIu(;aMQ2h`S=7;ND$+nj zD5v&UQ2v$FzA9>OHMPe~?XIDA)lxg_s2%l`UjyaaNNsPTe443kE!5Ul%Dau)(oT7G zP@6lcOsPHG`DL5Vd-kav!1GMk&`Z%4M8#K1MlBP>#nb z{UoKEqO{YLW`PNq#Ui&rm>Tjs!zonM_j(X+y)XRTQz4Qm_#ebk)_($r8 zf24l!Pt^1OOg;B6)U$u0p7~em>3^f1`giKd|Dc}uPwMgiK`s5C)MNjPTJpcC#s7y| z^nWRe&*MM@e6CQylL)vFsgMV;7ZH((I1h@D=OExh?D-rBb1lQ~(+?j$OSvpYBph3a zm~HbFBIMZcY=6RIzYpPaRtUH&g}hZFz70ewVngi29D4~D;vnV8?D#S}u2#m^Dfo^m zp|eKprWL#EB&+pO$QnlpWSw5LRwu+6vffd=!AY_~E!e6S?$(Hdb&_}|X^yLXg^NR@ zvt6%?Y|O=B%1L&{MSjjjbffq0Ki8=4s1=vAb`wh8u!aj6Qga}K8qR>4)2rchYuFuHc8iwN zpkvo+Y^$_3>kE!(8x6sdWTLKU}A#WpHgMG7J&H7!b86D=hwR;ij@s^OKYr6np! znNnD*7PRX`gN~x(j^b%Y@wl2ltQB@S+t;|tGhH1*w8BmHwtCSDr9|i;5ku@mLOX## z%I8b?9EhEe$A}c)xB$t%`noj%UZHE+$Dl6C89xA=7I4ekg@tvzBi#WrRp_9SH-OURlGkM7>Nt8mlm$n}l~ zHoEU$=i;}<)o+vMZvVX@aq%g6g~p1S^2YYshBn+-xVWGwIW{iPfB$ChEl!?moi=aq z+3dL+Vj(KHD#l0nb40afsWn$0rYQ4_HA}6D%JBAqvxsZUXAz28vs5gwg;v07e_ft)11UbPLgW9 zs8uiS)ryC;;^R8I8AsV^C&d|OtUkOEParu#j07Bf~yvynlus+wOl2t zQwch?qG3nzq#i_-OlXCpdMSun?Iurmkp*f*8y#$QVjGoIB$G-&RC}?=UPyD5Fq8Xr zi7MjIT&0OBv0*7Ve7)Fit-WloN*U>-&2V=sSnE-_$*XBsKyzTcIV`_0wjm>_Coz3I zHf3?9$p*Wy*F<2+OW&pa~F@xhA>JML}j=Ny4nfviGz@RPlzt%+VMCR!9xcD zG%9)iVUcp#5)O+IF&i3nRxD3iUx27W&Pr=V%CJ--WHCgwC{+-Z<|<{Gs5%G@WEKn6=zSaV5?5JS1%0Ji{kXcOr5Yu%P&`O>SU}|Ik#6S z9M(vWIm)J;m1i7PAL*Tbrg8o|oy)Iv&cAbX{-fUMPg=+SP&@t)x#mA*>VK7M{;1Ua zMx*&utGuC+pVdf4m0W01T9LA$O9@L=Y@$xpoK_8|S;GcV&02P)+7=qMM8kqcont8% z>eM38t`J7M7Ax5h=-3i9w?r!~RZA*WqDGYvD{EXY0ZUKlB{PopW6ts(H)VypGTB9b zKqK~)v2_x*+D@#rvr|Z=GO^e}EU*{xXB8>EZ({2t+o+HOT?!Ej*iffz0a2>fdX;EY z9#72W61{56f;ez^Dxug-BK2{w3sgJAIcYN79F6PNl>6+g@{cqHW#t~NNsaH0PZ^I$ z81)Zo+T@kJ#wpT6duWYz-#X_#p00bKRM)QF?&GsB^hk7ic2;IC?o^wVXH3s9#6`sf z`XBV(=Cj6YqsO+*KHE0!^x3$R%VAl#D&nyjuHuaCz#{enmPHtTf_@fZo_Uy}%rh1q zS|}=F*+4A+-TFezV~hAKX0NwU6fCufg{aK#?;z!<>^N!%4#QO^r4Zt*5h;)Jv6rlbC2t^RYJ{^ySRU+W$JUZ;mf{dcw2LezgyX@05Ie5_Mm(Kwvch=!G% zJ`I}@P_#!)q)W|e*Kk_Y>_!c%PGeiGVUc}bV`Ea=(u9OA1xq;$OA8dX5bJBu6~9Is z2^@x~)hc0&Mm(UC9@pES(A%BV*`0J&9CKH9d1%U3tKytxux&hKT&*2PV=qxTNC{W% z#4?xxG*>}a#=yf_BqT%yMIizqhivmgE>A#&&nJSd79tVwiP^y8F*bmd&5`j1jzZxk zJHZ~gC{$|~>m*Ncb5g3@@P!Rp^#lWcW>IV)nn5p58o|YeZ72r zz5F=z!O)e_s|;OnCKo)GMWj3%2)IP(#AR88d4{ok9zHX_Cgea>5)rU%7-9a`BhK{F zW)?Wkz|dNxA}+*E%(Iv99i##%RfUA3l(LClb>Qh_JiVMx3)fLb#9795k#iWjx~urm zvFdxM3^{S`R&ly$fjVtd zahuefIyJjS&8k$h%b*@rw%FXkK%<&lpyDu+uVg6?-8Dy?=tTm?lTe440i#wxX=wJNCA0+GJYilIo#5x>g&sR(Ak;)m^*OMYq+( z*?aZsEo;_q_T95*r~mHV2Y2oC-@a|yo$DDa1v&Q7wk) zjvWU?)!KomVi48BQmk}_r6MsQDg+dTaAApxcn~fvd?61a5D)7_;IP41 zdoJ5W%vmS4@wR8}RPgtyr9m#v(OdVX97<1$sEvyoI2w06IAUV&fnFb<`VDIeJah@` zv|&)HZpuBbs-3PnKPSDnMz>C`an`xGJFane_k_5)c{;E5bXvFB&1=g#zpWd0LcBM# z=mTtpX0_M=M72Wu%?X@wE3w6b60len!NUihvHS=Z%ulUFE)$&OUA<7Bq!4uq@4N^X@-*x+mjy*lBnIO(jq;H9B^^p|pYW#4Zm3IiW=%tx679+Nk8#skt?3 zPNkXy|DEVk!crR$HBZHXfQq?FE(Ek>#GvFDE^Bj0AV$Yzs0XPZL2*V#G3 zHy|}UFFUC-J#8u>_1uw|vq6U^_w4KS+F0qKPg$)FbyMtjk?(O*?QqulI_kElwQJ>S zSDDU9irEcdPgT3Qnkkd(^=;-rgqNepRlFU83Yw>BLPs$$+!$n3EjF zDgss?xM)6i*8W&vhi-4jvq z8dTg`4Yyj&Emw2k!au-L3sLV;RLRLwaOZ@Vsp4g+1UYI!p`)-=FKEz-yY5%bv}avu*Tz+tqgbjS8uso9mI?!I?28qhTaB?`&GuwV0&K zVNquf9va!QrPj?c%}E*TqS))G*riwb>9t!mdM}ORdX>{^7tal=w`}(G+p>A5_r@KY zH~4MZOx0j=r zavkk>&JKLg)mb5AA_MLk>3X$flS<^R5coOpcS~784%{R5oH%<{sslSu&MQ{(%hiG! z6~9$0>PFZKJG+zYqKona7uDxZ>R;;N>8pRI)Beg)`>~Viyrcc7PSBy{B1YPv<<@J+ zE)QnbD>)Ec)Tw#Z3O1}?#1=|a9JuiCmGYIgxhh+FXJ!O3AbJA;zjT5HQYsQj~QnPPCsRjg(?%3VB&Bx^7 zcEnY;SF7?>sl3&?&004vkImaR@7%pRG&nduDl#K3EHNT5I%I#ufgOi-Y}v8iXPfiR zZH{|*gOU@dy%g>66TchHFr4=f6sgeU57%at(50+xP2T=`5mW8F6 zau!&cuHb;8=}L$oRVheQ2{Sa(Os!p(PFn2ZQ08RU=%VO#*NnO8#$2?c9?pZC*7on+ z-Vy3wn-F453`vX&3JTx1&41fk?=>E4wX5BfPI^0yQmm8-?CrT?F_u>;3WArz@4B3HG{&udduSezlNrnq?ARCdu=`axRG zwdmxNq0wW9j&vUguGzjL$$MMq#?1j6wghbQJFsnkkbh)kSW4oNti*((%+!+Xg#6^l zjOehWQ2!(Qw(Z-r)m!i9t=i?IwO%qn7P0+F!r&W5d*wOR1se(5 zDc{jf;OroBk%?X95-j}H3cIyR>3X?zqfFvuC-jkW_elANq}(GCcDx-g(}9;K=bIFK zaMi39)oH|_E4=J}?6!{fXPjhL9A&qiHFsP!AGql*yQx9o9=)hu$F0_K%{m^=*y5{H zoH^lDsY#rcuvEc?0SxcSilVmJ3JBXm(KHz+RnAFM@KcBgQ&gfb zo>(r0{jb{Lw>2gvE+?zNpPQ9tHt=!mb$}$^LOH8+u07?Z8gZ6&=p;2- zeuaixq2)keh?c>-R}n2*q2!jSxFrfUbSYShcqu%3Xi;Xn&yw3fXqK|lSdXZiYzCE$wO1>s;F^MwYuwjJluLbJ-U6pIs*J!lS1kXqAM#? z3aU~wN|Iu7qJm-rb_e-x+~)4N*?ILkjgy;9<0zFY`4T&}K(vZx=_)SIhRa#S<=||? zxFO zZ0t?17|3fHDQX)mZtFBQHRjgUWY(0YR20OQXD3(ZWHlO1eU;_?Ri^H;oW{KLs_2}mEkH;q>S9JPQNZuEhGn@8PYOzeSoOe zw1h>01!8SiFid8YssmpzM^vFw1Q95Ne29_=S1lj{x@tvyorFhJt5l@77dtvgoMciL z2PsIq+Fra?!uPfl?vU~i+VR8ec=0kphC-055*k&)GL5uMEulqJtr0cqC7pUH(gExl(mj^#fl{`oZbg7(Eq~PT%h+jWzj?#)W zLuSiJs*D9mk+G9x+$0&F5LGEoR7+EI4ylgHOlM7&tGaNtw#Zdk>7s7*aB5rc(dO;h z?(f?Yd7vTpXjMg0NmFKSV`hdqHK8#6NJ?lx#J=tOHhAsuSi4#8b@4XU3Bv4>087v=ds~l;q8f_~dZ7%Gu&h9MA?lc$oN)_ z4M0dcx5YE6)k0JY10T3x6s+Y*%kNthuSK=aa+UVf7@{)d1WP$Kt1QnjEVXDue`>mGC?z0&fX#my{Q1 z&xvs0Cc%+W@pF`dVl~OF<6Nv3m*~WmI&qy|-0UcZ)e3$NIm!B+y0LlSz6OD_9V0_hiQ>Eaem^xOwu~pcA7-8Hyq-mMVj=k{xUl9XJrMG*KY}OOv$r zDSAb^vpUO7XK>T!yK9Xusxnu7?OOL%uMMp`x3wSM*OVGoZHh0gPc3LOWVL3c)}k8Rids{onDuIZ#N+Mn1v|6xzze_~Q-i+et{3=6XjmcPBnNw4q*IZUM zRMT*#x&3N)^M&q~i+!z^`kT&ol}**=3>Ief<>d_+^9S;c0|j|qhP3*Wq>9+1`C)sb zd_8wKt?`t4dP+8UN-QkJ#cbw`ww@Wf&Yl_l&m;vn*awK634$?P1qnev3l+cY!a`A- zm8&4kui+IQNmPseWLU~xwbFu^g{Z{kH`)F z8c^5?92^7=GNDW+l-moCDbNd9?gI8Ep^cx&_JEWX;=qYiaAW0&4heIVq8zm_S0l{V zfUbffwE$7pas>|w_XeG`UT;^Uvx6yHsuIGcHK`EVnl(gWi!xz+l2lS~=}n(!kQ0`| zwP!5S6d5Z?&PtToCdeTyBpu>pNIh_qR6gHIy z-o1SLCi8)v=7@tenGxoSq~eD3f{ttuHMu=Au^}zKDlx_weIzSnf5PtF(Z1UcZ{ECr z-CAE)mknBto4ryig8Pqj2}=7=cOe8zSJ|L`57j0@8zv;qFc#-o5!rGeU?zmmo)rO$ zC$`~{G8LMrYUlSi?X(Yy^Gr7G&#pL{$|7Egl2v@?nM!cN_g=l(!A-Dir5UU4&m{m5bW=V{ThtvU!#X%g) z#)gHxg=@p%t)kC199(m4SrCSb#8czgKs)0HjPGd)kr7LPw&7<3Q*iV?W{3K3T>GY+P(su3Nd%%VvcSchxQl+h4&CQuCv={6q~eLo3M95v7XwYO$PGWY57F zgfwXdB|4!=PwKBo5tN)=Cg+#Qghg^eF5;hRewvz>qUJ)fGy*&{s07(~9??-bm+|gn z9asq(5f;T^dmChOiO4zeYGJ&b2WKB{evYf!;GxZ2qf1|>&s^(d^l&TLw7z)H*8I?2 zhWLOCLuh7MTvlyLPD`etH9M!xU}(!tYtD+RPYJ7v4K9l~kbiJj`VOBM@2y8RB^ZPy%*@lMRypI04`V-C-)kIZd3YG{kh?uf`AimjN= zs6A0&o+>CkW+)g;&FYCy?~F_Bh)wTENNtNxZAnO~iHkNxgk=XEh}*OE(B?JUoZUAl z9o)Vz5pyGA`pV5q>4s_x-UA#hKM=@xeStLr)z8Ncx(t$@yGVtIQVD6bNT-$f^rI&Q&;qC+Kd3;d zA5=f90IEqYvdD$tpRAgPoKj1GQt(^7L~IcWokBsdC@?}Qj8jXKab+egFVf4a^wK$c z1(e*EGMeSIdL^M+Nh%lPkQ4Ep%|)zYv0e#UqL(iRvn5raWfb_Z0;1e{Rz8=J&t+xv zSY@NmSG}kBhyv^slBU^|q!O1@(#j%InvaW17#XM-7nQ?5g7PV=Z8i~$Y;?1Oo$uBI zs9>tg9JbYAUT8lxS7y}DFPgowa?aM-^?Mo{TNVJNOIsF$7VK`Cy{*1{)6D$!6=^H8 z6BZ^#*TqE7h>EFrn`Sz;@KUk&2W8u}r|fDgq^b`6<-|D*WqK4f?%?B%2 zo|v=#)ciFk8dm-`chR94jjdI6dn@bqR@d*Xt>05yw`=z7%`>W2lou~3$eNKJofGMf zv02_>{DG*i2<%5xtC53zgC8*aq2P&C@uT4WacCc_{Q3LSS7C+`K!t`d zL<&Dl73!~mok)jF_t`LKf zQc5w8s74IECx3Gv#!*0UfEK)&`Oc<>YrK+Ua8c8l8DI}$pq+%|unNJ~$DD7fG18SyJ5EV4)RPz{h zqaNBu>O}_aQloYWqgqPK7wMGEIvMmm=jkMkw5*YqG?6mM^nIbJ2q>LH31`vb8d_Yd zQ&v&Ra#CJK$t(0qP&q9FQ=QFd8}wMSgd-ei^b0&jh*4MCZRpXx20lsOZn_Qm9zI$&)!u%XUEK$8>=gqmle(bUq^+i znhvr*LgMdGKsU`Vjh5#VgaDlU9G#LtRUm$*P6N$i1@wS^4*C0I0B98Ry<)in1Op53 zn**-kioCT#yF;i@31v`J{znpsY~kGh5$MXr3b|OR_$g?bz^o3u@C{`U-%Irkarq~= z;j9M_1VmYw3qquN6edsPdT8t83V79HkkLa7z`HAe>SL8Z`awV`)BylggIZ=$%G^>} zm{1WFAdj3b3ki@r1>m$Yol*=g&8mbpxgbm~Op=PyWx{M+o=eKhDfLVWnMYzxB;HJ- z3kal1hc&WTqXC}>GNO$J6go%H<4f_1ZIuc$;xvQ#nd)3UXH8txi%a;`w z%+E=$O^M9)dSb0+E6&gg92EhXerXYfU%)2_LscMub_@wJFI3G-!fANPX%Q@apvKw#{jCG)@f z1|a!+6X4{~A*Hm?b>fGk{CvV>6wLCO2qnl&s^Ha#D}Y;8%gbNz_v7lTsVa18CCH#r zT2xApLKQC2#0b>UfvQk}(j|czUPU314x6jTAS;JzJZK(^H?U}fLDgVX&ST-+m%~U280kV>x(JgtBjP4h zJRfEW2=QzRyi`=F6Y-$p(i%nJT#S!M%eCTSt*F+3%rv62&BRU61tOn*Jad`kLnuZ4k z;?o0>fIv+^fHE*ZCJ;cj3-ukL7%DsP%1b1YfZ*E@%}RcqrV<5e6(S4~8I0QS7)wS` zWWmgYvIXhI%_-%}(yP{GS8mKLU7uC9A-i&GZq1H@s%?3dTl1^76;$smow2)o#_r16 zot4#F%4;@NR<0>4T~e6en3XmoF)}yU6K6J=Q5_-2G(ta|2&x33m-EY8 z5W^=;3kVrZ4m4xZ`KY83lfc9abe(2Vl3H3)t>fR!(~6qal5KADp6HNfJywe=>MZ0O zCq2VT)HtYGmu{w;ne8^z1)G7=#yD4Hc2Iedx2_~=ae4fj@|3N$*?Z=fwk)sNys~D^ z`q~xSW-r}6cj4~3#_hA}HdWWJsc2kUv|w>zM0@|5D$>4mG)3fHEWY{)3znqRUh zr+8y_*_MK;9VIopDynx>RBx@Q*icrvzM_0pN#Ww$oOv0kwF%*QK>(`J1W6xUG8O*h zlSdR+gZzjBr6iOYNra(LzgQ9l83xryo)HHxMxE3m+Ct!;h(>{Net;h*Aoe+~bG$XpLWX zAF<%8d@#WC%!dI`BV`b%KKY9Ls7jBiSwsVa#6}FUV5kj892hU?Pr=lRe|Xh`iS4+= zj*DEl*o%l_ zH9tlIqLlMUMFSzPhkhs_gTm}AN;aF8gP@@RO;Q*tSf&(jqp_QL8SS&HTVunTp-<}4 z&-Sq8cB;fp7Y8#XA#6n`TN`d_h;htG3o0%SDys@_u87@Kns_ij^>l8=#lqZ6WrgSF zRGw_AIk;-p&P{VRY@NG&>#T(vs+-nUELvK!WJ$@wWhL`hlr*d?nX|IAW<^ouvZA7< z?A*Ha%*wcg+>oevYj6;0Gb)UPSPyBYQUbXulvXryA>0C%$pazJg$x2l=n;vS5Q%jH zu|7a-o+dU12rODDT%wE!(Zxoal2RO*`61br5jis=^Xg(V>moB6BlDKT6|PDy0If*@ zP)j%G7H-TbT%TRCsi1OOS@n*psx6h}8!JlJmX@!rC|yxfurM#XAvI-2Y*@bA9dCpw z1v90FWAulM`Vi$QB{YDjpHj+4DNAF1=_w3kB!38SWeAwd4|-m?|H&sz5xM(1-FN3VkRL3}*uN@b5HJsFgzO6ym0|9#Z2*WFABkf{1yc zA}=Nm#)T0`V5U}7f=FhO>LwOnZDKdtOj{k+tuD*95XX9#X^DyCQADNlP`GuagzmsX zO504MO%$?#)PfpF%^ZktX?2b6hv5BOQr(EF7b5BvYULVXz!8T0G_z)6&5BD|sjF>l zlasBo5k)R4Cxp%l)#XI!3M1Hx81tM&S6xPMZE;9rMfkSTxRbdFHxm;dhsAY-#CCY& zJ`|QetFF2`ulCZCS%0jYb7B+TzPz|0S z#$_acRUq@fMUYyWLVxN9qB`6F2_i#+%q-;-e2IgMI?SxYOf>4l35fCuT$j{BkCGP# zjPc@uK{PPI>lc*VLC_?EV;w5bAil7mf!h;&2IouS6z~UVOrrZuvOijLMG2Ms`e_d128WGfJp&BAA`Cd9ZR-c_>$xXB6CYlQqOfyqm zi*v%3r@D?7#NR8->WGeiNxC|v=I;_)ztYvOkN)V0dl#Gjwy@-NZEeTgneFptKWVP} zdsfByIhB9aSDl(y_51v)!wV`~o2y%zt2WOm+B~yhLv_xYf|TVcG4sPcvu(y1dZwJ9 zGUci?g(_L8gsQT2`mZj9)U8$8)H1V5Vp2*W6}7+(6tT!Dm4+blXqzS}lE_FjWTu&O z3q9qvG35>Mg>$3x>Lc^!#}qA&FIkaXx;mwNZCd5}jEap}C2Mj@*AL9Cwbg5Cs#aH*E-uNRpOf2=kzJRTToVJ18kA@X3TDHc2Ctp{e<&p>L`P$c4u@Be zUWbE#QX|V#3bN>FKd5H*2de<;f6GK`jTB;}G$v95borg_r@!&U`hWpk{h;!b=Lpa0 ze}U@13eAJ6Bb5FX6L4h@ywqo;3ZV2KP=B!MW)Lvd{|43fqZI(^Px(GLDkGt`V@ju7 z93hkBphy{k&mhTpX5(BFQ*UD%?D__qZn49#F37e$*tH|by3&NgeYy<>WUCR|rc-Z1 zrJ${}0;W@73We{bn$^3kNQ(tIWFt;^%)dL`N35;tEAp0FRJ#>QXG?;WiQVQ zs?2cAPIazH^_-oZXKe=K)coSZS#lH-X ze-V@NEG4@=J@0XLL0ew&y`qvkWo5T2Dz8^n-m0B>vwFtOis~E1#Wmz+U-5)bgj|r>QLnjOkROVYLudR3h5>_dYZC6u|#&eW8YZq zcM$b$3O}P!UI}tuNsV9SU>3zXz&~>mjajMY^1`4wg&}pBj-{ENqgm0f(^7iEV!l~J zdILAA42>*&E;Us3l*#Q6nr_29wZ^-(>>*d9y#S9|gocj~8* z^p9a#-4VI(!*V-AbKVE%y!T{(^yGgFDe4O?9f+)$$e#B#wf0SX*@MWun=yG;(@XY* z#+OJ{@qvL+N=YQ431PGbLP}sl#-Mb0@Q5IFas-l|$YiCPip#@hH>S^8lwG+Xt!hzr z`NH&)g=r-VQ!5swL#e7}S$55`oH?s28aB>q-ZF3Tw&oQ(m#y8qX5GH^Yxb;PzGKDw zb&WNPtBdOMq3xSc84aKYr&_&{#;9;hbh!Ozj0)BYpwc=F5Y@A!K~I59|0VySZ#7VU z`Ej)vaGRc&%Sbs5xI>TGSrkU-tu%lNM=;L}2;RVPY=T1>!bl3@L#_W%hLiojS>qEi`|V)XB(!PoMZVK@5Dfe}L+sU^E(jkne~3ejLOMECo{Q zX$@S*fX_|{ri>B?%qN+@!jsy=)89vAyp2e`?hM+jQLKU)RGng-L4D9d|Lw3oGTLr3 z>`?>SV$s6#9JuU%m{A|msedzQj+>BUR`{lTCnelP3ieTgRzh$H2{@=0oWRl3IDH1w zokpp%wBfSD^>Mp6Wc1AKO-*{V6l?e z{itoy5IRD+2TjEklU#3+hd5-3VOVC8u`t(DTbs0CNy+@>6*CtW*DNlsU0MpNSzHKphM9{B>sOR7 zSX;AtXY;0gt9KsSyyxil1IJsAo;q~o5PV1^GeM(<(iqhVHhL*1#}-nMQTM9omtQ-RVhus}E^I z%_joIEh^zAOt72?SWOFIRn7%7{g7d9QRGoZyVs!E&#DeGs$;D74fw6z9hSL`;}0?FxzYT}?db>&f-88J+{T+>uKVHc zCr(EPYj~yAy;h@7HL@qT?6z8bht!T`B_~S=U2+~fi%9;nckUf@9fU^4p*n$-RlbNF}cBJ`%v4U#yX<3Ole#k;pOm% zNg`^3j2a_j#;N!TCUH`qGGR=gG-r>SbH_}1W2XEuW8tU?R19x8TM=i-;vD&tK}Fx3 zSs#LP-^Q1;rD;##+6=xXBhy2)-Ra9qON&m-P$cncI{n%>_p2Se;zt_;l%k1r!HRl>++Qg zmo8m8d-m*+-;eItw`1|zMb+~wvS*~nm4c%Nc{3crF@~^cV??a=XC2jFp7JMC5S{)! z`oUCzQjpc4<7J{jK&joNvzsZ9(?qz;BoC?)a~UwFUh85tknixfK4D#nPrM&eeqZH5 z{dp++1IVAg$`9c2Udr1k4=OGNP{B^kw8F-~eP@NsXQx2vKcE7uJg9C;VAL<*?kVKS#336ib?EIkgC5hWeY0VK}dJwQh0NiQ2t@yN2X80-4h+4t7xGlyO6;Bi136?amhr&?Y}<> z=}kTI!oqZ$3_Xm#htzdx&<=&79oN3J8#=>XuY;}a4E|W9c&$)%p=i5O@Pd}#ko|HS zQ~srq975&Svf}>8i(3+DoF8Lsh+r0m(EDRu_j8ipW~Ow8hV`1AJvz%z)j2oW|yM2wP=Q*<21By+}e&XhY& zrH|{f#+aO8HgA|M7|<1br}Ms3*_@+foK7A$q;Z~tad$y~aQ>Hw!q>3{T_trFlXKQM zTxA3nua!bo#A{GRx`>1jeMx%wg4%-Bi|e*-UcRSg>-Ifc*KAt1ddtQwExYy{KCtJ& z-W@GF_w3#I`|%?eFZ_Ay`uY2JF1Ovg)pqapqdRxn?%uzD^X|ZVz>$a|& zvuIZStlXrs*vJBJM2;sk(HfCti%hirY)HWya97?}eHBzl{Qb!kpGN7yMRhhK1L7$) z>v&2{I=J2la$6`~X2NB{-9`}VF(7U|q&aGMb?8+fSWyC`0knXt-|PN~A)#0VrpjOG z1z+Wb$pKNnU{TM1gX*_aKr|RaQ#kZlDQ~K@66B^8E=mrL3hO5P9V@71!Qb@-s0xNw zvN{#q81fLxLX~{C(|I;5;xuFWQ;A$qsLv_oCso20)qi&2ziy=evxffHI{M#Rm|u61 z(|4fLw;;l8m~;ms*{zWr#FQsl;twNrj71<5634r z81-3*JX?>JhC8a$;}*@V*ture!JXTW9cn#s;>58Nr}iKI?a0Z$PW*NGuM0QMU%GMW z;*IN9Znxce{Nl;8w;kyX`kF-#mT#G$0MP1K@5# zdR0nXX=H3+Xk1QkTy{`GR*)7^{v&9i^8G33OhL^bim1RUl&AQ@6b~xpM-(XaiSkiO zI<34sHo|Qsd6@~fiS&u~7#WX|25w>fqtn0>YtyNKRag(@H&sZ$q4WgFIMe~4+vRH< zK=Dcr0$gca;Y;~dMoML(Vegq1ZskL=&+j_(vFZoarBnJdDHo}B;7Z8oEvUi>MJ-GY ztv8yKQ?wkK#jH+lU=*Raq>)B1#K&HXi9UoO`{kmeDsiiPdaL@^{X{^kQMAu0*=Y&f zW(e30qJP~&{JIUcQIU#0gkldWJ4k6x7^#zH@(8PKr4>NwK2mmoQk*g4S6uqbX6jE& z@+Ug&Iwk0!W$(0-ZxYdvNIWVK4+jPgNkrcj;x8IWHzIkb6}{C6->3yIHPc^`qPwbp zJ!2HNQQ=iwdXdrorbq7QC7sKR-t9H)_vmk@#B^t-bcJ|7vz8&f1J3<-1pS1h?&|PM zwB{5dIirzX#WbB(+b71{N0>%&+XQYOL#<b_RgijJN9GSpT zsT`ZdF}WO5FwPVXvqgjY;z72w-%vDQ%9#kt=ORk`U0Gd*q|t~{E_)uAQ8$!O`7Noc zD{IE{qM28Vs`h7OE{%(t6&Lm5Z0IUA=Yn>fKA1?%ur7e(Og2 z{Tm%m?!0=@_Wr}OkKM07e|`74r}IN!_lJS*?%wwwzP;)G`ugLi7hUh$-`>A*|H8S8 zt*!f(uUT5tSd}*;E2TU!sU#+?Bs#4qDy<;Gzp4c~o=|4TP%VyW{DQU=&nm5D7*wyv zjYiyTCP6kEYqRNWHp*cmoes?9MBOgTM{WTZ1~GoI(&r_?wslC8aupQpbu3>{lZ>E!`md zD<|%xQ@;m=BU{)4DLfLm6AOS)a|b?cHx;mt6}9Sx2Wa5|Jm3&AeLp%K{=jxrxC0aI zp=1!L9x%Wq6x9K}5*GEe(vpLeUeVDDF*u^(eb7%SlV#%OxX>aXkYGnD!_LVlE#A14(zTyp%^zbLAboNowI%y6WGlfi=yqqa~l8qRn!l&pM4o-GUE~n2KB{K(!%mF%o#8f(I zujZUJoTr-el#hm#^>~XrgK|K_F_m2Ad@g=YuQ_`#qM|#Y>Pl?>#qybp;^LN<e%+1)>?8uWpwqVC(|77b+sWxIl;98}hK-RY zXvs-j^ampN9pw|H-Gpctypm$r&(o?`wi@KEtPFObL8gC{5}z|8S8VtNM)@ZuK92}* zqT;)#I+Byy94wLbLL4R3?og|fq25z;_1vCu zGp_JNPFbndwx+uD_^PHmM|OAKzt;2i`RA?=AG^PP`Ox?EZU4}_(eXE9+`CEc!zA}* zitC%48lIXM8=o8*W+ z=?|GcluzZsj1)kn$UuS?=_o!NHK1yvRs-`VaK#V!hpVPeOyyNd;>3Z4GRZ;$-(@!L zCKNkV)3z%Ay$cWAO$m8Wv0rvj0lUZm*c^3KFFm1`pVG!=6I?>9l`x zI6fMUUl{#oqY)OhwV9aP2KpkcIYGz{VWL(-bbu5ez=W_O6+nGqH@{}tZk>MEVCQVX z1A6NKYacZRO|o<=S`#{|8_rbE$Yja2Gm4Han)~GFp27Belb_y?_4bSn zj*j+E4tyCO|HyHmPaOA^Fosv!)4rhI^6AN-;xpmv;)a{)! zXU~lCwI#XD>4`IN0jl?{gCmWi>jBtu~+OtA1+@vKOcg3JLG1a$%1`@Lm=0Of&5P^6z`ve?3wCPlw`P9hzy+DcNIM4pw}d zRy}}~*IMaiL~(=Ew!>yNw;gbOX=EPL*h3b-qsOl5H1Hw%oe&@K{Z>aw=>bgu{HphD z>{FZZg@Ns4P5lI>=#)2n)|hE3T|s+}OBx z@v>7(S6*7W?8=gb=jYd-m{GZ}D1SqC+Tz66S>eG29!Ij%8f7-P8QMUi7(Z&ocTpuE z-!vBtalvOq2|meCVnESI39XF8!HAu##HIHY{2Az?@^yY+TS{vu;I_W6bbxCxQiD=j z99mI0-=U6C$}3T9wa(N+TlZnqep0cY62sXIy(HMV2d27*3~bejTCiyciNN0}@t?Hp z0wujn%5G4K8?^c|gPhf=PZRQ!s08!}CO+-c8B}~#uZ3-smoeD|Wxy3R9Qx9`TJbZD z_?24tMk9U8Cry$rtr#fnm5T=Dk|DXMPcHnT2z;yh^{M7RKeo~l>9Ww$0x@L@d--G zFYw2u=P1>6mUv)fo*4~LV*Tm}8VZW|!k8hx?K8N>?ctmwdeRa#W{e&;#*ed!d=1K+ z#~1lMKqi1%&DknAQwis(<$`O*ZH0r5yvc~NsmRj)knApN;%i&{+o&vVA!NGd-I&@?cv5Jxk+w(XmVnRn;hgg5P0bb$Bj*K6XQQ99Ro_i zQ32FpZeWP(9|lc+@9+Qk>HYJL$Ma6FoWF7V;`Mvi&R#or;`~X-q4<4S zu*%gpW)GnHFHFIeH$SVs06?YFY4`wu)i_L;+l&R-Ft3vga}r^0GSo$Ro%#@$Jti_C zFS~a3tj&v-{;_8Lt@T^lH*9&ieqG0^<&PFMUvHduZtkq#t14Owa@S;}&ySC(j0nqi zJEKi{hmK-M0wYlkL>*eKR-;7`L<4a$MaTeDqfTUDMOH>+W5ss8#BNZ)qJEnJ;X7gs z;i3r_L0D0gMYOQ2UW>vED-3BVfK^xsW>g5{G1V-Cezn!QnPInRG%chYKm|MH_e1i_ zOGU5_8WxzhV$+Y|f>VU}94@_tORf>J+l1mSrMaooULiFXapeU75|drT}i`s-8muaDK!+SCDUS|P*?k0>Ru`XxH#jo0zeroUw*Z8w)DsBCEN? z857}!AFT=f5xHHVsl92%+_DW*P0PR3HC{|i+3j}ymX&^IaZ~S^liaf>+_$gX@Gv(v zIX*hYpYY@SIS&TQQ#w8|IWfkKkMMR1uVbUUhDU+bslK6!-oDYVJ$)ZOK;`OH`-5js z?!0(*_w~yMuiiX<@&5VU_J^16T!&KL4SXWVnkCcQT<4W2nO!ADLQ^S65fJXZh;O8@6?9-ScV3zVF+2_iWkr zdHu%D)$3lYTK#z0@*7P}f7R6=t*PE#QoKAPbyidaKgn&kdM!qm(coYhCrw*Pf+cYR zem6MxjkMIvLUu2*=*4D(+-%gq=1+r>)Ejkrz1~b3t+d6;!fs8c#p*KJoQ%y1oe85& z4{cK?p~!$ade}cRs2GZ?%v>O@{#WF8c3B_;kpm9wO84Yo!6uy>BtL*=>())^@AomEHNlV(T`TzMAZVuF#2)nDLn+C&Hds?9E#5AiOhHx6yKAO+u@0R6_NBZ zBI!YN(z(>Mt8;2U?AycLyUTs-;=cECLy$F1j!$r-libJz2l><3*u?1Q=-BA+#K<5w zHpGFWLJYuz3Y7LueC-{DlEE{N+t!_*HgA8ke&gfSYi_Mr@psdLtXM%A<6KSyN zjb5uQE;uALIyNUUxga$)KQ$#QJux{WDl*Yw&ap9dq4pI~uB9$&iCzhtc3KRIL#+Ie zo`0my5xwj<43p5}BWS?yr~uOTiWv!? zN*D`D9)rk_BlAAKPux}X!1}@*4LnfSD^`K?(G}y^G9Hh<0dD3$rGIU zquk^unCZmm#P~3z{F5UC9N;<%`P2wEI5^(ZGu-{Tzq9l6ix=G;Pv1X%*!{AtxBJCt zezk*Q>a2`mjA?b#UhCrm4MvSUOh)M{8H}EASJCK#@Da5Qp zVCDoI6+jKQ|@roO3x4ql4e`xm+ZvSsw>oM-Y zaqhseiTy`M_aE-xd*I8y*6yv_JJxS_uz2x>xwDU!m2A&SUlAWOKgv5RDx@Ylq#`1y zz->!3GH!m1izEyT#>XB8t-(wHrIbNO7!5j$P45h|gy)2(&q^tc{jweYJ-_+2FeN(V#%gM#TJf`Ab*II0-(DToB#DFZtczdlm_@<=o7AtAU$2Hc!wsHdrbzX-uO zLi{(SxS~@*dIdqk(_qJ|DDR^n$0de1&k%QQrk6JBTdVnl!`TxY_T3xVa#s+JS_cVRQi>S%!8TfH z4YOepb}Z6?M>};fZgaT96B&}2o-(_7#;)e2*H>+RyK&Fp&O=kJfavesp%dKUliZP$ z+~E@whmVgOJ~p^-|K}Y$->qBM4&m#Z*=Nd&4`rusOHEjp6uBfRVnKY^?1`yT z3^VBMdcBdN2t5qOnDs^zqi0x?!5rlFMn$A%WY(9Jt*M*2xq0Ts)wLV8)vnoHykJ*S z`GM%%$upU z?=12Sk$e*W`c3%jh*ZeQrBf2|kU%h|kPT|&J&3Xkk-bz4AFBc$siuRA-XsFAk%2s` zgy1eN0#m)O72bmw0GHp@N*~ckXRxC)EaaKXcH6+5R0<$KJwpflMFpNE1JB}u^O)cw zA%W8CHJ#?B0R!)S9vS?=YlnXBIU{+?W`w`^%3*;X>*rAK*RaUX!4V%l5nqC0h9fdY z!m~z0v&X!-6W)9-w3rJmn+h%e?#desE9K&LA>X3y-{x4Y-+<*C;%$3K3Y92p!LgJ_ipb?_fhryv{{ z8Jrv&oEjaR81A1K_|6Ru0IP!^KYn`ttneBK}^O`R%TmO9BuHJ2}WBY%bI{5n(P({BoU2vkf0pL|mYcLAJAPwo%<}lic@f@9k2A|`ieOn6rls^0 z>(m=utRX~ah%q~gBID~)OV^dI-d(f%@a&djGj{w@vEh8t%8RM>=fesvSQGBL;_lkL zmuTHdL;>0HF>7h zdNk5rsSw(xV-m@PL^2|h^ooREv{q%$HDZ`WX;TK?R|nok1vd#HPu~h#@;`BeZQ4+8N~e8Xfu6Y`&51%%N`vEjGPY?CjP5%+dhoYNu+yU_xnrleJp~B z$f{23C5Opr2a#V6YNs92PWw$8aKaatULvK}DEUJcdBUO{Eb^Q|_?Qz{zd&Sw;zOC> zfiw_afz>yJ2KamfC$d%wx+nSNw(wstWb)Pke@k&sGySIQUmq=Kznz-2F%uLzAQgT8 z73NZe<8sw^sqC{{_Fe^cD(O&)o+w0*<-&)Gz=x;^j{C=ixSf(h%^#Zn&sjC-0V4X~ zGITo3ceILER!e_O9ArjqdIo;gze({WLIk?#(*<0778gOy>Y`3{&4S+zGTaF^U9nN; zj3_*U>W+)?oxXf@iY+-1QWCIo6e@I+CV z0D(CW7!!rz5ZEW?6TF8z9ctcG;o^xNgNZ(m83{3|y=E0W2PeWt#<;B!Zf|U4R$lJH zS#?L7SKe8%_1%U&-}W3D-gkKP;E~D0!0K<@k>gYF3h!GFjqhz8+0`6^|P})ib$VoB^@x@q!v8_s5H_JRQ3W_ zyuuVOQ8@q%Nz-F_z*DXG2{cSqzus2<@&FgM>7q(F}^DLn7(0 zTs4fKU$xq|YDI@q0+c?HOP(sEPZi>KnDRZYd`l?blB(B~;uWm`<~wvsNU3@vT_edc z4@u-cNqh(nd2X@6D^$#G5b`US1R7X>6Z}~KA2hI8Ums0&Nw2`)OizWmfCj^x% z*yRq@tvhx@Td@6!*WKoEK6E;txPm^$B=sg_O=OgCSydD9#eKo){qFRMpjJ+l~C-2Z+D;$v1lZ zm*ekewR2mWR$g1V<>iK5 zpZ6RX*>_<4z`@CbN4P^rK~n%NXy1X+mi@!K_V(@A)4O%&*9}{`SFeA!V%5tPD>|B* zZ`aN_Us`nxo}rmvv^hI-NlxO->cpzL$ebm?i93Vh&VQ)D;AI$Bz>`UK{ieG0h!Zbw`h0GilEBl;C8>xgGs!bz#tQPTSx<XgI+GZsCECFyUK5-cREk%W{-%N{#kQNA`Ennv}+Xnd$Me2R#8s;3@6 zIEu-xAmS^8^a>@v#P`u;XK*p!_GJ|3^{R7v)nBX(Iv4PrOGX4rTi0yNyeOn_`PK2xB1O?=G5*h&stlPQ=StAO`qg&YeP}y(bX$noIBUk);{_1Gv6K^ z8;1fa*eRq^9H0sXRj61&6?JN0Y!cc4{u=8D=j#oOeeeGE;n}CRZG*ipxN-1O&|8k{ z8Xf!8H_-L1w=>jDdtDUYTKd5%3MGBO6?*Gnt^eT4uf65(@{=gsQZX7y2pHT}G{~y* zS`^_HWw=cXMJlh&66Hx20+2-z&CstlQDGt7T|U%UJ8aiPi&C2M%%v4^167 zG!EK(U}(?&fn9sQ?`-MazW3Xgh^xbi{c(i`=QFE%VVSwDC0 zg6a)R^A~JLt=SiqeI_LFt~>g*-P^6VLr43)PWMtzK`ZBhgSz3QE?VK)psGuH<=Y7R zD;x8aLfa8_2c~T&kq5Zu8m2f;$j(x-bEFL3Kr!kPD!QTxyrK$#iqJi^=)PL;2r?bD z2ppAnPQLV{enzXFlgek99Qf=&ATAX>Q466y|4=<0j(bRm0MYw8(G7gsdDZ{9Mg-i@ zOo#ZhORF5CD2`@1lpa>2pQOq+QrT0f^obl|RP{TY_(;;dI6b67MilA+h4QOX4mH@9 zDu`XD-&Ie$uAFwCR*vN)z7KOnV_X+iNM0N#}T_zQ9=%1sZ zQ6>75k@9>pQh0xw6#PYs&r%XF)jxGA7z4QGGTaKb-SAj$x$O5muI}XYFUc7rStVTI z3^3K=jr9)ozU}++e0=CFH}PR=;@#Bb8}QZ1sV^g=pNED%MFcTn z9$lzY$NQ=k+M^i6pTH{2e?k}lSDau-p1&YZ@b@>NLS$ZPbv;EzwtuIz>ZCkzZ=DIa!w=6!qw_)3^jM>NH zOD=d*?>M4544(Ho+h@x7nbviDZ(Zb9!m(5nv3IV%j^Nnm>UO{n>WiF$#fA9VB= zlko$~KEv?4TJ>!s4o};;Zp5Gg3RN8_?_WfO7gfNj;HH`{-9OYy+O;xBpq}xPyf>gP zDJAd;dWB0t&$L2dsT~vCQU3de@;~=*0Ziy!)%dgQWhrTDc5J|n`1sNjm? zKj&rt8c2)&93Og@CEziaH%ao9+x^KK^4eyGc;Gq$0f6iZE{CK4EWtAg|JCR9;G)8l z*z`Z3#7YU_1c3pt-%#-%I^_i`aoNdUw(GCi4L2R;&g8@o2}$46a;6F@r*g~t7b`8a#_=;DRL^$k4*rISU~Tvg*>a`CIEjG+a~x#Pzl9^A2O z{rn_&v}p+L4P$bX!#6FM`~3X5fhSLgUcckML%no-656Q~|A0Ed2LUh$&^OiFH}QRx z8vs_vCcaONL)~=%Dp3o=n8%KI9ole*1{C4MqdcZ? zmpdjb1tz9u%xY;`dTIIkC+oI$?b$KZvVC;-wuxQaCwA=QcD8W4_H(-qPHf*lxE=ad zd%pmsE&F>8?C(Fcf9U^G_8v}cty%WyAMswjH#5KK>D$*PD;|X-=_m(85+HJr5IN_Z zgUQZ0;hexZ;((29Yz)R=FxljsbIzQ%kLkJHucv3KrfT0)LgrRMv9!M()>_~Fd#l$= zRxjO|J#(%1{MF_=w`yNpd-o#0=y_0LnYH%2sY91UH6$<}7AS{=ias%fd{7|i5eT|W zrC%}THxPp;_+@mXE(^t|rTK(RF(s6aW1>;MXh0zB!mt)Tw?T>lD;~bHQ6>3qDf}Ry zy=KEgiu3_BfyL-o7P%HNZloHwP))iJYCnrICSmn+OuFd%dlCInuE`ii9zgZmkv}&g zf39czxt95t8piJswG6#_mO%r{=o?MH0U<_A&<(++2@-ER!=RgK)Q=dAGAL6lWQxI< zpdw>rWSq>Lp|DoTj8zlroC#@~N}gmje81xGo2?(AE z3ttM4SP6^36H@T>+y!0eLQq0mK;-(P$K}NrbC1M%MXD`ac`7w0Cfx1znS$>xpUkv2 z=5l@Ru!fK}Ly0#>0{0%ksNp7+T4e^r!70H_=@ zInjLCm=Qp=w*-`;u=IDaRsc|49eoI(rrpUq{PD<{=Cch*2 z%ye8NpTwkN9MK>LgLK-;<1}Dsi$YW-V13~;VJ}%{C4mdXUxO}>Yw`v)2CP=G$+b*! zBLed%>Hv!|49s}}GRPwjuz+WxKg=|M?Pm|;_g3W3&7A$;IltF%^x&+oL_59!k9Lp%#g^_Gzv_v zAf0xx3|ct`O$Ws&kqN&GSU@cN z$~CFx7=Fc!D>0b=8$cp07n+ob$Up;oDWm|`3ux7^;PWV?mx*ZQB6@|C@kPd(3eqfw z`Hp$J&xiQ0M1+oedo6^7?#3kI5$Sk%>S9Rru$TX^#&gcceKKD%)WJghvTZLD>ey&D!6qq%$eNL%IWRbZ#AEa2WURLFZ*_j@nzY zoh(^;!x3r!3!6AuAFZxIaT-UaQTPqyHznKzPLwx zGF3OqtpJUEA_>Ta288gG^$F#DLISAm96_r{(jXCklZig_Ih9;Ch~4_7vf*FpbcoCE zW^>xu>_#pdvQVp;q!OdQXPLld(2!B9%y@4F)K?s%GPcnN5QCtk1~#Rg1>HS;l*^hB za61s=PKI$0%eaq8L@(Q@n`_)5Bvmo~@{#f9x6Hqkv3`gDkqE@Ff}}Sj#zur3sBByL zlsc}_S9JeZ^!GY+UlXd=%GloyvjU1i7sa@nLhhncyD8Kzl2IScq@S2~ks$p-F8#sP zhl;mFLj6SlZOmTL1TC8c1CHOgh55XLgF9Fo_{cYo$rrYMC93}s z)q98P0|x;30I!7PQUU3ifCRimLIS|2l)|qmpa9S6y^Q%;fp%-ulL6XcFW33dfYr#b zF)z<)|A3X?s9{@=d5@6!;Has)AKh5&Uzq$kH{QB5-LbaVx3xaEy}b-Y0|0do zt8Ug}!0H}c0kMwen1dN_53YdNy|6VU1gDltVoCrUKL;z+*^2FK#et>2la#`|RM6PsdKzpFZ7m=5*VcGhJuT51lU>KYwMq==x02&8bVb$IsvBJA1YB zOi}Bp3$3TlwVgcGcH($bL3a7+120QbAHR;dQSE=M!6mWD%kH#E{6ejVEjri5nI2Dha=gP5&a~O}e@ENTfqz*{DDa3L{9T&0O>cp94(J z1_kzsM|q1F!iv0FfmSNmFsA}`M>)sn6W0j3=_VevgG1}*(#J7$3aHC86Bv8K@DpfJ zK;8ps32>o1FzPq9VKvX_GiCy#A?V9K^JrBV`v-?LEfdd(`LMC-5YS=MRLvz)ZVjf_ zz&HGX8Z^-L8tHm1bi+0VsfA908UqMdP!&T4hMm-RmH`yHb(mqD5ZL~P4SdqFhi$(p zzllL@f;=o1Z#lc*aWQyw1Rfl)>ft(Ot8A5^)hxqu%5Rk%0~r3l<>jZ3zrc)?@n#V=;^a1C$fWMT^)mE_JJZzfFdbX z_vGH`vF>m9$~e9;k8c3L7Pod+peTh2)GEHdxV<#FHPyA&`(vT$`($0?RDH)xQ{Pj6_p7?t7WW({(Eho=(pE}on`h4H1i@j$qcb_b3J9@gl@OX9Zp)XnapVJRiWTm~% zjJbLu{OmpdV-=dbHtYBSiQfq3IEq;g%9J3o_-QVIAk-F8<+RXjMqoB7HE$P+p(*}h zuJ|D2JV!`hVGHkQ+bx$3NI;Y!h78;(610f-LA zo>zm;4x_eWRA}%C{RoFK#bu3gSffm2giaer=o1WNj7jUIo3v34zS9hVyHdlYePL5R zG02q+T0Ix*6^f@g*bK@ZM(ICUq&lX473=p(bl(@AUabH=1^Vy~l(Gbuk4J+g=?@MW zPWEpY8Prmhs9qJ~)+ zNwxW;z1g^f*|4LsRz#~5!9arqQ({P`FGQ3lBI+X{4de-bjb93{rvl0=38PHT1~p=@ zx67c9c0N3GIXZg8(`UrfZ(IihtN7iptv*6Kt~z{GUHNJ3d&4LvGxe+1;MmB2M;2Ae%1Z3o~1j zLks<#Gwn6wUq1|$zwIge*!%8l|Hp>G%8t>xp{eGnxt~jmy^ul|r#dDFn#Q`mPxLg* z4z|JSe}1eVrmTDC{vJyI9;lF1|Gp9c+(N)RYI7oBO5kXPxv02*1*!^z@sy*L($(JC z&m%lMI6E%(Ysy!FWO=HsWE4;}xOUGOnI z>vdwvv*_4|q2c!<0xx9;9X{=y^4KM@)+TC5;y=f621})7p4pUCF<>U`u#&c`q`l^f z5ruMIWIivn7?zpAjImB4tT&gJVaz8?QjNK|)yfpgIlw10P@R12r&s``>31a`#{PiP zieGC-Sd_ox8bAsHYR5;+uo5%+CLlHODeV}MGa+*hgM@@dn?#UF3U$(iHcv%X87R!{ z=b5Zggbv3y)UoX>qzOS9DfDIvvzsND;>l-d>{%KD{eCxt1TED!)Zi=E5Ok?koc%TI z{q=0aW*(_ii1bKU5I-gCW+kUaLWe%+BUk@3->6Dp3~kXDfHcnpbgA%h0QL*Cbzl)N zL`6D{Nv(8h6N>`Ot~M?W2!VAhW04bMb@5l4ni#-?Tn{-}bDgv#hDF zqJOk*e6nSJrW4Nn>7ka1p2qRchRN>c@vi34j^>e{P43phKf+BV_#<4c_z*yj+Kas} zA=BEMiySP7whOYTt2NI}MTDz0AO6YFO5tK-r*ro9)x`w+XT?MuPfEI+oOvtxz}<}O zX9sfM<>po87t|IM))f?fD=7Gyo&6y#wKOUIVN4{jsc!)(B|>*J$0P2Xqt|n5&n64+ zX|dZX+h&WY+~z6f#o{qjVXuX_%TfySnK3y5)H#twk3`;LD*q}G)R;+MfFu(o)!UfX zNcr^w&JQ-Tflm9uqBjeP6Cc)#pJC?DHT=v2A_wfs4azxs&?du+3Z8x?7x*DYfT9kr zNe^l=z%l{R{Un1tWo)uwOkO85b|_4oj^YT4GdMde&L)bjqWmSUaET*X<;d4i(`^J_WTtYtDXLq~>~RM>F+;276qCiMbRElaZXK&^3Q2o?M>-1pTL|4;D z%Xbh__kFMFtgULTssNP!0nWV_dzggRe~(poP5i5s$jL$o0jU+h>866%!zv$gva?F= ztg_PBxdAcNTN@SZpAi*xBo^GRlP@Kv6{lsEW@UZI$^Md?^EE%G`as%;jHFj-u@93Y zij%``CkEY!^}Cj;JCbXoJ#S|DOkvrqw40IIt@6yb*|Hs;cv&czl48RO(SWIBNFjx$ zenwJ8V;kHO8R1~|CMSC%;!287j`u7gh1+m z?$`)&R|U@i@)*4Mgc*G1=vA`z6N6BWQ3p!2P6G^MAnZ*d#w!fQE}MgM_&Ae?lM&pI z46$oM--WS~5p7YQzGlS6Ng~`>vi%!(`CqB4ztffsp^>ML(x|X4ZDE)YY$&!dDE?rv zH7a0F3DGGY6ZTM$t_QhDpP8WDlHaUAYX#Iw&`LA(K;PHEA;Uzsg-wQZ+Q&iq5qi^a zzfE(vBWwmRwVIel5HJd>XPbOu8-Iny5H%Tcwf<>m`ppc3%_*1*m12}qJ{{sQ7fMqq zAQKM##~A4$*Z3iq1lrZ7eB_6#y4zbj9T~YCpEMg5y%LqW9-W3KW#buzo2i*oVNnZ# zk$7|}9+QCw#cpbXmu$UOlpf<^=Wc6{_Q=@E^M`KT%*neHo_;YP>s;WGOHtSF9(Yl9 z_UreDt=;9{+TVO=diLa7@tuk*m*1Yd`11JKXNONb$vgbwz`@dtV`aJLKOVmF`S^{> zllQ({d|q?oef_M;ht^V9xQC|P<_1Bj#{sE-?$!dWO5kC`*AO9eRSBT+ceXNfv9@uub}vvN4`; z3AT`O#j23MAmqWcd_p1yN#=yy3~WONWo8W`;TJLYy@>rv$bgpN8R&`RoFl^OHmcH@YUyRm&r{D%CZY0G2g5m$d#{XaXt{!{# zcaxFdjfYIgJ!EpTu|XrruoIyUvXOB%bC%6sWV06O$Q*?_OCpU>N!?tekw*umz_h*P z+u#4K(qvzssqiaB|2xI7myeDs#DhHaC)K!<5dFtYy(esgXFOw=06Z7apYUj9 zGOSJG3_x9oiC;}j-Ac*^tm4TzI|-SKaVg93$vd&B1W-c~ao-r+BYeR^v!c+Os&rLeRM{^_TE^3MgIzM635PS&-O>`Ns%CvRpPyqTJLH9q-bRMN$W z)XULX*W$Bp#pOIm$a|V}_*KTKcR6R?=bbOlzg&L!M)~pLcc&hgUo8JzT>t$|cT07D z^S92gmCYaD)xLT4@#&-2B_)4D;NPA5@aF#nRFyzuMW9q`jr{>st*zMIM&@p9>S}G_ zW~mY5^1HtmH8)^ya2bRfurg1sb_$|u_ zRvV=(!xwBrs10Da`c}$qc6AsJ4W5gN1)%Px=4`}e?g4c(>u0pWoHLEBjJfTK3?<)0;OnR{Vb&ZWg?~aJR%D{_cBzq15tkK;6Tt z&Q79LOEk7}z^a>#rMs=QR&5VufYu?v+cn-#mmB1BA}aJ&T0&_~`uoDP^7AfT_Oc8@kfmLnoE1iHGxCzF2@j_uz!K>zC$i-=dwFcW+#Tia=gbzQE$dCW$c3* z6*4NE{#62#8UYD*IyF2a7dH- zH%r!^BN;A|j221cIYX0q11cQ-J9@nB|3J6?AIAE>FqZYu1uAcmDV}4AXSvc@o@|08 z93i9g2!Dx+tx~wFWORkXSfS9DsPq{o(oG``3b>tYW*^4I!-7X-l13`I9=KIJv`@_M zmtb9dHWa0>L;xW+Y`ea)4L-B=KCuldIYuCrt>V)mK%EMTl>rA;4WIFWW(b?CMj^W% zV>AiaKLwn2J_-bEn7Gzp^v_%hSP;Bq8@<7(@5Jl|2h~u3-%LdGdU86RRj`wijVEVs zCuOZ9XRIb=?8arl@SmXhX(Djfutjr^6^R=FwcpCE*2}9n+3!FmTq>as%(V&2wu{Ym zNh#2#6?i1(Xrd0dcqXfK8Ma=zj($g6!_RoeT?$CM7MyuAEa!f7{*%~4FA|TwPCEQL z>DZg(lV$0r%d$>A%{cQQ^Wwd{l1C?Bm)@u>d-V0qv#M7wUfq9q_uB2NXN&f5_+Ov@ z9Z`Zvq7o6Q6dI)#s?7_(&?`z*BD$)Kz$E1jCwf__{OaadOyY; zk%$K5qH%kxK1T}>ZUEW%J-Q!ehIX*p9Ncbk{yo4upxVd z#KTptxEAC{ZeU~zQ;TsU&WtfNMTpiF@(7kK8r&a+PkC z@*7I4rWpY;LDB_@8Waj+LN2T=Mnzoc%YYO9gO7l~wt`E3%O!zHX05duH2%}!5u2$Q zcuoPHmb)FFv6+woKwV4D#N#vZuoT=ocGn%ase$uK&4R#bUhXzvqxtOab~4Z|B21}^ zk!q4;zRBjHX|}OhPVw0;(OE7LSL$4E#zfL~!BK6q)l;gKkFW%0*_u%Z?7q`B=eq8ms^y&S_*RR|@ck;r2 zh3MWp|1D4fqL#nn7f^N9{|Qt;thEqAV~u}|snAWEIxL!7PpGU3@r6MQJCDkS8htAQxUgZg2K)PPJA#7*#qiZj8Z3JL(erRz-Fb=DT$;P z1J<8()WxdRQutL2b5z53jD0Yq`pPHQ@IWMG^n+tkPtyZV6pT+NFy;)8HN&P&(M(22 z2Cz2jLr5@3okC~}4AwG(y~^S&vv^Y!);O6xMHS4`Ws4Nk6=UT#$r@+ct?*PM4AHF6 z64wObf$_Mb?~2TRO>8&Ikk2qAGYsJbn?J%#Vvfa9;Lyw7J4f%vw}(2CqOA@-*fK%QV>cD$RPEC-1rWqz*4x&S_!r) zz_R{9CxdDR>Lp;h0)q>F>{)~k90M2&5AYB$Zvl@B!0LOjb^#@$xwKp7Iu#zem6nO; z7UJpIYq6>8@#z56^^~mL*epCW6`0kyTjZMBZ^2AEFLat!xDDBB-#OW3yGy;j`I<

rjI^&mkF%T|6OD&Gdx)%+JH1~dF-rb182hoQf#U6YX zd+`-j(xL@3;+ILuF3qG{lV(Vpd^^np6awdq{ zAiF}2g*G4j!RExuIjPy0+`Ln+sF4bxhbj}ZVBrFXehJqQfC|nb;86MvV~m?CCPX5j zSB;C&|81pXDt(Pe_yL1;^s2gRNty{a} zx=>sbvhCorX`@?~yG(E_mL%#)p0WqwHBpgo2>BC-STukc^QmAtbI*b~Cq20-+Hwh8ojFmBszDRlPE_P$Vft#sm zcwQl%k+U9`wvmvrnvw|_bvrs^CnyQ`h{0VWR&0EhEj<^-F3?PkIO<;7TPHd2JUls` zF$%9#^YASD_&irQ`qK}2!qw6T&V^?Fy09UZ|>k+*<#>qp9xGr*99QeJr~E*v*pj zKZm;&7eb@rL1@9a)spXNLBRDNfa+nx)7fI4Hkg;K@IQm^Yb^=1R0UW%`&bhNK(JS4 zeB{a0`16@DCyvD(eVBRrd*12ZjQp9Xq*cGrRXg`(q2)SNildfW5}PTpd6!7mCY83z zWKfRwOB6$5#i+=1SYp~IGi{MdtHu0sA?vk}0q1@RYH*il^pFoNEvW)_mm;)Jz#HLm zhiHsJD$>tHy12|ym0~;8YcbHhLoEZoF|dvyvDBc(-`OT0dd9)-Az%kE~-CQ!yS+I9j1CJgV6&7nVAFv# zSep%ad8{QR;{^xt?0hItx04U7r{=6BAJ~XU-SCS8HOjVA=q#Yr!fRgaJgtCYSo=t& zj8xGz9&BB-+&|qquE0Ixs87!Ez`T>e1?R#Guf!DGip{wbn^7DMK+Px#&$=51K+P)& zEhr8@csIP@K}6o8hy#y94?GRYE)CCp6`lV)HV=SWl2G(8_sN@!)zy#N8p_+7>fU{< zx&5g8)TR6G76efLhbMtjO9H5X(mkO5-O*2sr}mmDPqom?PT*xH@>UZ;VATfmwi1P? zEQ75a{A@J7&LJUw8HsVH(^4;GB%V8weENRYnW~)Q9qGBVamm|Z5j$?~8>UukOa;!f z-V&>4MOGscivfjskJPlCFYXlq1%)6@^@=5(QppdA0PO7GZ&WIxgGCt8MggS_7)N6I zHwg;41=^?q4y%_!0rkfyj}7W180kzoD)EHiDRC4NDxUHUi+TDWq=mK- z{H7k$^}tfK%g&<1TmqXrC~|rc$|RGZVb76Gwh?5PMBOog*&2Dt#AJqSJW2;@4XF)I z5CI)nG*C9c>EEGoSxQL23lHIW2Y1qQiApssZztivc1ZGuXY_`1D2P=j<(he=$28_R zEOBaAyWKFC`J0kmv@EwUk$0L!>|ssj*?|1>p#??Z2d_mRx*dP`L2};x1UU55i^EcH z2c_K($hsYneLE=oR!Huhu$+5g2OflGJ`Bu!9F+AuIOk?~U!NXU9IX}SzdU(b3qCYc9#+D=Vt|;Y+KN2v zC7$+DogH!Fd#fcrc2Zxp6w;}$l{CcCD$vr_&&J)~Jv2NdFEQm(R_?vR!iUFl?%Xc8 z^SW{QaWBthmGg|mW=vo)A+?%P*o;XmhXn-xWDt|~W1=3OpabIp ztrU1rl|0%TE~%KU|5!o;l)^6NgM?LQDyW0G7K#9?9|WYpUhZX+dpX8Ed}FYA1VfSz zj5cp?wdiI8BB^SQ@pmDmMapR6k%1gCuapi@LD7sYqry2d2bZem4H=vI2yR5g#-9v! zemBMqsJjN#`9JB;{@G}qgiid0GNq5slf*-R;o?q_BPLQ@6N-BT;jTVg4w_XP=V_%1 z2mr7ns}rDK#3*p>;0L}$|I0Y-`%55WvT+hh{uR zBP}BI4LW0o&RnC?S7}5n(I|^Fq8J!uk$bq*Rsrojq6Z#9Zv>1so$EwQ6n^a3R!$zC ze;Cg>f+yzh1g323Vs|w$n@-^%r&=`gnc}<72;KXou0K73j)*XgjBM}D*2GE!@>B_D zwP}}pGA;*XUJuT`6Mmp1BC|L=<4#!m?a;K_L8-R_({B1_-1N(U=j~8N$Gbo3tr_PdVA$;_07XC?`K?llX$c_DR(k8Z8H#7v1{+bDCZok2dp5de(X$O=4{5Sns zM6xNeZQaMf1LJV7VBF1X$4R?pZ9gWFbz<-Xvnx;%IP|_#vL6UY7pZ?fW$yXKAK%C=*vUJLXCB03a&X@yTm!o4=xvAaRjYs{x!1J7ZCa}9 zv+(?6ugMgkE;5Rph6|mPU%q9`8P~*1x`fN#DcAi0nQ3=|A&U}mD=_7zU&?h~h_vfI z={NjRZw9B`2~E2jnszTJ^}b))L!XStJ_nxqs6xe%JRz6DPRiXz03$XlAxHy-kxP5r^9w4$V+9D*|sSncNO_w$TA&V?*oh@3S3vj9JG6kDAqD}47pWbf(32KE*oii|)*4JC1Ba?7YFw?5ed6)nkw{+|EGWpAJ+wbW;LC>rP-_K@Ixe+Ezy$A< zE-}_6=KmC6Fv1#=h(Isa&*Ke=1XJenekm73h=kM&F&U$i=NWYPA=haD(Y^RbphB7Y zk*NobKk)y5xI4@wC*Y?}Zsi}`$tuKC3-PF|9p6Nd{Ns)hAWhvg_g|LiW<{DwrFWl0 zz-_Tv9Eagzia6@{x&(!PzIF5|x482ju@`lTSA0@#20$d;@F(KBPvSN2q^sUZ*Su1% zc_&}0#Mzog|0R-7h9mCn7ONMbdC<*F0Otqx*%7d zP>p|xM_{ODXsAzYL`YtAY*A8rX-59n+#_v=k98l-Z@GHt$HRl4o@W)8CmpX#InbMx zx^N(6H#T<1H(=RCvuFczD%(Z5YF?zA<4Z@_*Z|7u;-Uc5dNI37%me}kbRxv^8v0)W z?VTyF&Q1wfEn`tYjRMsj+%wXQ(SR4)g^@eh2Hk9Z5S0K$xeGA?Rq3>~bjVTwE;_&! z>6fyhLYNowCaAPI8fyjNtuuwVg%fUSvm;b2GB|_#^=GK`NfK!uLB@@ZL7~6EDa+1qzAAy19o>WSJ2JjcA}gXE(+WOuormGMJmL+dX-tb zqkWUgx>72Bh9WPytOiSSP}~ox?dDwFKozy%>Quv`*9+NAQo=B>S;Xp)a{FccK`}NV z5|42N(_8@z>*jc(aTW*G%Bw01Fe2z;(?H@4)Y%axWtu^Q(;pHk0Cg33Uo`p(m9|2q zfS>RLlibfCcZe7;_jtuJe9ooRI@!#nCIL`)^AF*fg?Li_c6j=xPyD7!#I|klmYM&i z%zIIwnUi{qsC?Vq0t*mU2$!Z&aoqi6J}H*Lg|;y#U1QH^0IQHxldkWXPh#$WSF zxat*u#WV3L5h+)__JEpvGa$LxKe^aDxx_QMM4NhFoBmLj_blMhi}1tGV-G%z$-5Jm zc{wWfXi!k5udTO(%+8Xd6ca=H|3z@MmMoo$9v{*vFaup|OkLELuC{7VXH9@- zV7PxwOkh$>KuSzNT2w$rL}*rI zB{Wc5JVcFNz*S{D+7pca)y}L{qpnfO-eR=(Tv`Q6hFk@M^NhPeNWvy;AqPQOQy|{fYFEHRt~tc2kxfBZR`gqbQmD?lgMid z1yGo}Nu*8^c~T(iqBDOYY}`ArUm*QvME^!+R_GhIVgi^^bfUZt2HFQ$MX~QxS{;+| z9mATHrakudQ=UF6L7~fjA(I|nm11F)LOkN(z8)BWM?~Vm!6Tr%7hp9^TB8tcm-B(B z0JedxeCAIcy_-p&Wnl}j=OVEeDV#YHbBe@R;_`PbEc*yzAq9X6^g=LWfeG6jlllv* z1W<`emGW1h0wrt^C4dSvtrv*iGYRGU{Fyjl1ee#ARLl z62uJzc?Eh$Mu%l3 z#~n_IJCPD~Dmn60eB|k<*fY@ymt#}!C1k!z&aO<)YsfkH^U#sbv&TCx9I7eGeQ_iE z#=V>q_tR6ZhG;L?iOZ~|V4XDJVmIO9IOkxuV5yoG$wrvGDGq;(iw*L)orLQ$2kvqL z`v_n|L1$4WVc%z&+@$P(Z!YQx&~*5^)jFEL<|DA${>U(@=h2{n0u3oRJ`JDMegT|^e zqWoZ@gI3nd-hP`w;cLF3tDZsYo}ugBA#GMxt=1Nk8n;O&hcT6E$jr2XiPSTwpx^Je zln>j0bCj$@%xUK_+Cf}EAw#y`BJ&ciV<)Ic(_o8TUhkd2@e)PX%CA~A`mxR zFsbtlDr8i!zu2JA*U7Y13T1&xoBRY0%7$j|Bfff!jP6HF(?<42C*1xN6dd^q=4 z0~41#qnGSMmKEL`Jk18`20)!M^Z9P;dCfxQ&optB(sa(^UqH1EDX@z@;hu0tmw3T5 z<%%z)O~|4#McU{~nwTO@>?LjdWe>nAkx{QhzV%MN<(*pWopMK)c*i}l*fsgCYsx*h z^n1GOhkm&aLh|p16&A-7-j2(;9FuxFI<7D>A~P%?(O+jP_^0u=-RK`nQX7CY9Qte` zY`E|Z1nJril?9`gz(!+)Y@>!Mrrp^x!i@}3q*1dvP+ylV+X;tID?CU%3<}~i? z0PJpH&$cj`%?!qXOgvj6-oVJxESKX?$&KZ3{R z>;$GRfoNJ231%s9=hPOe-R5|#2z2At{_oW8X4r!0ZI7f|n#5bKiMO1S zZabwEyJXze9eCiIb3YJft@*bj@@_@~{`l+byFcFFX{)%=`1b6N2L+EK93E+ux0I|BA?=e= z)bFgGb9P#=wwVyi;HVwt3t%w{!~Avus{x~f5~PAdtKhTV@EETJtO^@NwTr4+Yt!iG z((L2-$w~-YDxkmti4JUeU=s>J9c9u65HjeXhxm*!89FLsg2=Rwp$Ghv5waeXa1aYj z1ju;f6zU+t1e(^Gi+0sngGa=T$StPKR3InZb@v3wbz@>YB@+*goK!nB3q(~kq#YA3 zm|0F?!WoWeRcJcTk&aS03t|gg7l4N+;33hwzTqn#0c*OD9iNCDUHGb---1>Z_{mV>ZF!e`9U8hjs3L(g-093fwvQdP*r0G3llb*2Y zk1k*c%jKHs|a{@Iha@7}zq{ZiUo z_oSoYL07}=?uMH^jn_MBFLiu6-&j)cIy2z9*0eS`;AgB~xtZvv+Ir2$XTs8I1SF`i zY{Ga@0Cb@&uqp-h5Ewy!WKpW67+kva!CX}3V)@2KQt#{3=;Ki5V*W+Rg(()S%YUNO z0X7wKX&;S1Y(G(^GQsN!2q%3k!x5A;Ox-_8)t{ys!2o9#p-sUSl|>(9Guu(_C|ru? zs-3a62f1rIo4?`WiKpk_iJ5pv6z&s(`-kCvAuAfMMOV!>0NB|LH?`d0N!PiOC5CW{ z%$-DpvqH0NM;-13+yCg@fXFT1FhDHs6|vNq5z0zRgK9uRGEamLSI+y(YjSSIeDx~h$y zQwJ`X`EAJkb_BjF092dMMhD+QfykEhn}Vk=H>JR}O>Q1C_aKE&qAIGuE%Bsx;#p5< zsiM!iMxA#JJ!2ns)-L>S5W*;mRIZ{N9RG|X}R{4Jbbq}lX+ym+#Ujjt`3RGLM zzmrm@24}e0@oA_3M`vHDAh_>z{VDJs9jN9_uY0?YTAFb!+hF&925PE!7uW-d!v&%Dk8A zTYWI$TUyvlCyQoJ_toggX*c&VORGVV7-lli`4Tk%o884`!bKs_P{U=5Z`c%ArR?ha&En0GSqmigGL<`P$Qu5gJY>Y4e_z-b?xtf3RYSz0tD_Ocu6;Yg))D-x#P!AZN;SR z1|;u##IHF=EZYXHD*aa_-kSoS1*y-FI`Ea1Qv#o3h3pe@_X#A1N+s3Sp5x*p@rF7v_r^An~>ACp=Z*-zIk-~-o>m-2SV;2h%5>ByrNdV)jIZu1+B%!&3fv<`V0tulM?xqP&~%v0al?5 z049Hng!c)h5f_&T8IJ_im!_PqU`=0;dxyK~o0R%8Wy z+t&Hxz99hhRXf*lnRzc41rLEClr_QUOko(92@J64zc|ti@D(JqQQ*vm(g!#U0;PNo zFs~p+xab&{GtS|R!lsx>gMl02=LQ!BaR{LPvS&8}gX=Xq4W_9pbOsDmq45Wx!g6Ys zK>;&i!thNFyEz)%P+1Com^yDfyI?&u0nYs`mzZ^R*p_wZrow*-)6NNW6BhnWjsZn- zix583Mo1F!4KR_RshnzNMpJ9}t|5wmRCRQrd+af{sN;@d$LvCm*#sR|1)Z=AI%x%P z4Lj=qWkBRPm#Fj3ahF^HsIiwEqc1r`UbG84rwTcv3O;S+cSPw`pm5KSIL2aDK@5c_ zS>j?WbTp7@X>t#`LWh98Iq>-jZXWEFhyz^$;M{{H0Cf+se}EQv(QY;>H?@xCpK~@Zz9=KAD9Y!O zw{vNr=Z~nctwV)N@v-9??TD2%NKgT*P_mBm`F%W27oXFs5H-s%ptS>)2W5xNrxo$@(bz10+3&Ub0>{ z-3X=xFe_*mF+WiaDw(8u9vc{3eWqsp3iDy5^`y#aL9JbN@?LZHT6g!w{Uh*@m<1<~ zE{$Oc^mZgyy)tZboDdu5Ob`t3|aF?&gWRXkqdO12@8t1!YWP zoJFy4SuC0p5LoR;ksb~L-t6!bLI6;Q!0r!>HFzi}Q-EYU#6w4U9Dwc!hY6)AOr_ul z{s*8gQcYHA)MW%&Mi@{4{92^`4XEJ%295zhdU?;Fyd;rk{e$tO%=G{mVkd1nMQvGy z;AX+wVxKwGbzJ1pZx{I4)h}Nr^^>7)Hkg?y9WFq(QZh{CWGhFuy^qj4)+#jHG4ha0 z_z}C1Bep?DEd!332OhTwJYgApO0|d8h_lX+S|Ovx6gfs+u#Y%r3;z^w+`{juneP#$ zXTDsUC2>v?*hO(vL2N63wzVH>zyU%@Hz?0zUxACb}nK|{R&h%Zm z+W+v;@Z0j?+M0ou=8m4u#(}_}G!m z!#PPuV8Rs_aydHaZkXS@h@jEJoSCfj`Pk@rf8SXb*BKk@DTM;`Q}8G22dyBp6IpR|#6to%wJt+)VK>-1VaO1N z2AwjINa-d$G@};K>{ItwQTKnM?E@Rqk4%FKxJHV{YL`j66v{5CvQum}ps<~`bzgMy zf&jO0ILa5Cb-2t(gL}XnpR>s4E@9kx9tzwinDoL=MOX;(Xx)S_D*|8!$<+kP0(=f*9C(iNxL}b% zWMDQS%?6Z0B?G(B0hEv>PSA;~f`C1>#6T7p3<9n&{HOm7s6Z9#m+^o`_>oTjNN21C zgV99tMnLSkE_T%}Y#Z+N6Zztp&mzxbSn2!IJ?y@ddxApfYa#G*HFdDTEX|p==4_>c zqO@gLX*h17rv9ncVY&8U2kk-+s{)T$_#ZV3IA#`b!W@!n@F^Q8S;NmbMVxhvz2Fpc z-ZA`)UGPaO|6`Uuht0eWn(7Kn-Lj-EsUrJW%r=~36T-6#6*z~B-J)cU5hBM(0X*## zEWj!#q<-o3e$k%Qz%cn+F8w3BdOIq-oNPUue1iQ_lj4r2C0&FocoLKD#wR_ANq7M$ z^$C6gDAoEs3XFUcpI)7n-&k;@@xtZqn|FF1KOcPiVYsS#sG+{UrMauUwXLJAv7@!F z{YO<(&BwaW@4uA2eo<0#v*^N+!o1X^*woml#1Ov&A%4fg1CD#SU-oqW7!%f>95<7h zvXP#&6BD`V>$BwOFk`Nqk&7mUya7HNR2!g@YnJhP94ug2xo3U$2`+6EQ5&T6b{VTp z4DPt(9|(2QO0}ueE;`#oXWhYL5`79v1A^Ze7l9xcn_OxmmjqThAoqA;_%E*+zXRR6 z*<9Ep7uRCEIuvW*iJQ5yA#?i~C*8cO_p;W1RTnsJ@7f6?U$Jmnge{3>JEj)I%0TUk zJ7{r7k3j~nhr;TiFu=zTqza&^S!Z%!b_8maIWB9S!-f|?a-KwJ;Bf)vF<4vgnX>j` z2%P%_P?^7i!`VCZr?}iHE})t<$RawaUqB`G@J#wp;~@|u&b7AR9;f-%oz09=>o z^d&lVflf42aP)%}3|v)Ehtex(_b;xPEu+xqZQD+<@POF1YSO**>Q0iHz0F-*j zmo(jb*72gOx9mgT$BO>XpZlu6^i+N7`0}x(qO9)S^UAkRDoRVr?p(Nc_RxhxIfvpR zq7uR*V*LD){rw8Vf^$7w&-&}C5$Ex`=?OYBa;DzzDYqBaQZrD{Plo3|cu( zJ9*8!`ORs3r(M1Jtn6BZ;zlO5lSPFxaz-Rxk(#Z^E#NBBIicw=0~?^RN9jb{zQ*Qm z(3!hr1lUb;2uKJCFJHnZjYJTi!1Rx}RZYMGpc27n4DncyIVagHXq~26C(9^)7wDvUCIZ%%#J~;t{{a<#%_gQv6OUB|9}Pzr zJTh^^Cw##zXvorY&dh&@=Z({~INN(i7TBfodur<%%%XZIQ5Q>|qc!HL{{J|8@9rq? zbX)Kv%zra?rjOliK%sJe>y4Fjj#5Qcm2#Gl2m*v8lp_d9{n&``1CzJ>)u&wuUdr~?Dq2Z^Lygnx+sjr4RWVNZm@}seyKZ2#Oe*@ z9ro%~uG(Q|^_Z<{)KW2Ks+h3iWv`j^)UNf{tqnCyg`1~Bjgx`eHNMI*S8mh+mS%<= zJO&(@UPrpio?d24FLh*>x+^;T70Z3t&Ppsc04}o%+R;G=1sy+Vp+H9>pRZPy+Nxsq z%9sOO%|xBKQg2OJw6UUkY1_!M#hW{pY+uyAqpj`XMT?(kY<;S{W?v$=FH`kYb>mA- z?QbsWe1Fx@*)`KwH*CGOW!KrAkDlK5GL~pe#5yZ7D@p>><>_&+ZFkiBYA$xJ zvEr*`ZL_PE&vq`IZLR+~m-->%|H5wi%8$)e?wZ~3WvTxa@jRH5zM(GSS!yMY>LiDh z&@U~zY}NAFETzQ_^>K|HerM>%VwVGT(;Y^Ahf<=$^O0J_t4Bh442lqX$+@uZeY=v^ z8l@$NIpsTy=54L|ZIoAT-&IfWW+3`WB>s6k{Ygpeiq{V{Ncck`83tFet$jzK{#-$P zAtyhR5?`rw_m#|_)%t&urdgHlp90Nnv1(RILE7R+jrKwAQhDdRu{RMls4LuoSpP7T-`8-c~L6LREMV zhl(2cR~iIWC1x4lL2*SXzNJ9OD64;89kC#BNh?<|2cu*cnxXE9p#|wQ8la zrr%XH?5G$v=SEEBqvkwUtJipI*97V&gJ5aHq_=v)RWa(!4I?$RWrrNuL1)=2ds(+F zv(ldJbmmsLD_3}tOJF5C-C<5G)2El4EYR(@kPzq#*mWU?4z>|#uMQp5xkYF_zhzot zFOP?6$}=tX&Fw8+OEDW=w6k;BW6NM~+Pb%t?oIFQ zSbu2K>X%mc9q8-avaqGI7Cg;ls}qUFc(lDF&=d8oDeoYMSAqQaaa9p!G`9?z8i|4)H_wn)z(3oKx9FEBe_J6lN33Ynk9)Stx!6jQ&@5TCR3RZ@-3!)uKC z2BXPGROGIRpFB&!RgL-!jruc<3Y5ku3Qacr9WPVDD^&3{s_;5lcuQMwn?Nh0@SaA( z&r&t=Z`IOoHDa{jJ|~2CNbxmVeoiYri^N-Jm~C1-TfXpb(fV)Q6+igv?$L=Ksj^vp z&0h=^p9UJ9b(ZE9%(sjFWF(8+7B%$A{Z7hcRxlPB>y#NCg;sZgJ1h;S$z+2ix5Qo9 z<*V#-l@Hpo!=~Jb0dciz!iK^M6m41?Y+UQ9LyR4_SC2WWM_pAT&WZs?uFsA?Qn|`m z-fgewvR8JyD!Uz3UH05cb8-cn>gF=NCQh%`8ws14by@WRt3G1aCEegEhoh2gki|xH zS&6eE8LO?RYi?YIA?c#lbxT^eFKXT0+O)f-dPgp|BVD#Dm3p|U^67^9R~EIsyK=?J z!QM*~BR6JNf4Xt{lP&A6ZryNc+s2Q#Z@RpF!^hj!U)s9{fi>G!ux zzqfhqThpU24tMYGS+=>oX+=X-U1eEWRWja?2rn%0c1Bzi5%;!;``KjZ)mZ3oEOfRy zceSnlMn}utuBAT>56lh?{IIzFtD4H&(eT|w^oUaYwyfY?tpF6owdo-3$IU=kA;y?pjMLmM;cO1^+?gKhM5d6Ur9EM+b^l>r|YdnYm zgR9sGeN!ztq9fque9>=*3*<+T97o$hD}>w%q*F0R_(UzfFO&UQr20{y{bw;fD>6V$ zWmbTD7US%E!|X%s?1S9w1N7{J)a)P0*#-2hfcZf}eXFF=CjFGf=B@e)t@)pb3LW5I zh>F?@OAFUgNom9osRm2)M8!7a99Ii&k~~-88VpNTMA5q%A@Dg-d1dN;}1@z(bw40v;q^T_LiB24V&t#H&$fVrIIs=#Ku&5 zXDYL|w*H0YmN%DneAwM{X0ZR_=i~WzB)bm(e&imJZ4s(o1Qp3J$`Cx?8Lh9 zr}|dx?rLAVtY&F@wz?*ntW1_vCPTF`_u{ByDD2o955AF! zA5F$j#Y#V}EJtVc%EE?QOBen$+CMuwI6JUvcIC1knrpwx#okei-co{`yl4-U$MSM0 z5SoDO*eP0k0n7Xl!_gE$73!Q$20*y%sBGTHwDe;vzhNi5_pB|$B{-E|B|DpZ)4+O7V@u24C`PzR9nIDwwcUs*&ip4nN z_eAAe{iJ3tqAKsJh_BSV!3t8=PY4BH@uTCsntR$> z#@m|K)z{2q%hr^ZjzyxYOJf^TnccYxXz{(;)_!ba z2}XgxGUD4Ujr6WcffX!%A}`SXLqPvnNc~XA0DmiDe=205S;0rq`Sk2V#6RZ|e=pGf zC}w`p=)R-$m_6O3$bUmrHCW06Lw`c^saBaMDu2j;e>Acfz=}AGR6&d>`g64Qdu!SEy3DM(`X_DjA8hU$Q^g&B<2!+> zRWi=^z(WqXl#mrE)kP#N))}QngGkRUFd7zEZ3`l4d25$<&5pJWk9GEKY^v`s&8%>x zyR4Z$b8gU3K5DF9V{X8^zt+<<2uWfJHge;UQ5lW1HT!6T%syc5h9XOunb}1C~(zlfo%i_DO6rt(q~CTgSoP*x|+pJ z4XYX(M(b-Q%d=}@CBuQhU@$lli*L?W?60nWzNPKZ;*JkGyHE8FTo@d>G&Fp1bmY?5 z=!LPd(_^D2Mu$(244oMnfKKn((Y~`Iy(h=}kB{{qnHYF$V({gO!Ka3LcXxG6bvLi- zOVqB6BpOR26{%1v>rZAJ)d|b;uxXvk@@hDAI$U}=6#q0``B`=SjmE~?OBUW)+3hr0gUnEgPnJ8o-$~Tb84J(9wp_V zC~rKi5ucJ3T#^g!DCMYk{wyPZlu$p3n16`be@OH{N%jAb8GxT<##xzuR-&Jk8fJ^h zpNh3Vh_ru!Fa^QgCpp;qT-B(5B`Sdqe?Fq}Rliz|^KIa34FMI_JWn4b*(Y#&JUXcWq`? zoB2*1yYFlKD7A3L;7=Ax?ZpzkLavYs)P#uE$ylR^=H}_R2LrC+vXo}oKzMRbiH_D=HzolXr*{P*|+75EIt_!qGhk5);R7BJ~QR~M1;3^V;s(vSO z0DRUAIBN$TH3Rml0ptu$Ot>&z6)6g&YN1*yCn@;$YE2yNFfwin>vOO^JLh*Q;+mT7n(D#w+(bf#@5zClGr&;yxuKp@69Z?)2R;B%#|ICN4eaah*|K8EXlH%L zs?uCnu%sy(tSk$pD!uWXvm$L>Qfi*^SznBXPDc`#Ly6B)6`z&Y+^MbqY+=j2Wo@4> zto@;L(f953KX){JnhL_$4ss$O=OL~bILt!(6cYCWD58LY5XQL(Q%G70)qO}tBYl03 z=9N)Ta?%S1V#EXDRFoXDU90QEea+Tn-^s=u&&I;&S* z&=co%suNo22jcl>LZ9AgeUaUQ>^?HcCj3e*_wqv`^sk>m477@v!=$s zDpIpl_DgN))o}gGrPU2e$}SMuwKSttkt#VX$SFpmq35f}|6#H`P+dW<>Wl1na_PQ9 zLob}z@YIp%sV7%1nJKRt3}$<6*#Q%XTC>L1wBFUW(ciWqgbpfp0C=LVb?0+by!$*? z$9&*w&7eEa)oQSG*jYE?s2j3Z51RR$VcOfgK2R*5FH#iA)Do3Ot|ingsWEUQ?D?El z)?sDc4s$3FOeU*x<%`P8JG0r|OxbWEHX4ZllgLhM>Yi(De`iU@@fF<{yLvD8^s=3iEr>|@4$zBeaCxOo$TvAJJ54(xaY!f&sh+4tpEM7zSqY3pC0Mm zv#N7y>B8>C)lDl)lFNd@hEiWu#-Fb8CM%tlS^J`-bv$HyIvM#ep1crE+)C#7pjuva zzp3#r%iHg_)&J1ZaxEVCBpEnkArC`9j20k-zQY#2%N4!Pq2!11q>xWa2_f#L;UtB~ zd7KeLVj39&VlTw~P;H$zt8cnF98#g?`cPd6Au{|P#M?PQs)FxX@$A(?vqAth0ABT1 zufAwd!I<*0Q3Ju!GYY{Kx%3kS9%$+>gziVR?nj00?{dT6Wcu%_Byoi#;5`JQ^3zfhjeYHxgckKaL|TAv zv6Mn;K~#(?Kve#pODn`p4gMLSNjL|{vEobNQEJ}%^t|_V3y$au-ZvD#ZxG^{K>R;X z6Mv5;XUkenNRH%Zw0bL21i7xGHcWpiqomICKX}OC}>hd zu=6PMgMpNEWq)ADV+)^tcl4>FtDinLwfFD@h`M4^Rn2fPv&vf5XQ&u4)UC0!taG(* z3bbzw^R52raPzbenE=8mGEWp!JXd+5`l^TBm4i+It*yDA^IWYSv0{MLxZc;YDOf0d zs90VgQHm5QsY;~)S7}OvG{A1*EEd*oGx`0&M4~d2Yc0zzOQpK9nUPdtJRVz{N^P#G zd17JvTYMnxxw5MNX79kAfx+AT12_BnF0bl6-`9JlulGd%(6PS35BmF$;rl@E*`eMG zqrD%E_nn&(947WEgZmFnPTpDeQcuLfACF1~n@6{L?1oZNKr3&v4PC1{Ha! zADs++Eu;rX8{UI&-U5IW;XlUX$YtaQb&LiDuMarKz8EwRgDWjdaUyPc$i!*h!Vmq&H}3 zvzoHY37Zl&qXNC9&{`tQF4B)}%k6)o`owzwHZXsM^uDUbo)Wn`ZfGSpmM~5lK=Natr~Jw4%w@Q(G76aj-k{7nJo>|o~8|c ztgjTyA1ac~E0z=rq{ULXgy$-$qG&b8Y4irtVl}utZht6V601t2+S6q#|-RbSU($jOHx92R#+0*yls)2X=`oPr_ zgMFuvqmK2T8Sg(i+Vk#c&ub$+PYtcy+0(IRY0L74s+#I_tUeWNOnGZlp6W7pRR%0| z)MxE&WwtgyGZZoIP5BRHQBuXO1S9vu$sbbLA8V^VjR($ISez1{M&3m$E^xAQj0iH4 zFnq-4X_|i!QEQ+&29QG@R|&9+`Jqnsu0aM9u{Ss&G}58={Dyqq7p1Q2ZvA1|eCRVk zNQXbB=81}+T6_dOE^Q$kd7vE)DSmiE@FMCu4pX8&Tcq9B5H-(S`G zzbXyiN|^f+`o5C8r`3I`VeSwlB!)2k{D!8!)skOpwcjz^S1kJ_O(SeVG2^-xe%4SV zfNL;V%I`{jO4BH>&2x$p!|cG1to`b5TZR|K17O;$>2eO zmL}c^*Z~}(=D))gy+O}EsDAJ@s^9~Q3a61DD8#ckHz=){b(jBxOZ`O^`%W4Efvot( zT6ZVea=;#JR;zp}u~|36gV5ET?@DHdw^}*!$SEyfo#4&S_Gm>WMYL%t|7ox zCHeq5z1C>q94@;*5D7VfxpmUcfg*tx5> zV|qn<@1lm*#`0`sI$V+UmuKBoWo{6)F6C@YJDSVv3)9wRX?t(nye?*YBH=kw62OVv z_o3L&@ys{T@NJLvl8!o0$SN%X*uN!pc;dg7(cj3qucXXf1$&p!-_g)lRK!K466;=H zSxtX)+WuxSf3MeJAqum5tnJ;R2oUuKsR2KM8>IFYiJw#0X8et)U(K-;IV$F-Uy}TG z3VN+jP)9a`OTE0`G$gfwL!c-t!sqMMf#kp`#oZlu096S*cr7S!-RoCOQ6e z>*m8NcN|%@@s*XEU+&p_uy0~tN89SM_+o3Ml}oKKWx5UJgNC{ZbJMh=amJ0n$S?j) zdih6x#5_k-RP-*s>gW0Ct()-IO?dgWt6%m6tY{8^;aF8|nIo!1F;AkHFP0UGr2?5u zqEN_GYMELip%^)iss4I(Aq=V^lPrBTl%eZP%uBL>uHR)(e+1paqQiCzs%BA~$kv9|b}wh)bX&=r-%MMy_#`1?~3 z6+V)@0y)M1d&Gnkz!&KIA+x>W;y$*~nDQf*;`i`H8BzFafZ}IWa|x>87{Sl8@aW^k z$Ce-*sIg^-q6T{c*cbhVtL_*z4vJ%w@qXIg&c4@)&C zNg3|K;Oh!eO$e{O%H|=M`y$}ICJjOe06s%3ILL^eR}{UimfsCTAU623JNrEoy-$^V zWlZ05R^N74e(2Bjl2o;hi0YMggPdW-Bq2Zt)u)v?MDxR}xF&5{HJq6`uxQN-cIf$~D-^OLmwtEAh=Ej-jOCRs=Jv=^g zVeOjRGi$$`p1iwy?AFM@rQYsi-JOTKJKyZ-dcD8z^}&HRMurbfj2;>retl%%#i8ye z2UhMKSh1~V$(m)&-EGyaO}UDObfON{)Jb0|=T4Nn@!XZL+#|0pkqRPStE z<@Y7QJ4W_8p}LCG7(#*n!~kTQd7>h^Vv7$M!lxt!mVQC~!cuVco|Z*I%ZF0}JuB^X zmOoU%NjP>9-=JXBD?G>uUSI*y^PJ#0M)(|C{2X2MqCxxwS@;B5^c*8OAewhbqy9&( z=AY5ZA04T$bkWasu}_?tE5XVW!OSz!#8R6vWuyEirOT|andJsf$Px27<%34$13{ax zxxq0yUA^w{MQfj5H1SgVEXN zu+~<$7W;no$~BIv)h^7K5Kb$HP)RxJC%lbo{FtjEcdcI=z)BTLC!W%4?RC@krVZ}a zt^TEZV@viX04-TekV1kGYY3@^z`HLev@(Jefu$Ie8O%}(wz=Foug?|?_(GvjNi-af zrE{4^IP@)U-_o=4+2KKi%Cp#xo>_Zqa^lL^(AoY~@2pz+N_XcA-JKBaf1!WX!J&Z{ zM+RRQ?SFc(XYZ=zTY8pGb+->KZ|-cXYHZ46>XR|Bv_9^yPIz)zPbTN7%y{Zj?&hRt zQNq1E;a-`rcSnrFL2g^nc(BBFJnXpWFyIZnrB+>4;51LhZ*hR7D)Ds{f+yeE220VI zIY}3urg>lTISUCf8dHdqFVlh-h=Lc%BE%nz@{cf5M5I%c{4c4<1&m5HqLW6=OR5Dg z(#5ao5vBxqQs1LR$OK>rg_HnlrTn^}N{AZ&0>8GzOY39Rklzl~@++fXGwe64{!4z%TRs|JPTtZ>vE+0`5U9lkjiIxC9CCJaT z)R)?PIMv-Hb)RcF{1UG}E>JLLh4U1y8?XR&lu;gLWUr7y825mjP^5f{6+X@uKh6k% z{Y)`*|Mrqak5a<@q~w5Ha1={@b#34K%3yJF*BZa&Onww7I}%MlTT;3y5v_6a3nu}K z+Gkcc%@UKLNN<{Nw9ofOrDZj2$EwKKrs}m1H%;toUh{0*hL=}vdvSQ`(VoSFm7xl= zJ|H)R75*Gm(#VysFje)MK-Bt4Yu%KsYOSq&(owP64x*yz#JBOsT?nU5lL4?4-2ku@ zNi0^W>!#gx)6V+!&gRYTw(Wl0Q!jZm2Ix5{r;~D=g5y*uppcp(EnzsB-Xt?vBxbwR z=2E#mw9ju02A!dhBVOuCBz&2&R83Xe!sd|`%Xankyf}mz6F+`BJ2854bl^x|_bXk? zo?5qJpIL<6M#uT1licn9ThcBd7e3n9)4{y-or#17T=l?1tc!!mu zM|zYOWYGRC8M*B=LI>cOLG=<*__*p%h)$@p-qaS&Ew>b7e*o%#C$wS^70aBLX(jYY z@+|$5qcG*XtyW+U|1L}2qw!?J8pH6nKw!4KVz#vvMIT;)4>{s3g$Uvj7Z@#QhL!JI zj0XC;w{Xozs=!k0oqnRx;D`@R0N^*G@)8_c?hArOJ%xH7e{mc+Ue(cOby`f~ka->? z1<%rgC+C>Ck1c+TDSCu1e1tB3gcaCYGiZe#FpyG zJqVXWzP}=9Q^n7Rw@X3M+pBg+IfT)^iohEg)+Bn1zq1b41Opv4N=As;V2Y z)law^*YM%=w}{#_6Kq=NZ(1K{T<>Yv;A-0BYTMy!-yQ6HqHM+E>E#Df7Ngu^QelV6 zY^Ka+1~8cjlNm3*-0G0nT@sg9>Gx5gpgt0^M#Gj=!kkK3QfYrKm#eGoXj?eBV)_aEwC^-A}OCzrMFf@W_^(@bmA=C+pYOBQZk+P;2i`|3q4eeDe$ZFS8} zxm;r=UY`m#BmzxIe@imZlJWt~DPL3C*HGqb%=lX}{>54U%Cv7J?%kCMKkBzWX(C@? zl$Z@2Qx@apMHP=mBA=RqrEq~%!+EFpB3yW=f|K;T54m|Ca0@=v@g1r&Xp>TC(M#Sm zz`3UQam_Z>~r3Tdj!LEj=^0Fh>F!v5EbA(f=M-!&$+HCg$usB#4iyQEX@-YKLml1 z72qJ{vW|jQKQ#Q`fYAy03rqJhMGrH@d*~uyCsnvhCt9y9*vg4EQ-aOPqQe3A{f4Id z>FT?Ivd`VAE3VQHz2SqA@UC=dbycvtKI(ImZihCYmwB`cteQXA?ej}pxVov5?q^$i zpIg}XNbSn0c;7^P_4i9w8~KgfIzdin%D9y&F83i{aZIgaG%l&Y!0++@h#luTeK&%bZ@ll zsqBg;Gs_-NJIyMWg>YIarnyD9*@%JQ-=afB&dspEb)jj9oHoj zx>VdzmW)*9YMUFnI@+gKcI;fW;?cg9=!ibi*SUA)(rt^I*R<3PG}QFgRS(qH3^vsc zHr4es)pa!1G&hu2)o06U(vjL!pf=%cNO}-C7nb>f*0irR?Qco*U)t0DrDW! zI>87|GeWddPq30VjIyWLqQ_JZAz&V)FumdWoQy#me5a>mdVmi{o#Xa8eE6IuA+XCoBbD44e&Os02@wFTIX0 zgPyYn>LtPamn4O6Xe1x#w6J=CX4)l`OAPZF$Dw-4;|@vudS^rrf|-1ZuWG!xeKDC2LhuW|29d zj8^GtRygYVY>i{~rnPoVQLCry<&$GA`KrH>{TKayPZa3bV}{Vo%7asLHwChB8L{9I{37Ypj+Awx1^Nky$d zdD4+fIC60hmQ<_K$%b6r!ssKsq?(b|J?rtCJZXfAv?Z;1=%G;{a^%dE=Y^Exc zF3%*&$`bLicr=#?l_&gFNqzH>Dg+XDKTQ@xR~!}$SJjGZNKgr0^W-;N){0O%p&xaAZk~9C63jt# zW^SDilP2V)2X*|v)_saU9Z){>A|=GT39k?gMiEz`=zG~rUUlovIjFZe@r%m&R|B?- zF2gw+zk>3SQ-9fExN6bi)keb;oll-oG^DMyH?(S`0arNCSa*6(D-trfFUt!d)$%4I zJFHjX@DR&a*bumcycBj4EcFG&X9%e4Kgnb6wv=Z(1WZN8{iKyZ5xE858kx3I;V=)(1M!3MH$Em=5el#j8JA=&)3 zvclIqt~*UFpER``FG;-a@x9>l?+-?> zC67jz?T;_tUk1^?mMy8OwV_g<{=Y@cZ-@ts03;<-VM{t1` zpJcQ?lWs1rY^|(CS+uC8bxBmMlpmFfj0!M%=N8GZt~AN*raS z_KJiXf1T>2vnJ)JOWW(qYz-NEJv#h3Z%a*NY0|qYY}-`geJtjGD&%@TWPQR(?KjI0 zaAFA8zd?$RY2_E;eWQ{??-Wa6PqV84v=~3mM zkk`GegV(JTO6f<`LWt$UwDF3SzUenz51Oy~&6jQZ3%JH&HK!Og62gz*H%;@ic%G#s ziF6U4_>N8yEFR!AbljkQn^VJcL_#%kUS20p5)I$f4~(d&KO=Xp5d-4+jQ zOa(WTg@KKklJV+bHX{qy2+P`3%P0Mto@##Njm}Nawhr$sukUr_7Mmhf3|@9yK&y9X zD7^xEcQh+An$*~8ra2{N^GMN%`qIbmfFiotvG3{NZNR=mN^=-uDYD3D(hWX6@aNC!DZ()n8Zv0hpx2F6DDaa9^~*vj--Q1iQGa78f+`~FTRJ(2`UG9PNBO5c zsz2_h3!l@8!PR%*&W!UDW%2uJA$B${+NdjD{Y{_cBEuUxpHa!rYG5g%y{2bx>sXv= z^P?hy{!*p=OvP8|7$MDxV$qNg#Q($RG(~XA1D@3uqkH)(ZVWA&<7VQ#2_8C_;PbgC zwxRg?eXeLi+KJQ@Kz_?}m8YnRzm9>Q3rpN)z-Ek)IWd13Q7}x2ciOm@!~VBQBQFK~2b{Lu zUdPt3XHz`Dvou!N&u2BQi@rC0@sN}&e#s)7|u}vSXgcmq zl(R>YVyxsC5M<3$I!z_UZ6dp;hle~#J(o2j%(Rj~KFfUPjIK@C8_?JMM=W3p)hro87 z^l_?ax9U&ZR1fSX=RM8|UNA^s(@W4W$BI5y_%P@>f%Pg@c9zEYUUOZk{#dE}Sgi(6 zZn5m=I^JxB@4%}`oJ4)1)L<}*LDD6y23IgItBRi?ik{LGK1uLEqVgQNVYKkDQSqTk zjT9GJQm}tQsQi*7?vdL21bG)jRV^}70{EO#e@3fe&Vq=FZU88a&H&QUE08asw3jIA z0!yDauxHHNheign|4$L3hl!%?+TyK@a3doCOQ)FPHFV(wxnNv7e~2pR;e<;x^H*t# zHd*QY0mtKB`#z6-Z_u+X;My4V%q09XWq9;U0C07pCNeUR*|e|YiPu-}eQ9`d*P`~p zxGzh}jDL{m{zGLdplwplreY8|IVH`hSx!Sy61_pm>Qo>qYfyryU~-_G%`J7*54smk z2iiA)tDcsP9vt%XQ~M1OoJ+TE4Dr9jqrV<3b+vAB=imKBd&0{ei=oU%YTC3dTs7rQ z^jkwKjNT>e+!Ksf_`k;-IXzV=Z*|%?2aMqDH5o^3)`{p>m-E$S{k53@7+ar>)MbM} zZN|qV>*bO2RhId(2~RR=FA12yQlFd7Bj9C2eqAJJCKsw!2k7Em#JtVw2e)Ydw1+Ev$|OMt5<=^5WA~4e93`;?DCgrU zqyC&`ztpgIRMagMd0oTfrkcE|(!eh2a}D*GnolwzO8GHKoKPv?ngif%{tZmn8mnP()GPVR=s|oc4p#$a`Uq zc1g!VH1(X0J858HX$0GympKiTtM_P%!P3pNa6JMkD_F}2C+K1X(h;&?Si7K)Ea)>x z7OUs2P!&wu>4$^PT|V1(pM6)U4=kOEc_tISiIi_mIy94wf~ae1OD9IEH$Jj_+rCvj ztLxJZ4og_AG!!mS{@)V1P|gT7oRre5SpD2v&!}ix4x;Mx3bZsyM$YIJq*1DKD?rrp z4rjxVXYovM(ME99yKu8_;ieFlpxQQv=MZe&648M=p>Dcss{W zcWo8`lU?=Y{1Q}o+Eo^F;JFWbIrQkz{ct)6H|}lSl*h~X{9GWY4@QjP5^DtYTFir^ z*UEskv(&e%Hupkx?ocdxHXOQOG-KfhQ3YibY{DRVADqL`YVzb0l&| zj6wM}CZ+p?(cNKmH=)x@vtTTw+HX<18=USEr#nd#Z>wZ4$cvt#L};+{-a0zreolav z=03XU09o)9KVpC>r2K?Vg|Pz0zIf0vBS2978Z!c|<||SI*J-$1ea7-8>5yu_p`SD0 zGcuQqy7NZ;X#+|p{b4=*s)2ltQ=xmmOH;f>Q?!vRUdIa8vc(guV3aK$rV9tDqJC{b zAF-gDC|F4g7O5WUqJ$g##yxT0){uRj-@38HwJz?POnO%*yyN&x1*bESP1(}5HKko0 zv1NT_ZJmi|*2GxFGNu6hl(SM5r&O~Ff>pA5!eFFuXUDQ~trjcyA`lhVOj=rodP-}M zphM-)F~1RY@g{K92cm+XSb}QX9BkhjXxrj%-Q=E&r94ZQ> z(6M2Hi;`5Sr8J}ucxjK51W^Gy;G*nq+TmfGUe@8)yL|dkz#NANo6lSqvaE`G*Ohvn zjCf8bqZl*-Ah^}I+=%ck{1ndm0Ez+rn8vr!!QEppA>pfzW~fcpZ{OL6P1&L zsBnDP!wNQ%f0|VPVIB3ST}HtZX30UL>`hMg79qlI;1PKdECBH4B5Zy|=F1346P~4zz0zJaQy-hz^Csq`k^4~39^sfb zb<{JgY9B4zO^UV>#T&InGo)ZGEkG0<;{+qDaEKN3(M7#fagVl;XDP9uLp8rcQ!rps zZj4&DmAYpF=E;C%UBWXR_adB5rh>p!GO{ie-Iy#{T^?;Hx0Yl%S6I#2#e`m{!ty-i*~tmk$@%YH{!ss%1yUhHB&AfPNY8y`>)xo*BKf~<9S8} zl^)#Mzoeaqji!?%?_iFW{_pWG6wUvVCn_U9NK0Y&11@c%=C4uxKhxR=cj$}uQ1hQ= z1Sqx8KSx^?ml~IlN$RpFG6B?9FA)MbK112{96GLM9R^#U zGa3Ma^b-~`gX)_)%{7At3T78Ayx#;)U*FNwuQ9|+q~>W#wOcFMgb=DJnkI@s(KW1a zj1~-#g~Ob1fED$z!X8%8MHh9F1uKX`V3}fm4=EhClk3CgseozB!%c>)n=;|GrJkv{ zZzdU9pN_0gmuyIttdB>=p+O#Ftlnb6@E~a{)Y;J*RU?*4v{D7B(CP@2m9@L{4kv?i zX`J{mbRkCYASzav_$yJJ97M$pb)KlmQS(nfBI#tOZPy?H`V(@ zRnLLSjy#z>B+3it(4qUg95CsEjHMsJ_L2|B|{ zegl4z2O9pbDvJ+lrSMFDj23Lx&YRKvah>+Tt<=0HjYv~PuMmPmYIynKo=AJktpCzs z{oG>x-0Fa`$_L;ip?IE@KdqJSQ;RTqm?NijCn?!NiPzJjX;w7Fiq>Jc*gE#gcxYTYY!T32MN&|q~u*%b&OSi%n=w6+(OUFsD)R{H4}k*fsYKD ziw+LX+DD8eDyC;Ovi&N_UWIUn68~{YrWoN`N;E<96dh&+LyQO%MH^}*S=>qef)!-Z zGNQ0UwP2~_Ph&>)2ETdQYh3LytPNVHqpsB<`^HoVSR3_DMm!r5(RH!#Olf4g25#UQ zXHaN#7n|H-okONIh?JZ}tykdPcLdCdvOsCl<@M9hM>QIYIIaLksreiggQzCFAag|3*|Y#>B}_KbXx1343WrDIb;?7=qRtTg^5XIjDq~l( zywLrp4*M;G4qW92h@>1l?I-3go=)l{n2?@eMED7o+tD&borU}8-+vxwq#x)ts6<{f zX`xQJgP6Zw@c^(z`M_hE`Og!@*zP!O#OTTE35vJ*<)L zP>VNd#Z$C&oD+{S;$cQKNDKQJA)@FiR@}u1I~lA zMZ3{wUhCG6yL4-UmZ^wyGGw0)yEexB8>9XWC4sH!*i30?b=W^z5lNS7Vii=T-jt{| zIU@vN7N`wE)}i*t?D6toraDrZvblU(lU1nK&u4L#Lh}(7Pk+AZ*XTrfqE;?<=ZT79 z3RQnTM+H&aclz6Q@SP}>`6!?ujo$farh9+IioLm(&C!Z+S9;I_mR3#pfQm8y|6ih_ z!=FUIlt(80uS5k`{|k5mH|G2e*}48e&W9WzmvY2Q%;AvE>t-EJ$^u$i2|#ZnbQXd$ zYjjo(t&^DS3a49T)fYqzMg1xB3yZSPmAWoeCcdsJzZVIAYIEGRJ3cpAVEu_!5;jF~ zf``weyt0`9i+ude2+3bINdvGT@|EdMA z8I?!OT6mD%^w>W0*um0IY^LiLoTV5~n~f-8o?#SwS=lb5VyjiX(W+W!QB9fEYfQ>f zqkO<1?={N0jM7yGDVPHajnI6?IL3;AJayOWr5jnv7Dlw46e7cfVc&jQ3g*8|NqGYo zh-K+i@9I_W8r6r5szXNgK}HOVH&je}w4&{VXbU0UsFlvpvI#~u%!-E?Nk1d*rA0jq zk8W1Hk`XOugv%N6QcAdl6fD*jFCqj>)P=*0V#da<_nB6^xM2r7;Ww=fJElU;DZg`5 z#J?#V+*}ggoK8%~qZ7%%nohiE?j^20qzqB}R8;m&r zK|=}aA^`ktv0;Lg;5ZHM8#RC{(YZrW4MG+V9Xy+u(?XYXH;mjBBX_}S`p~R@U8jA5k?-Q9TTJo|Hr0%iSZ!60TUDbb z)qqLSYml!rNLLu7oq942B8QC62 zzMqyoLGp}!nwHK%{1hd6k`z9s6`+m3oe*pxgzL1TDN?eQlC5Ut!>km4%|1rFiV}9y zLX`6>X(3qJNsGbKWphMrCxr`%;x?^du|_a%A*UQ1!s)1k9&)l{e#>;ky&>XRAM|XA z1U3f!GhzSwRBSR6o2)I{&{aP((>gF!y|}kDUaL2UM0&q4kYy{{f>n#6sXDhW#+f|| zy;Y<$2_QPna7D;bX-1-@qPL>6ulf;DLDb(DQ!QHp3wQckwtE3g^Ldl0{V1Ty z7Vk_Vmg2=v_E{j9RD61*qUQ|Mg?RMa`kKE~Rox9mKX>}R@CIO3d)CHcI(by5#x>9x3w_?sePq{t z>@osZT_)g~+YG=B=Z4#QHyrvr61g1?T?zRwhCRULsOLu1cf;ej>9pOpf}(~yCIkOz zHQlgTK6cuUS`4po+9z4%9-VTNNimIBYFAHKc$SVBRsDK-uTIgUldsgtfNn2)TukZKotVD9KJ*yo(Ye*zV>-u5bq_*h-== zQH;8N4J90>#UnI0FX^Wxy);-VLW#7J6s**WI!VzAO0=95FQX(Kv}6e>TBs4WXaozj zqD7Qw+`&vZ*%2q#?_>t>`iE@OrC$Eg4|=yogBwGE>5|}7Ha=Wl+EKKiX3uDnUxnN7b3sAS#}I zPZ^n6Y{O&<4Sz(`d@+T!6J7#+o40AZr*&6g>0@!8rH^IXw#DkEgNZ&PVrg#JiEvu8 z8o)`l3+Gf7gMs)8XK0b>-x2k{aPK!B=Aw<|@n2EWSYFat5#mu9{000kBmB?HV|n~W z)co%RU2C!da1|rec-S2F>b)+;?V!L_t4U=r$~e2!WRnCLXQ>^y<#61zJFhq#m+W@f1AXMMz;*Pp&4gU^j?wg~$@sa+^qJWNu3k6l zE*te%opy9DQFK4WsUFd*HW}noM){;!HEvLj7!<=g#UQKbXXUFH1<=Ft=;jpNtcw5S zAPD2 z^H_;vD(2l#>YMiQPydFJ5E@gHRVmD@t4nOzGP~6;(fI^=f3Yj2ggReCSFozX4M|CF zMr#O42y3C%BIF?AXHoNAQ$_;qlz$;Awo;u*O>&_Lnmlc5eJG~T@JH33Cu-AHPs>h! z`@_+W$5LQv`_3d-njLk-SDB!anrA7r{-BhO<0(k`=lXrI<&I#x@qdq~<>5K{{hp%! z#!A5ZEATxy$H_chOF-1793OH);CyQff5+;KzdY#%S7SkAULDS5C$Mm6G)q~V2#I=$ zLA2aP?Fo3EbvT}<*ca8*yJqVlqv3tG^ICcK+l8&)HMM?`tGW|UT@L!rdn_j{dh8M5 z^ORMG!sobwI%C#j&IldI^Ap~0qp2-S)W;CK+!#oJ{%F9;UF_wLeP(6blluo^cQ%rO6wR*)ED;s0vqqJg#k`I%L zAyPF=sRw9v535?q0qVI=d{N*_CoAW{NxN8S7cE&yi4hFD2qDl%Nr53sGD1l~+O>>y z9V=bWNv5cLgH$-m2*Fam@5G2uF(HulkYfD7l^Q{(x_CJc;WCYIu~M*v5HBGmZG@;r z1)>VuX<3IsH5xDt`t+-OTyM}YP+}X2IafzrYv*#*4H4gT#J@IGGFqKzPPzhat<|kC z`sD5eRa#?)g+$FVf8}ydNu$o5mKjSVTE_x~;UVmuayAWXp-7I<(kjgQk)tA_;_26$ zHHfHSvMr{>l7DWcsb#f$;W}@gsL<`lJ!#AKz(RiQq!iaB?YrXj8$#vduH=BVY|xP% zc2)}k<}4rw$EF-%pPbn{O=PLQ8Y4#d?5WjQS;w_CFzwXo zhCOVz!@}c}s_Lt;w99_dYC_OEVb-0on*e;l+UH3NhX4zW=yO&h@=UPwirET& zUelYe8!XpM*6UX5O}qVu&4wQSO`RU4*_Q@0jLbgcbTD4IW65nDLb6f0Y;SB{{lq2)YC#jsX2s#T4U>S0FHLo2%&9-S;O$IrP>ggZRVowO8K z$w+vBu9UcomUUCI9<6khR@_er2QS3mmsv zfm1fiS%>wU%>;g)FtaCZ?E4n-11ojZ$|B4nu3j{mA+UdqGs8~zy4eEUuvmecHVbgu zYPoGT6UOH=}4HdTb=MJnM!Mu-p;sHY^F zrxLZ(h((1kp{-O_i!!rGnU#>vZl(l4G$EhUKxHKq8BHqTQipa`wtZE$^WmWFk)ZuC zzkOZ6`Aop|Y|#C5jt7T%uF3N*FAFpj*<&HKCro1(NzIa2DG+V2hiXj0xZYFBI$}yw zP)eI;DY(DL)PJGa*&0rwH!Agd3bQDf^pi6}g<6CbDx(#%I+4~W&{*bV7qKPH*7}Eo zE$c(g&yp5D8H(NzYI`Mj$-5O0uJ$W^)CG4BTUxl%hO>N2aahWuIOErg005>H(Bl1~ zLrT_=@QTCC5r(UJA%wh22!Nug_npNel%&m;iwPQ1XM(lk7^{#HIiip*%G~c z38z3fxZ_5SA~M#5`>S^~{y#Jt)W z5s^v^wW>rdG`ze3YNWEDTIsANS^z%lQlR45NDG$Oxs^f3s%-Zo0q0|W=emIV8NcV* zfEStmqdprLUY6%th|#`ke^sr!vMB&VTG;A|*4zA*I(La0yGmX8YFn5#`4t+gP^HfR zrL;OjgDrJ>8OLF7okXFQ$XSV!#TWppsbY;z#2EyfIWv&Q6ei5I9l^%OgN;vTVoq%htFn9`gcMKueCHUg;=U>P9BzsAc}$ zpf;7~G!*$01^z@)u&E-}5YMkGk5!e1D@!Adb;S$kRWDgsvvhv-g0|Ae>TpG|Gbcx5 zwTevK9FI|ytrv$>a|-CpI<35(mb5X_C9HC_Uj3BA_>$lGcGUktUhwO}*rpusmv+lH zCf#nc@u1BFcmK0qjiKVhM$J((cigH!X*D6#Bz~U=0V>gXiy5qvwyebjT`(J=^Jd*S z6Ne+#d0~CRqCaTS?KEmW=ag@#rO&8@nC&D4>Sasy(j}Y>xzY-?6riq#MO70}c}i2c z4?&bSsywClBYM9@X=y@s|9^bz{?0-DsTb<`$Qs`?f^)^%o8k$3O?Xk-C zP@uvHJ}oiI9FkkYlr79)OOz$3(m5m=vykC3X*N@>5y7Zp2PgtmjHxKKGCXHM<;WSo zT2qE6qD1uocTd+ng6&ZOfZFzIsP)yzg4c`NHx$=D69JRplUMFC6H2B4l{c#R6xMjB zV1+$zvD4pVw8mBcZcyRz8%lCOX>Cz9%2st{xpftJHI)U>yw>VRR?b`hM8~shJDz%c z$(rTOix5tKAJJ7 z>a2fkOVgl&Pk{OhqAD?*J17OBywa4;Rg1wVFWAyFr7)yCs4%2evRSpt3_OABBC7_L z^KqZ^3BPM?(6cVv3q;pN{Ez1b))WL+m4xPF&yc<& zBArKW3eeV|+Lp~4-3qk+)du)?0fS*btw^O2BI~EMa!RYDSOr)`e+u+!(C#;6Vyq=x z!C{7~=3zHLMaqvmCFi}7yYP*Y=I8TZHi0PkydPBFsDf2cnlh)hf)&o(MNV&n-cm_d zl>~TImj!`7PL2ZENNf& z#KW&`c;>ygU;g0Tm*0Eqg*P{>f8npI7c8tTtIYNVbv7r40hC6I48p?Y);LkcGAqrT z#J~s)be5jVv?}I=5TO}WPx|by`COkkY};&({T9bjqvg2Xh&%{=C0t|%0@EUVBIP$* zVPkoE@gxNSD-tfl2`hKpqD>1gaVH?IT03ab?l3YRb8^%?k(fWK5u<$Cp%X9TM9WY{ zW5wX}VN&NLpx*ECQSkh&EnTdZrnQKH*_7frpMjT`%p;VF=hCA2YAH02k<3*SwJ~C- zRV{9&#Z8n5YE%jv6oPtr7L-tA)kxavr0Ax&q~?s8Y*kCnMK~T)=NTD^z_$- zd{0LFkH&&4@&XHE*oy9}&2<)pjIpRWR%rLd3_6!wjsCtxq%dYF4Ouw+TzgauyWl9a*@M`V%1-Dosc zs{Y-eqGMHGp4(WN4_jJWp5L5^uk2W~e%<5mzWLghpMAV*$CkajckJD@^@r`>Z2$VR zuQ$H;*2`-jS>9Y(mV+Txt3$M$GL^kJ(--u^&%pUH95<~(7w!nB^Tnqe)Wb8zcs0}pD7QY)%eyZ|aFJ!wUK0967l zPLn=jfg#mmeN3l1u4hoB-ECs99p-JV9IZKv9I?#*XFpN2>Vt?y&W;%qWnNhK2A|^7e}n&Y@%Q>M`Bao}*az?2jlHoXL zQmrDOW}4h$Um;!4Vy<54L5$k|DkzP$zfSJ+tz6>+rO}0k{G}Ek3V~ISdB0MW0$^uo zzQb9sH&ihHUQkJzABG{VEzhlu7q&IlJhE!ptFOHH>8Bs>{C@k3`UtmB57jSS+N^7T4!DCGdmQ$)(Iir%} zXjz>`Zee8srL>Gztg+cY%P-nfT)r=odmxZ~*ylU$b)E7!&pK`A?PjD)7fB#GV^LA9 zf{{?pDBZ_CKOpJtYEE5{4dZrXe=m`RIV3DIiW};kx()z zC6m$QY`v6G6{&R@I(wEYhO)n@YK0ru_~Q0+P}=fxIR1nmb}}?iA6a0`TVmx^und<> zIn%-yKzNgYI@jT>)$5D@&91*R+!!ycj~CU&OIn+1R0X1z)K`F?D zA>~0Wlg_G;&jF}-&O=ZHP<@UkgU&}oo)uBwf?Quy9y!%BH^+asDx5RKw+PhMX7Z%oQnagv{f!M5Ksk_NTiTRlu{`<3`&aW z6r@^eU6#g@>4+#|4Tkt~PvcYJxf}A^UWsDz1i@!?p(%SV$AcPMWQOvWq6|eqUlUNE<%{^_Tl{N$65cJ2P* z%(=7OcX|f~hlfYTCMTzpPJ>qmzG*_ zW{cS_HrXV|un?wNHF6Uru_|N^hB0Uu9OrIT(Jo3^VX;14U9fGPN+`x%M&lFWmySI+{nlpRMJ|7FfPl4 zs^nP}k~!71s9cs&ApA?QWLA;*p;FnL7LGzDwbt)Kd8#AmT#UH1C{P)50BijTj{+6q+DPCC34|6s1s5QXE1qrNm;ONM(r_GMGvs^s-TE2c@zp6ef{WC(2Z0 z31lLnOeB&E6-qHG{|Hk7D#gt*2c?lZQ`Pcd%QFS-uM{=E6v0K4h)bjM%{gs)C^FBK zyU?1q$cAU(QfKK3FN8(@VtdgtS8<2CaET|o$z?4!YNLM+R3QB)L5+dZhWeU^SFL#K ztv7b;{QkrlLg~oFZ?a%_33Lxv z4re=nRSe;uGic7Hi2cc^-ezJyGf=Ow(x+6y-vL!aVu1TWg(3YTP#3Z?XaOq&rEMBQ zX^UFg%t-20e}^b2$XsRO0;jI@pxS1SYnwL+d*CY@8R$ONB-q6dK}p1`${ zQ+7BltAp;<(cqG(uQ}{051Io`HK!A+4N}S=0i|*dppv<0)I!k`r5OcHD`4lS3-vv3ZiN-acXfY!}12jr1DOV#pF z>$50Hm7>BQU+ahc1fM*p;dWzefrS@v1)LBl#TvL0E%XEvPHT~o&G~nMT3-={>MC<9 z%8TYNocG)d&u{!{(}BZBu65lS9Ge_ZCMS}~NdP*X0(BZoyn(j|rzdZWkDc%BJAC>2 zt|O$H7bXvv&z-yBsdd{o zescEUkKN~vj$S*R?7N=4bfWv+SGQJ_d}cE5w!6-TW2d5_pMCCqR^xt)5yX;&%WOVv zG6PrGRUTK^RqQ&!2~o#W0V-ltxPCObwwpB@jr8jp+0%>&6L)L0k`)}ur1>$OBFU^WMP`0#(PGvt_B%Vm{w1+MV~(THsq>j=okpmjNTMWR341cF z_}8E^6znQMg=DluLW|-30jh)*%5)+aRobEes1RdSVn>x+EyEoU0@)m~WR6rmM~M(Z zok4N4%>iXB;jCSm+x}c-`^%MePv;h`c7f7Jn<=MR4~1Ke(YfYWy9LUfXDwLhC|c~o zlV21ra^|+XycKpsL{GVu|GMAjzcTIp|H$?8i1N=wJg=seRL-hB7Huea_vbo|uy z+r0x5Q$uj|_gI~ro|u{*o1Pj?PLCv$1EW)&gHspojGXH1KX|@t=fN{ye6{0+*FSi8 z+3JeQgxeFKtagdrsdPEib~9tv(|)VDrnu;_j%9DX_`;@7KKyC-_ZQC`>+U>1a_4$- ztT#E_lRWwJ(8dq1KJoaE<>jB6jo)Xxe++r|1RXo=hCO!UQIGRDrUi7|5srg(J+9+U z>2;uV22{+W;w)=`YSQkv=(bz9jRxiot@2q`_M}F7AE@Gg3hKQ90C}3#1uOxTM--GM z7(yu!MOmqe%BrRXysA`!`;}m2Fr+m~ArP%mi6MXrL@Sh8C9*jMq6hITm1o2<|2G!% zy_Syr@Z3nS+G~rL)DDeYuNGn0Nu?1XZxX9B<*W#P9~FDjT4J#830->yD20&4%T-c2 zBbG8E2%w790*O`tR+UC6SY_>$#-UxW5{=o55S8whl z@yV&7@yWYmW4DJ#yN8oE2a?zNrY_$ZJKZ&St zymYqf?Ki%vE_=(Z-xxG+&-L!XCDhrDttgP{*?qWdSFb&&=ML+1NA!C1_wPxILF*$1 z%^{0^uSNfziTgy)yv8Y?)yfH|8rcf1v_p%UzZ7FpsfoV(oA{#pJ57r;n4uy{d3?ou zwH!id3O^3>2=*Yj^(sop3mjIdh~oDNFKZcD6$Lnjaiyr5mQ>M_3Wcy#npq~xDwSsy zN#+ztiNcxxQA!CHhTN^OV2Ri6)u{}$NJ|M=24{(rA!jt`L8+1zqoV|&Q;)8_f+pvm zq!9(BGBpn>as4x_vO+mW>?(3AjSahpRBEFVKSx5%k;n+BQu#wt<%2TyLueC}wnf_4 z)-HOfx#`(>{_=pcQR{2q0`-5V>_$BlX*K7~vllFILPd+*P;R>|SZ6T=b(D$8!heMS zQc!tA3Pc;@Q3#;c)h8A#U-k5huYK_4rdgM3&^?|XA{ljOwZXGyv^6MXVz5UszPpy5jxgzfK_*v|*wtBQS zpV1k#Em+v{%1h7e+`9SX&-*VNJKA~f>_AT!^0I-xp6Q9fWO6t;aW^^8oxFWLdF4#< z$ev?smws6uc*CXM7_x4SI=`}MzS7ZqoaQ|y4wL+t!a8KsV^DBL1}!MX#Na`*;RmyB zvqAg5R`m+2d{(1)l9i`GC37h$PzkPJHC-hWjZ{P44F zKOQ)G;mY;C{=Uh{{>h1<>9Nt|$ar#iGTA>qb!&9&#_-6E;o#MtfRWM6XXZgLE!^{4Ll)@^Ety%#Zm9I|W*TEF%f zwmA(uZMxkS-9C#R^ZW6(xrBK19n^LSBHDhqGEGg+M8u zHLSc&tBk88wHgJiC=hKhspq*(tqy&?$85q0QIrVzII8g~7DXqKRFNf93J94gIFbI` zQ-++*5Yux+3@M-DnSv8*A}N!ZT97IhJ_~eHVFPIg;3z8AC_#3H!W2#~hwB&1ACxh( z9U)y=TV7&iymDn}WPXmL-l8j4+2gFc8hnCMEf$ccM&qmFLe1vbTzlR;SX4K1sQme^ zK)v2pgzF@62`jGcnf0FlmGoFkG3rmorxRt7ba|?-B9y2M*T*9mk*crC2c?OcirR)| zfV$$*b#H(C`Of`^k6*mpdFSpRy#Lhr$kf=_G(a5$sFTUNlgT?%(|r@8z0>0$sy8`) zJ2}>s?7!H1>8JAtH|^N?(i_ipENUw)E%HWl-39n_+v^uSy!h>p-uQOMmnTpD+|zkw z{LY=^;9zoSWO{IDYGh=5Yy>qgSnTns!NHL`BV%`xlfB9Q%gO#r<9j!6>1e_c)*poI zn?ladEbMltez#4Jp8h@yOsjUUQM1R${%Bx-wsHq-+#VaZ#l(KZp*AIZmX)vPs7JNR zm7HQZ(&~Gl^5gyYK$W6>f4@cLi&4BG1)^<~7($x~e!rHPVYQkO^GbtyKdv*TRf*74 znqU>RYIzMKt5Hi5oT9;`s?#eQ%xt+vR;HCL2sf>G5$SUBU1yP80o(`1RX z+L1lw&2twl@aE3-cxw!%JXXdja0$x)_s~OC72!W6Oz5Q)#Sj#_qKOJJwg*1r#on5V zV0~@0p$=D3=T}ygv@|t$EPr^-lTSUn;kEZSe);{LeJ9Ud?7DqtXn1sVd~9-hYMLbb z<5Sba<5T@(lXvk%3@|p{KR(`%cy)5T2Ni&^kqced_Z>g>)i+P zb-7(Vx5&4oHviFiHIFZCz?ruwZ1M$C1f0C!)`@4Qg^-*gO(>uXfMID#H%cKCDTV1L z7Q7@%5x)@01<=g=G6xLrFKhHqt8(p zBb1|zb5(GzN-gB9&^Rm9?l|YG(S;gqu~t|9Twg)Ezo0!BY4X}jb*ztiNRl}#OY~rd z;7?JS{^FXl7`mc$W%-HnJi=;axVk)0Qk<+`U|eD~uoHtpDn zeE)K1*WLcX@d=bnlh8C=Gis*s`y*-||~O^%}l$>vp(wyPVqZ&8jV0#a11) z%c|aGrFS~%ZEp1!4*DG{^@2&Z&P+XOqnDfMr6$!9BfUtk3|0nB+nH`71=zl=7^S-qTFOlm`_+{*EL{ zG2TbLG%fOFlo%~kv05h8$`yKwGV)TOEPx)X$D5IaYgw)Pby|Y~B zs?Y;hN14W6rgoIGAU3<+5^V;kfr9p&yw;qYgwK@EQ4ZxSsc^PH@=&HI&EB6{{1((i zRj9T)hX=K`wyeFqef?9sC=C&@Zeq>$8tM9)2 z@s}SR_<7%j3+H-!Z;y@+r}>{7d|j42|OtP8DxQhm+%o6M9DX?>M<(?b9yJ zTLHs+F7>;5=_VWdbIfxv$MKy`zROJSwySr#v|l^e_l@)ho%~q?z0S%$Y-Bo&%o3w& zp@CYUS1#Zbyijq1kj|%@P3Sj4C_|++Q!+)pR7pSugkTR(KuApJed!XiByh{eqVV-l z9jic4TCJ8;X{5C}S&c~nN-Hh0N(WsRHq^vyZ8hPCmnPOfxp3LigvClB5amti{d|H< zo>DyjMNoNqQ-ytjPzIw4ODjUDKT9dhqC`SQEM}!LPNvW+5LMD13Ri<;4Xl=!ewMd0$u+|)HbQiQ`7tRgmHs$!^E^UrVWDxzA zgIZr5uB!>v)kf+P1&vMB%a(V%^7=bpZ{4+X-=QS)Tu3d_I$AMvu9s_ea-r(7q5GI z*~_o2fB&O5zWVly?LTZgckWDA7gDf6PzpXtlPfv(N1&n$HgV6S5B1$1zTKG|>r0N` zO5V9}bK6IomexPx)4l1}e;spe_UgYdtF~IyICy-wmHok?+hWsxq-S2&D4yr2XN{W2 z^z165W|={~$iU9mGwph&O|P1(Q_a;Xc%k3aqLnvmWDrXF4XlJ$y;@w$AkHKOeB}5E zm8_nYB`CrwF_rgNtxJWVK(vw;^QvN`m1=2?j;iDon8mH+WK|}4wMAKJlb6|KWlpLp ztjAr4Ew$lQ%Ny1{xuCJB2puAXoxehqC-aX$O&iSLT>#Ov2($`erb3XR5M)w5>o*xi&Un|lIb&4Rx#&Qn4=m?f!0-Q0IsfL9nvLxq1sxg&aSpZ z8@= zYu|xmXRi0&<;(l<`v@6fPNzt33M&}d(UH-<-oBeRx-VYpJaggt@f$s7x_i&w?mK&{ z@AREJCvM(6bmr8y{rf)q{=0WKefipFA8+{Ti+6Wy{c`V*JC7Vac>46on>RcA`}@Yn zN8$0)pkn>I7M1*VOiZKFFg`pqIx;Ys97REQIypEs*`1ueHFWOBT`#TKQ0jlq#lG#< zeBsxB#5rI`6SKg??a>9NB&I(2{BefK{ zQl*h9GbqbUigL5E+@>sdP}pBqD%s=Jv(_j26*I!o| zt^ug9sP(ai=8~4ViH=n(Uw!Mn&D-`Izi{=|@aR2INzW9nKLsk@8=ssU92n~Exqap8 zjnn6^9zS>W@U^a^H*Ov8x_zSi*0G+Rqc=N$zIbNW(Sw_h9{gti?yr8@x%trE9Vd?* zymaY_iSbey9ITMBb zKjr$<2J^QIAetq~Op6eU#7Zdwt30SYtHRV^0Ez}^(JD}1)r*l>$#p2b3NaZ-Tg8k^ zuJ@^oIci%(W6#rh3XGm&bEv|Z-;iD2np@nQ8;u8TQ40nM9+ds(L7mC^?@Ol8& zaQ(I6+C;RrzM!tTYW~v2NcKP8wDs_ri(UPw5hX{bP~9Y)0@N|YhbeP9Hg@;!z|F3n z3s-NPy4ZQ*(#@mSx{lnqee~w7qc^$^!<^o@4kq`UJhb)9(VeFc@4j&Cr_S@I?p(V% z(A7PTdg<5%YEU4PclZC?q5{kryX*9O$@7dSrgbDz7lpS!rvUHZ=)`VTGK8#?uiEd5t4vzAjoqGLMr>IDXMn@Qbd zfi#T-)V~wnA#WPhjRvM(N2BJ6QhW`kgzB{vKy9YwyitX9O@msl5|=ZQGFDp7$;bHFI@9>5clxB)EAS?*CvMhN2ltmRF27pC{1XLDS#S<-8m{z_oKpUlGOiL${ z>4X@&QrqNOx6z^eMJec{X zE$SbE+E5ou)J1CQBJtYX%DU3#h4Y?#{>Aq`+r0P4$tyj5Ba=xaQ)6(*GoYep1W!FQ zI(nzC|9V%?`RiS$u6AP*;6&%GBVD(Tbl*O5^X5UA)0iNe&JthsKgaD3MN*`co<{<$XQB2C;wO`p1)FBM^dQ{4 z7aQny6V+-~wOD2lZQ*{+Dv1h=>IS_k!BJoplw#4q(Zr(Cay${NLd2G)V$n)g#v@v4 zR2G|*1qOM(UKTM*b8L#dYz_z1<9ZI5(A;b$H=E9nsB^uGL1v2_tMrJEm%cyAg?N?q&_#lIua=K7`=KiEB-%%zhp`Tb3}yIv^W3N zqPjBjyQ-~-5TQ0zk(VehsISP!Fog>0c;E17&*1RQzQL>AcQ4-PJ=HgS=63(Fo;!zc-8yo! z^YGP(Pj={q7H8bEnHjo^>LmCaESCV&6CvX1z)ynEO%3V)qt6z%f-!8DdmTh>^rGCk+ z#TgV&=wz!=MAeArv!Ygwutg_rF)C7VDc!17fz>v>8fw)su(2%$b(5aq1p^DyN+{)M zRGh#kQYQqZP?bg=*T_+{FVo2jIcd3#DYG#-TA`Pj<5A7lOaE6S!1}$k%OUZ(WH6!C z70!whb2vmtqnd(ZQ$tJcf@PKEbs?=oDrEj5<1)$22`lAGsd%QXYkKjk2p03t5QXZq#uQi?Z!7u4FS zNJD*YOggMVQN355Lgvqdid4OKWDF&#&c30` z-TmipA~fwi+}ZQfwHy07JNI9`y#M0qy`c2sv4fqbPTsn3VW_if{7!#zV1$4QypS3F z>y(mT6l8H@sqdV`Uxv7UQp!bK!c&XrWH>q2Pa0U0-P45ClgaLbr#C+PW?SBq`KG7x zjnC(spO2XSnyr7-Dqmw(tTxM6nB_}M@&!ieT!R#>BKIeVawq~2L>shJBS#ZTQvpC4 zQJ7QseLT_kgn=as9fgcOZlEd*N?1`KnrDy|+UP=u%B#(?(hu5H4{_9gxZMgIX+p*w z&6ysLG(S&QT4E|LF~(xr^0*V`v}Jx#wAg{$9&!9WZ4y%)Ie4EJi2bd8-439o*i-`X z#HOL;ivYh01Hfvglqf@z!3%33Dv)P^Re*{oSXE%(kO3!)az>|)wW=`9f=GZ5ToIgT z>@vNZa!1YCMJ`YpDGj>AF0BnaT4lsU%LQ3dA#hET`K!f029@-rQ0l*DQ2}bAE?S)k z*EGaxTT80js+$(ifAskm-rl%*+rC4`&R@CRKMYU-3Nc+k3%#KvGN6I+2~yY}9J$sz zcmd}0de7l2H}+n*{Qdd!J1$(G;prPM^Ge`Eq|}_t@>b(>$ec)MNOG zlYbUeWKYoeG)h>ho)!Kgh?g-XgI^u|6-P#rhzQ7AWc*-!^y+lqiRAFvWY3|C+unI^ zMfJ*DNWBv44N957J~|zRFi?8 zXXi-PpHi(3WXfweH0a4Qu2TX|A`@LGQ zVAtziTF#|Tm969o0|s2PC9Ai%4o;SL(u({{t=@5 z`@BU>gPN!$uD_-_f;5T;wWg)GsnZjjl|D;j zlH#@^#bV{im&}1L9Qmue^VtE4#@OW0!xTXVFyu({vfDNSi z@BkZCfVxV{utqgN)q7Y->!eU(B|8Llb0pks#H&UhYY&+mVT;*sWNoC&FH%c{G`1L! zO$0osX;%L+rT8pB#ZIW-2em#@-IN<|DJpNSsF~lo>e*-C+_>qx9}gZmd!@T~XmAXb z{**-}xexDd2d0yEC#HKw#;^AcUFf`X;>ykar_XIWe*EhrhrT{`c-KUj5YElDQF6l|u<7+)SfSQ)i>A zjj7JNMOp7)>YeHa7YkJwq-DmxQ>jT>Y?2pPseBtzZb}im66q35sNXKfVO*8vo+V2v zo11gPQN0sR-y_GSIUIP1J)QtX;ZR6xGKzFKSI2iO;pE|4SFVoS8AxJR00;tM$bw)Sr%~!6wv`N= z{0XBv)5aw~g9xNzDrOY*hlz>1DC(v*8h~Yzp`qwS`U4n3#GimMn!&qM!+pu=K{78e z4Kv$0*?X@4>Y*!#zdP{lyPv=Q#7hsiJl!RbZFryXbt68j87@sD}x8R6#cta8q8lG7w;@YqJ+Eizk|**)g5fE#qtg zP|Aa9c8V-c0YJ4oGTk20e3;Xg2*Az>vTg^i@uI92xkf9*A*m&kci~s`&s3Qoq<*=0i|NOj2E&kxlW25tXek>P<38fRKZ-+>$y=inoxOwSuk;)`e{~Pc>B0S<@7?w3zFl7&+Pm${k)OLR zT^+vNpBzqwkttBY&?I`VB&Nhq{d1sB!&rjARJ4rfVT4%HfuUsI!1SFV#HAz-K#>ZT z7UcjE0!)HR{7nhGOMDNAXo--YJkv8cK!5v-|nmE>FV!g}1@iEHa| z_Z$xK*6Nk4f##*wQ@rknc81S;pJMfDUOcX8R_}j#zoo^|6Ea$kef=PI23N5tODqyd z#E>ursz@e>gi;yOqAVs;tQS&t8SA07K3e0&ftE5zX%o{9soG6xJZiOzp=`87FBh_? zbj?`QvhpBQUXfiQk)au%BRU!gVh#AoRu0#uhFlRV3|8K?`>P1527}@C@UF<9&nU zm~p)|GTJ>ld}CrX)hw9mp1ONBIdSdQxgTD6vc1?(2aOp~yBNyz$e~=X0z!$NRO$Ux zUO*M{(K$W_3ixIab$OHykHYCyx`V3he1kux(K`gJb&kO;(m69tUXj@+wg+VHY?;F= zae73tT(-8xTUp^KEwmKIOhviY;yhb!$e8VgX;tCsXL3ZOQOOx7URpg3@qFSrL$8rm zr^M=+l+o=?G%^1PTV0NG64_lNv%_fRq9h z85z_=4^satL;D{xYnI9_#S|awQSwqbW$0L8t?^PCuZp%Su}?~*!2uUSvR_*%%&+to z#C=6^e{ofyv?f$h6OPwJs%oQ^@lX|%npQ=TKZR(lt}==R0s|yabyWq4%EFq;ysGkO zWqAl+AFm5nHsqEz6qGf_o0l*B>w6!5z30&3v)3+l_4SQRk(7E0Jt6#G9-YMAld+!h ziJr01&Vj!3y|+%^>N;`h!rl{yzdLp4yPvjwvgPx)wru>{&dpyO*tzTMk&|5)Z;WG4 zASPL0=ukG8CYVi3jbq4#_~^g?m|>DwKqxg#h$0kHBwld&7&b_K@ZKLu-WZ7@#wR9+ zrzQaP)a#I8If0!?NbCivY=P#hy28fx_p$~Lt$T-(@$ApMV&&e zbv9?8Wp-s+Jy~XNh9@d7giLOnTpHIxw%{{rpt>Ni*n5XwJ2)I4;iBY zF63ohR=LeAH5()bokY(`aaN>Grz96d>h4)r0}h}d)p%aO6{RFbuTo*eR5!CG3>z5o zDLr;b(a4E#;>^ib{Gbr8h`8%6GeC^wh-}!#imju*9C$62pHZd@bbbSWYR1^VLp}&Wey!ty( zfhaFRX=-E|ULPTD>Vway@GW>XLp7KkxjS_0`kiZM2X9;$M<#`E7&bg*$YD^C&JpzS zo5F)iersTA5xCw;PTfdOUmqR5hU_6<|nAlb#^)<5Ydh9^aT1z-%Os5HISvP#W3ao-sXMw?8WN;OkFtVb_X5>~$ zmXZ`^=ZI&gK`pEa0#x*fL1|SYR$UW?aMmtFD2>PJEA#5B(AH1A8PBVY!|DGWs1-Fi zWR;lt0r+I3+6iHqkudwPc_c~FsEV@4Vir-MT`?)G20)phF1#r+pf z?>=>O`=Py?_H6xV`xkF*`S|s3KY8=}FF)G9W829C2d|#G(0#Q#4JrvQQzcnYO8EKB z$1k7~gi@f+n9~_h$)MpRVHMvBR`L7=)T!~Y{#!RMp1OE^fA{%gWDf98f;u*G37}rP zxcAYA6F8JO=#cpo+^teSI_v=lue1VEa2`f5iO=uf)%!4rPEt# zHAFd;3!4%#o-Kk=y&qJV)AD+Rnz8Eo+}b*#L`_~@H8wyI;SAn}YII8py0EAKHFeA> zv8a{t2wZ%0k}Uv))%!sugWQM{rpCtyZg*ckbM^G0 z-Ycgk`g{HasFR(^scVztSCi9S0Cml(Iv&&rY0XyI{Bo;LW)Dgbj(S7#P#&FErinM(T9yS@KU2N#<K{i^|!xoP*KZ86H%fS*tbUbg*AQHAj`fYF%C%ITs}|--;blj&cJRV&x8n#2|)? zM|!0Xs$7LefSMh5`O0hnm2$|XEI9!KO|IX93QB7l@)Gs=b&0(C+I+CegW6bCkOsA; zG8az2x+1^2B9{jhaRNXsjOXy6E`H+i^{>7A`X`&e-+%nX#cSPnN65Jo6Jz~j{k{EN zUAHe@y@u0$_8vX7ZU5e{_U`&@=hhFlZhHIMjj!+9`tjkNU!6Jl{q<9a?p(b*dZ#xv ze3IlrB?gkD-iUMws3dOu&Bu&Irpd{x)05Ye$sV|VSk!A0M+YIx@~f=O%ZU?VJ{Q)v!E0f6^RupS6oY-wy53;Hq@ZYZq)@^^u9X1rC7`ODUn$$&}Ip= znNnO_WAG5OrS;BUX*n_~&O4JJ#G T$7i<%YK@k-Z8yma3ut8V^ML@ysKH($N4$9v9w z{=4@+Uk|%8znT59^O@hsV1Hk~cyUt1fjMVq#DJS+)Bf_qR+NvyGGyPkAFpTM_`|ya z=6`^@?RWy){DW-!iyW*QVU>(Vn9j7%Z-2L)hP*MXTmSm)>__$fzb@c!^bRp!V>R1_ z+SgOGZT;AGHzXm_7ncOE*(wx&-_`lzjY4l z@-o=|CpOrh8{03i-^QQoG0N*7hfFj5XY0}Y8*OtS#5>R!7H0fqJ-S$~+cf^mYW(wh z{P`Ee@-=>Y`P23Od|u2?i}T;#BbjN2U%#K$=WnDM__qQE#R-`HbSg%`QE>t>6ekc< zaRN??6Nsfa0cXVt#8#X@9K{L5Rh)o};soL;PQX=h0`V0m;HEf%1d0<#s5pT{iW5kz zIDsUJ6G*B!fnWUxP@F(Y#R;TRoIq;D38Yb+Kw8BKcqmRFo#F)2D^4JT z;si1(P9T%w1Trg5AdBJzvMNp>o8knrD^4JX;skOkP9T@!1ad1*Adlh%@+wXspW+1a zD^8$*;sgpRPN0zD1PUuoporoGJQXKURB-~u6emzzaRMb2Cs0yx0;LouP+D;UUWya& zR-8Z?#R>Q*PQX`j0!GCN_$f}Htl|Xx6(gegv-vf>1)C{CcN;smNGPN2Ht1ZpTwpr+ykYAH^jw&DcpC{CcR z;soj`PN2Tx1R5w#prPUf8Yxa7TyX-86(FMoIsS~1bQn@ppW7N`YKMKpW+1iD^6g5;sgdNPGFGY1O_WkV2I)bhAK{A znBoM6D^6g9;si!2PGFSc1V$@PV2t7f#wt!=oZP6en<9aRN6KCva170=E<=a9eQ#cN8aZS8)RO z6en< zzQn|5Cwz*9kIwiI8}H-bU0l3%!JBw^?TT0N@zM=165x44JWGV9iSZ-}9w)`4WO(R~ z2gz|i1@5K9-Bh@f8n@HnR$AQjz>Rdco*vgS;A%!($%M<9aVZNfX2peUIG-Koa^P%E zoXLgLxp68FPUgjld^nyT#|q$RK^!TB!-a9E2%qPlSX>p0s$pSuEU1C`H8HOi=GMlXI+$G-v+7}HeavWp=?yWh5vGP?N@Glpz@#Ra z*c20*VSICpYk{#XF{Twpx5lV87}*vh+F^Km42#6j4j9rAgF9hRXAJCu0bS9*8~Sxe z-yZ1G6TN#ODhj=Nqh}xV=!@?C(5*kZ4nUWI=sXCW2BYH;bQp@rVQ4=b?M9&ONVFM+ z)}zsC3|fvwi*aZ^9?d48=|nV{gow##JO$xX(P$bPPDg_os6P|+W})tE)R}|Yb5Uy^ zYR*TE1*pCd)fS=ZVpLgz%1aTp457}L3FfpIH*x4~yS%ItvmPI&D?>D?%`2POBS#6A??k75T<^dLN=QREN`A4Z`gD0mbF zjv@bXubb&1DCgm h`wns5BlZV4e?+WLaQcjxUl8Lf9KXTgI}AU7zW{0vzm)(0 diff --git a/hl/tools/gif2h5/testfiles/image1.gif b/hl/tools/gif2h5/testfiles/image1.gif deleted file mode 100644 index b90b23aa4c495ba04b1f0b3cbdbff8b4b74713b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9736 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 diff --git a/hl/tools/gif2h5/writehdf.c b/hl/tools/gif2h5/writehdf.c deleted file mode 100644 index 8f0cc0d6182..00000000000 --- a/hl/tools/gif2h5/writehdf.c +++ /dev/null @@ -1,115 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by The HDF Group. * - * All rights reserved. * - * * - * This file is part of HDF5. The full HDF5 copyright notice, including * - * terms governing use, modification, and redistribution, is contained in * - * the COPYING file, which can be found at the root of the source code * - * distribution tree, or in https://www.hdfgroup.org/licenses. * - * If you do not have access to either file, you may request a copy from * - * help@hdfgroup.org. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include -#include -#include - -#include "gif.h" -#include "H5IMpublic.h" - -#define PAL_NAME "global" - -/*------------------------------------------------------------------------- - * Function: WriteHDF - * - * Purpose: Write the GIF image with the HDF5 Image API - * - *------------------------------------------------------------------------- - */ - -int -WriteHDF(GIFTOMEM GifMemoryStruct, char *HDFName) -{ - GIFHEAD gifHead; /* GIF Header structure */ - GIFIMAGEDESC *gifImageDesc; /* Logical Image Descriptor struct */ - int has_pal = 0; - - long ImageCount; /* number of images */ -#ifdef UNUSED - long CommentCount, /* number of comments */ - ApplicationCount, /* number of application extensions */ - PlainTextCount; /* number of plain text extensions */ -#endif /* UNUSED */ - - char ImageName[256]; /* Image name for the Image */ - - /* H5 variables */ - hid_t file_id; /* H5 file id */ - - /* temp counter */ - int i; - - /* get the GIFMem stuff */ - gifHead = *(GifMemoryStruct.GifHeader); - - /* get some data from gifHead */ - ImageCount = gifHead.ImageCount; -#ifdef UNUSED - CommentCount = (GIFWORD)gifHead.CommentCount; - ApplicationCount = (GIFWORD)gifHead.ApplicationCount; - PlainTextCount = (GIFWORD)gifHead.PlainTextCount; -#endif /* UNUSED */ - - if ((file_id = H5Fcreate(HDFName, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0) { - /* error occurred opening the HDF File for write */ - fprintf(stderr, "HDF file could not be opened for writing\n"); - fprintf(stderr, - "NOTE: GIF file must be present in the same directory as the binary on UNIX systems.\n"); - exit(1); - } - - /* first create the global palette if there is one */ - if (gifHead.PackedField & 0x80) { /* global palette exists */ - hsize_t dims[2]; /* specify the dimensions of the palette */ - - /* size of the palette is tablesize (rows) X 3 (columns) */ - dims[0] = gifHead.TableSize; - dims[1] = 3; - - /* make a palette */ - if (H5IMmake_palette(file_id, PAL_NAME, dims, (unsigned char *)gifHead.HDFPalette) < 0) - return -1; - - has_pal = 1; - } - - for (i = 0; i < ImageCount; i++) { - hsize_t dims[2]; /* dimensions for the dataset */ - /* get the gifImageDesc */ - gifImageDesc = GifMemoryStruct.GifImageDesc[i]; - - /* set the dimensions */ - dims[0] = gifImageDesc->ImageHeight; - dims[1] = gifImageDesc->ImageWidth; - - /* create the image name */ - snprintf(ImageName, sizeof(ImageName), "Image%d", i); - - /* write image */ - if (H5IMmake_image_8bit(file_id, ImageName, dims[1], dims[0], (gifImageDesc->Image)) < 0) - return -1; - - /* attach the palette to the image dataset */ - if (has_pal) { - if (H5IMlink_palette(file_id, ImageName, PAL_NAME) < 0) - return -1; - } - } - - /* close the H5 file */ - if (H5Fclose(file_id) < 0) { - fprintf(stderr, "Could not close HDF5 file. Aborting...\n"); - return -1; - } - - return 0; -} diff --git a/release_docs/INSTALL_Autotools.txt b/release_docs/INSTALL_Autotools.txt index 325090aadd4..5a5f1fec31e 100644 --- a/release_docs/INSTALL_Autotools.txt +++ b/release_docs/INSTALL_Autotools.txt @@ -484,8 +484,6 @@ III. Full installation instructions for source distributions ./tools/misc/h5debug (low-level file debugging) ./tools/h5import/h5import (imports data to HDF5 file) ./tools/h5diff/h5diff (compares two HDF5 files) - ./tools/gifconv/h52gif (HDF5 to GIF converter) - ./tools/gifconv/gif2h5 (GIF to HDF5 converter) ======================================================================== diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 7f4571ef0df..5fabb8dafbe 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -116,8 +116,19 @@ New Features Tools: ------ - - + - Remove the high-level GIF tools + + The high-level GIF tools, h52gif and gif2h5, have unfixed CVE issues + (with no proof-of-concept files). They are not critical tools, are not + well maintained, and are an odd fit for building with the library. + Because of this, they have been removed. We may move them to a separate + repository in the future. + + This also removes the following configure options: + + Autotools: --(dis|en)able-hlgiftools + CMake: HDF5_BUILD_HL_GIF_TOOLS High-Level APIs: ---------------- diff --git a/src/H5build_settings.autotools.c.in b/src/H5build_settings.autotools.c.in index 67bd023b961..70eb34b8123 100644 --- a/src/H5build_settings.autotools.c.in +++ b/src/H5build_settings.autotools.c.in @@ -93,7 +93,6 @@ const char H5build_settings[]= "Dimension scales w/ new references: @DIMENSION_SCALES_WITH_NEW_REF@\n" " Build HDF5 Tests: @HDF5_TESTS@\n" " Build HDF5 Tools: @HDF5_TOOLS@\n" - " Build GIF Tools: @HDF5_HL_GIF_TOOLS@\n" " Threads: @THREADS@\n" " Threadsafety: @THREADSAFE@\n" " Default API mapping: @DEFAULT_API_VERSION@\n" diff --git a/src/libhdf5.settings.autotools.in b/src/libhdf5.settings.autotools.in index f04cca78e23..e7900a19dfc 100644 --- a/src/libhdf5.settings.autotools.in +++ b/src/libhdf5.settings.autotools.in @@ -75,7 +75,6 @@ Features: Dimension scales w/ new references: @DIMENSION_SCALES_WITH_NEW_REF@ Build HDF5 Tests: @HDF5_TESTS@ Build HDF5 Tools: @HDF5_TOOLS@ - Build GIF Tools: @HDF5_HL_GIF_TOOLS@ Threads: @THREADS@ Threadsafety: @THREADSAFE@ Default API mapping: @DEFAULT_API_VERSION@